/*
* SM1370R.cpp
*
* Created: 26.08.2020 21:35:58
* Author : Pavel
*/

#include "settings.h"

#include <avr/io.h>
#include <stdlib.h>
#include <stdio.h>
#include <util/delay.h>

#include "drivers/u8glib/u8g.h"
#include "atmegaPins.h"
#include "drivers/uart.h"
#include "utils.h"
#include "drivers/eeprom.h"
#include "time.h"


//=============DRIVERS==========================
u8g_t display;
UART serial;
EEPROM eeprom;
Time time;
//=============DRIVERS==========================

char buffer[30]; 
volatile unsigned long control_button_pressed_time =0;
volatile unsigned long control_button_up_time = 0;

uint8_t currentChannel = 0;
uint16_t currentChannelRssi = 0;

uint8_t channels_pin_sequence[] = {
	0b0001,//A1
	0b0011,//A2
	0b0101,//A3
	0b0111,//A4
	0b1001,//A5
	0b1011,//A6
	0b1101,//A7
	0b1111,//A8
	//0b0000,//B1
	//0b0010,//B2
	//0b0100,//B3
	//0b0110,//B4
	0b1000,//B5
	//0b1010,//B6
	//0b1100,//B7
	//0b1110,//B8
};


const char channel_1[] PROGMEM= "Ch1(1080Mhz)";
const char channel_2[] PROGMEM= "Ch2(1120Mhz)";
const char channel_3[] PROGMEM= "Ch3(1160Mhz)";
const char channel_4[] PROGMEM= "Ch4(1200Mhz)";
const char channel_5[] PROGMEM= "Ch5(1240Mhz)";
const char channel_6[] PROGMEM= "Ch6(1280Mhz)";
const char channel_7[] PROGMEM= "Ch7(1320Mhz)";
const char channel_8[] PROGMEM= "Ch8(1360Mhz)";
const char channel_9[] PROGMEM= "Ch9(1258Mhz)";

const char *const channels_names[] PROGMEM  = {
	channel_1,
	channel_2,
	channel_3,
	channel_4,
	channel_5,
	channel_6,
	channel_7,
	channel_8,
	channel_9,
};

void init_ADC()
{
	ADMUX = (1<<REFS0);
	ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
}

void delay(int ms){
	while (0 < ms){
		_delay_ms(1);
		--ms;
	}
}

void init_hardware(){

	init_ADC();
	
	//Pins for SM1370
	setPinMode(DDRD,S1,INPUT);
	setPinMode(DDRD,CS1,INPUT);
	setPinMode(DDRD,CS2,INPUT);
	setPinMode(DDRD,CS3,INPUT);
	
	//Control button pin
	setPinMode(DDRD,CONTROL_BUTTON,INPUT);
	
	time.init();
	serial.init();
	
	u8g_InitI2C(&display, &u8g_dev_ssd1306_128x64_i2c, U8G_I2C_OPT_FAST);
	
	sei();//Разрешаем прерывания
}

void clearScreen(){
	u8g_FirstPage(&display);
	do {
	} while (u8g_NextPage(&display));
}

uint16_t analogRead(int pin){
	ADMUX = pin|(ADMUX & 0xF8);
	ADCSRA |= 1<<ADSC;
	while(ADCSRA & (1<<ADSC));
	return ADC;
}


void switchPin(uint8_t pin,bool flag){
	if(flag){
		setPinMode(DDRD,pin,OUTPUT);
		}else{
		setPinMode(DDRD,pin,INPUT);
	}
}

uint8_t findBestChannel() {
	
	clearScreen();
	
	u8g_FirstPage(&display);
	u8g_SetFont(&display, u8g_font_9x15);
	
	do
	{					  
		u8g_DrawStrP(&display,10,32,U8G_PSTR("Searching..."));
	} while (u8g_NextPage(&display));
	
	uint8_t bestChannel = 0;
	uint16_t bestRssi = 0;
	uint16_t rssi = 0;

	for (uint8_t i = 0; i<sizeof(channels_pin_sequence); i++) {

		switchPin(S1,(channels_pin_sequence[i] >> 0)  & 0x01);
		switchPin(CS1,(channels_pin_sequence[i] >> 1)  & 0x01);
		switchPin(CS2,(channels_pin_sequence[i] >> 2)  & 0x01);
		switchPin(CS3,(channels_pin_sequence[i] >> 3)  & 0x01);
		
		delay(100);
		
		rssi  = analogRead(RSSI_PIN);
		
		if(rssi>=bestRssi){
			bestRssi = rssi;
			bestChannel = i;
		}
	}

	return bestChannel;
}

void selectChannel(uint8_t channel, bool save = true){
	switchPin(S1,(channels_pin_sequence[channel] >> 0)  & 0x01);
	switchPin(CS1,(channels_pin_sequence[channel] >> 1)  & 0x01);
	switchPin(CS2,(channels_pin_sequence[channel] >> 2)  & 0x01);
	switchPin(CS3,(channels_pin_sequence[channel] >> 3)  & 0x01);
	
	currentChannel = channel;
	
	if(save) eeprom.write(SAVE_SELECTED_CHANNEL_ADDRESS,currentChannel);
}


void displaySelectedChannel(uint8_t channel){
	u8g_FirstPage(&display);
	u8g_SetFont(&display, u8g_font_9x15);
	
	do
	{
		
		u8g_DrawStrP(&display,0,14,U8G_PSTR("Select channel."));
		
		strcpy_P(buffer, (char *)pgm_read_word(&(channels_names[channel])));
		u8g_DrawStr(&display,0,38,buffer);
		
		sprintf_P(buffer, PSTR("RSSI:%u%%"), map(currentChannelRssi,MIN_RSSI_ANALOG_VALUE,MAX_RSSI_ANALOG_VALUE,0,100));
		u8g_DrawStr(&display,0,55,buffer);
		
	} while (u8g_NextPage(&display));
}


void checkButtonPressed(){
	if(digitalRead(PIND,CONTROL_BUTTON)){
		
		control_button_pressed_time = time.millis();
		while(digitalRead(PIND,CONTROL_BUTTON) && time.millis()-control_button_pressed_time < 2000);
		
		control_button_up_time = time.millis()-control_button_pressed_time;
		
		if(control_button_up_time < 200){
			currentChannel++;
			if(currentChannel>sizeof(channels_pin_sequence)-1){
				currentChannel=0;
			}
			selectChannel(currentChannel);
		}else if(control_button_up_time >=2000){
			selectChannel(findBestChannel());
		}
	}else{
		control_button_pressed_time = 0;
	}
}

void readCurrentRSSI(){
	uint16_t rssi = 0;
	
	for(uint8_t i = 0; i<GET_RSSI_COUNT ;i++){
		rssi+=analogRead(RSSI_PIN);
	}
	
	currentChannelRssi =(uint16_t) (rssi/GET_RSSI_COUNT);
	
	if(currentChannelRssi<MIN_RSSI_ANALOG_VALUE) currentChannelRssi = MIN_RSSI_ANALOG_VALUE;
	if(currentChannelRssi>MAX_RSSI_ANALOG_VALUE) currentChannelRssi = MAX_RSSI_ANALOG_VALUE;
}

void displaySplashScreen(){
	u8g_FirstPage(&display);
	
	do
	{
		u8g_SetFont(&display, u8g_font_10x20);
		u8g_DrawStrP(&display,28,28,U8G_PSTR("SM1370R"));
		u8g_SetFont(&display, u8g_font_8x13);
		u8g_DrawStrP(&display,4,44,U8G_PSTR("1.2Ghz Receiver"));
		
	} while (u8g_NextPage(&display));
	
	delay(1000);
}

int main(void)
{
	init_hardware();
	clearScreen();
	displaySplashScreen();
	selectChannel(eeprom.readByte(SAVE_SELECTED_CHANNEL_ADDRESS),false);
	
	while (true)
	{
		displaySelectedChannel(currentChannel);
		checkButtonPressed();
		readCurrentRSSI();
	}

}

