/*H*****************************************************************************
* FILENAME : main.c
*
* DESCRIPTION : Includes main() function with while(1) loop where your code 
*               should go.
*
* PUBLIC FUNCTIONS :
*
* NOTES :
*
* COPYRIGHT : Copyright 2018 Hardi Selg
*

* AUTHOR : Hardi Selg     CONTACT : hardi.selg@ati.ttu.ee
*
* START DATE : 06.11.2018
*
* CHANGES :
*
*
*H*/

//Libraries
#include <xc.h>
#include <sys/attribs.h>
#include <stdio.h>
#include "config.h"
#include "fp8_e3m4.h"

#define DELAY_IN_MSEC_50 	 50
#define DELAY_IN_MSEC_100	100
#define DELAY_IN_MSEC_500	500
#define DELAY_IN_MSEC_1000	1000

#define EMPTY_LINE "            "
#define ARRLEN 16

//Main program
int main(void) {
    //Has to be the first function call after main()
    init(); //Includes PIC16F690 basic configuration
    int value;
    float val_l,val_r;
    float f_temp;
    //Loop forever
    const fp8_e3m4 num[8] = {
        /* 0.015625 */  0x01,  /* -0.234375 */  0x8f,
        /* 0.250000 */  0x10,  /* -0.265625 */  0x91,
        /* 15.500000 */ 0x6f,  /* -15.000000 */ 0xee,
        /* -inf */      0x70,  /* nan */        0x7c
    };
    fp8_e3m4 num_l,num_r,num_s;
    fp8_e3m4_str op_l,op_r;
    unsigned char insert_state = 0;
    unsigned char insert_num = 0;
    char buf[ARRLEN+1];
    WriteDigits(0, 0, 0);
    WriteDigits(1, 0, 0);
    WriteDigits(2, 0, 0);
    WriteDigits(3, 0, 0);
    fp8_e3m4_unpack(0, &op_r);
    fp8_e3m4_unpack(0, &op_l);
    while(1)
    {
        if (insert_state == 2){
            num_l = SWT_GetGroupValue();
            WriteDigitsByte(1, num_l, TRUE);
            LED_SetGroupValue(num_l);
            LCD_WriteStringAtPos("    Set op L  ", 1, 0);
        }
        if (insert_state == 1){
            num_r = SWT_GetGroupValue();
            WriteDigitsByte(0, num_r, TRUE);
            LED_SetGroupValue(num_r);
            LCD_WriteStringAtPos("    Set op R  ", 1, 0);
        }
        if (insert_state == 0){
            if (BTNU){
                LCD_WriteStringAtPos("       Add  ", 0, 0);
                num_s = fp8_e3m4_add(num_l, num_r);
                f_temp = fp8_to_float(num_s);
                sprintf(buf, " R: %8.6f  ", f_temp);
                LCD_WriteStringAtPos(buf, 1, 0);
            } else if (BTNC) {
                LCD_WriteStringAtPos("       Sub  ", 0, 0);
                num_s = fp8_e3m4_sub(num_l, num_r);
                f_temp = fp8_to_float(num_s);
                sprintf(buf, " R: %8.6f  ", f_temp);
                LCD_WriteStringAtPos(buf, 1, 0);
            } else if (BTND) {
                LCD_WriteStringAtPos("      Mult  ", 0, 0);
                num_s = fp8_e3m4_mul(num_l, num_r);
                f_temp = fp8_to_float(num_s);
                sprintf(buf, " R: %8.6f  ", f_temp);
                LCD_WriteStringAtPos(buf, 1, 0);
            } else if (BTNR) {
                LCD_WriteStringAtPos("       Div  ", 0, 0);
                if ((num_r & 0x7f) == 0){
                    LCD_WriteStringAtPos("ERR Div Zero  ", 1, 0);
                } else {
                    num_s = fp8_e3m4_div(num_l, num_r);
                    f_temp = fp8_to_float(num_s);
                    sprintf(buf, " R: %8.6f  ", f_temp);
                    LCD_WriteStringAtPos(buf, 1, 0);
                }
            }
        } else {
            LCD_WriteStringAtPos(EMPTY_LINE, 0, 0);
        }
        if (BTNL){
            WriteDigitsByteBlink(insert_num, FALSE);
            switch (insert_state) {
                case 0: 
                    insert_state = 1;
                    insert_num = 0;
                    break;
                case 1: 
                    insert_state = 2;
                    insert_num = 1;
                    fp8_e3m4_unpack(num_r, &op_r);
                    break;
                case 2: 
                    insert_state = 0;
                    insert_num = 0;
                    fp8_e3m4_unpack(num_l, &op_l);
                    break;
                default:
                    break;
                    
            }
            DelayForAproxmSeconds(DELAY_IN_MSEC_500);
        }
        
        DelayForAproxmSeconds(DELAY_IN_MSEC_100);
        DelayForAproxmSeconds(DELAY_IN_MSEC_100);
    }
    return 0;
}
