/*
 * myComms.c
 *
 *  Created on: Mar 27, 2026
 *      Author: ewars
 */

#include "usbd_cdc_if.h"
#include "stdio.h"

#include "myComms.h"
#include "clock.h"
#include "ds1307.h"


#define NV_COLOUR_HOURS_ADDR		0x08
#define NV_COLOUR_MINUTES_ADDR		0x0B
#define NV_COLOUR_SECONDS_ADDR		0x0E
#define NV_COLOUR_BACKGND_ADDR		0x11

typedef struct {
	uint8_t 	cmdId;

	struct{
		uint8_t	pByte_3;
		uint8_t	pByte_2;
		uint8_t	pByte_1;
		uint8_t	pByte_0;
	} bytes;

	uint8_t	crc;
} uartMessage_s;

static void cmd_readNV(uint32_t data);
static void cmd_writeNV(uint32_t data);

static uint8_t nok[] = "NOK\n";
static uint8_t ok[] = "OK\n";
uint8_t myId[] = "Clock\n";

uint8_t UART_RxBuf[6] = {0};
uint8_t RxComplete_fl = 0;

void (*commands[])(uint32_t) = {
		cmd_WhoAmI,						// 0

		cmd_GetTime,					// 1
		cmd_GetMonthDay,				// 2
		cmd_GetYear,					// 3
		cmd_GetTimeZone,				// 4
		cmd_GetDate,					// 5

		cmd_SetTime,					// 6
		cmd_SetMonthDay,				// 7
		cmd_SetYear,					// 8

		cmd_setColour_hour,				// 9
		cmd_setColour_minute,			// 10
		cmd_setColour_second,			// 11
		cmd_setColour_background,		// 12

		cmd_Set_TimeZone,				// 13
		cmd_SetDate,					// 14

		cmd_readNV,						// 15
		cmd_writeNV,					// 16

};

void cmd_GetTimeZone(uint32_t d){
	uint8_t respBuf[4] = {0};

	int8_t z = ds1307_get_time_zone_hour();


	respBuf[0] = 200 + com_getYear;
	if(z<0){
		respBuf[1] = 1;
	}
	respBuf[2] = abs(z);

	CDC_Transmit_FS(respBuf, sizeof(respBuf));


}

void cmd_GetYear(uint32_t d){

	uint8_t respBuf[4] = {0};

	respBuf[0] = 200 + com_getYear;
	uint16_t y = ds1307_get_year();

	respBuf[1] = y/100;
	respBuf[2] = (uint8_t) y & 0xFF;

	CDC_Transmit_FS(respBuf, sizeof(respBuf));
}

void cmd_GetDate(uint32_t d){
	uint8_t respBuf[4] = {0};

	respBuf[0] = 200 + com_getDate;
	respBuf[1] = ds1307_get_date();
	respBuf[2] = ds1307_get_month();
	respBuf[3] = ds1307_get_year();

	CDC_Transmit_FS(respBuf, sizeof(respBuf));

}

void cmd_GetMonthDay(uint32_t d){

	uint8_t respBuf[4] = {0};

	respBuf[0] = 200 + com_getMonthDay;
	respBuf[1] = ds1307_get_date();
	respBuf[2] = ds1307_get_month();
	respBuf[3] = 0;

	CDC_Transmit_FS(respBuf, sizeof(respBuf));

}


/*
 * 	Format: d:m:yy
 */
void cmd_SetDate(uint32_t d){

	ds1307_set_day(UART_RxBuf[1]);

}

void cmd_SetYear(uint32_t year){

	uint16_t y =  (uint16_t)(UART_RxBuf[1] *100) + UART_RxBuf[2];

	ds1307_set_year(y);

}

void cmd_SetMonthDay(uint32_t){

	ds1307_set_day(UART_RxBuf[1]);
	ds1307_set_month(UART_RxBuf[2]);

}

void cmd_Set_TimeZone(uint32_t){
	int z = 0;

	z = abs(UART_RxBuf[2]);
	if(UART_RxBuf[1] == 1){
		z = z * -1;
	}

	ds1307_set_time_zone(z,  0);
}

static void cmd_readNV(uint32_t data){
	HAL_StatusTypeDef status = HAL_ERROR;

	uint8_t addr = (uint8_t) data;
	uint8_t respBuf[3] = {0};

	status = ds1307_read_user_RAM(addr, respBuf, sizeof(respBuf));

	if(HAL_OK == status){
		CDC_Transmit_FS(respBuf, sizeof(respBuf));
	}
	else{
		CDC_Transmit_FS(nok, sizeof(nok));
	}
}

static void cmd_writeNV(uint32_t data){
	HAL_StatusTypeDef status = HAL_ERROR;


	status = ds1307_write_user_RAM(UART_RxBuf[1], &UART_RxBuf[2], 3);


	switch(UART_RxBuf[1]){
		case NV_COLOUR_HOURS_ADDR:
			clock_setColourHours(UART_RxBuf[2], UART_RxBuf[3], UART_RxBuf[4]);
			break;
		case NV_COLOUR_MINUTES_ADDR:
			clock_setColourMinutes(UART_RxBuf[2], UART_RxBuf[3], UART_RxBuf[4]);
			break;
		case NV_COLOUR_SECONDS_ADDR:
			clock_setColourSeconds(UART_RxBuf[2], UART_RxBuf[3], UART_RxBuf[4]);
			break;
		case NV_COLOUR_BACKGND_ADDR:
			clock_setColourBackground(UART_RxBuf[2], UART_RxBuf[3], UART_RxBuf[4]);
			break;
		default:
			break;
	}

	if(HAL_OK == status){
		CDC_Transmit_FS(ok, sizeof(ok));
	}
	else{
		CDC_Transmit_FS(nok, sizeof(nok));
	}

}


void setRxFlag(void){
	RxComplete_fl = 1;
}

void RxCpltCallback(){

	if(RxComplete_fl == 1){
		RxComplete_fl = 0;
		cmd_UART_Request();
	}

}

void cmd_UART_Request(void){

	uartMessage_s* msg =  (uartMessage_s*) &UART_RxBuf[0];

	cmd_RunCommand((uint8_t) msg->cmdId, (uint32_t*) &msg->bytes);


}


void cmd_RunCommand(commands_e cmd, uint32_t* input){
	uint32_t i = *input;
	if(cmd < com_MAX_command){
		commands[cmd](i);
	}

}




void cmd_WhoAmI(uint32_t){
	CDC_Transmit_FS(myId, sizeof(myId));
}


void cmd_SetTime(uint32_t time){

	uint8_t h, m, s;

	h = time & 0xFF;
	m = time >> 8 & 0xFF;
	s = time >> 16 & 0xFF;

	ds1307_set_hour(h);
	ds1307_set_minutes(m);
	ds1307_set_second(s);

	CDC_Transmit_FS(ok, sizeof(ok));

}

void cmd_GetTime(uint32_t time){

	extern ds1307_dev_t my_rtc;

	uint8_t msg[6] = {0};

	//uint8_t resp[] = "Hello Ewaryst\n";

	// sprintf(resp, "%d, %d, %d, \n", my_rtc.hours, my_rtc.minutes, my_rtc.seconds);

	msg[0] = com_getTime + 200;
	msg[1] = my_rtc.hours;
	msg[2] = my_rtc.minutes;
	msg[3] = my_rtc.seconds;
	msg[4] = 251;

	msg[5] = 44;

	CDC_Transmit_FS(msg, sizeof(msg));
}

void cmd_setColour_hour(uint32_t colour){

	uint8_t r, g, b;

	r = colour & 0xFF;
	g = colour >> 8 & 0xFF;
	b = colour >> 16 & 0xFF;

	clock_setColourHours(r, g, b);

	uint8_t nv[] = {
			NV_COLOUR_HOURS_ADDR,
			r,
			g,
			b
	};

	cmd_writeNV((uint32_t) nv);

	CDC_Transmit_FS(ok, sizeof(ok));

}
void cmd_setColour_minute(uint32_t colour){

	uint8_t r, g, b;

	r = colour & 0xFF;
	g = colour >> 8 & 0xFF;
	b = colour >> 16 & 0xFF;

	clock_setColourMinutes(r, g, b);


	uint8_t nv[] = {
		NV_COLOUR_MINUTES_ADDR,
		r,
		g,
		b
	};

	cmd_writeNV((uint32_t) nv);

	CDC_Transmit_FS(ok, sizeof(ok));

}
void cmd_setColour_second(uint32_t colour){

	uint8_t r, g, b;

	r = colour & 0xFF;
	g = colour >> 8 & 0xFF;
	b = colour >> 16 & 0xFF;

	clock_setColourSeconds(r, g, b);


	uint8_t nv[] = {
		NV_COLOUR_SECONDS_ADDR,
		r,
		g,
		b
	};

	cmd_writeNV((uint32_t) nv);

	CDC_Transmit_FS(ok, sizeof(ok));

}
void cmd_setColour_background(uint32_t colour){

	uint8_t r, g, b;

	r = colour & 0xFF;
	g = colour >> 8 & 0xFF;
	b = colour >> 16 & 0xFF;

	clock_setColourBackground(r, g, b);


	uint8_t nv[] = {
		NV_COLOUR_BACKGND_ADDR,
		r,
		g,
		b
	};

	cmd_writeNV((uint32_t) nv);

	CDC_Transmit_FS(ok, sizeof(ok));
}
