#include #include #include #include #include #include "utils.h" #include "main.h" #include "uart.h" #define BUFSIZE 40 #define CURRENT_MAX 30000 // 30 Ampere is max volatile uint16_t syscounter = 0; volatile uint8_t digitbuffer[6] = { 0,0,0,0,0,0 }; volatile uint8_t leddigitbuffer[4] = { 0,0,0,0 }; uint8_t digit = 0; uint8_t leddigit = 0; // values send over uart from powerboard uint16_t voltage = 0; int16_t current_in = 0; int16_t current_out = 0; uint8_t dumpsw = 0; //TODO: make bitfield uint8_t loadsw = 0; //TODO: make bitfield uint8_t gensw = 0; //TODO: make bitfield uint16_t power_gen = 0; uint16_t power_load = 0; unsigned char data_count = 0; unsigned char data_in[BUFSIZE]; char command_in[BUFSIZE]; const uint8_t segment_translate[10] = { 63, 6, 91, 79, 102, 109, 125, 7, 127, 111 }; const uint8_t smallbar_translate[9] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; const uint8_t bigbar_translate[15][2] = { { 0x00, 0xc0}, { 0x00, 0x60}, { 0x00, 0x30}, { 0x00, 0x18}, { 0x00, 0x0c}, { 0x00, 0x06}, { 0x00, 0x03}, { 0x01, 0x01}, { 0x03, 0x00}, { 0x06, 0x00}, { 0x0c, 0x00}, { 0x18, 0x00}, { 0x30, 0x00}, { 0x60, 0x00}, { 0xc0, 0x00} }; static void timer_init(void) { // clock is 8MHz TCCR1B |= _BV(WGM12) | _BV(CS11) | _BV(CS10) ; // CTC Mode for Timer 1 (16Bit) with prescale of 64 OCR1A = 250; // 500Hz TIMSK = _BV(OCIE1A); sei(); // enable interrupts } static void ports_init(void) { // make column / digit driver pins to output LEDDIG_DDR |= _BV(LEDS_MID1) | _BV(LEDS_MID2) | _BV(LEDS_LOAD) | _BV(LEDS_GEN); SEVENSEGDIG_DDR |= _BV(DIG0) | _BV(DIG1) | _BV(DIG2) | _BV(DIG3) | _BV(DIG4) | _BV(DIG5); // make data ports to output LED_DDR = 0xff; SEVENSEG_DDR = 0xff; SEVENSEGDIG_PORT = 0; SEVENSEG_PORT = 0; LEDDIG_PORT = 0; LED_PORT = 0; } static void print_sevenseg(uint8_t display, uint16_t value) { uint8_t d[3]; d[2] = (value % 1000 / 100 ); d[1] = (value % 100 / 10 ); d[0] = (value % 10); if(display == 0) { digitbuffer[0] = segment_translate[d[0]]; if(d[1] == 0 && d[2] == 0) digitbuffer[1] = 0x00; else digitbuffer[1] = segment_translate[d[1]]; if(d[2] == 0) digitbuffer[2] = 0x00; else digitbuffer[2] = segment_translate[d[2]]; } else { digitbuffer[3] = segment_translate[d[0]]; if(d[1] == 0 && d[2] == 0) digitbuffer[4] = 0x00; else digitbuffer[4] = segment_translate[d[1]]; if(d[2] == 0) digitbuffer[5] = 0x00; else digitbuffer[5] = segment_translate[d[2]]; } } static void print_bar(uint8_t display, uint16_t value, uint16_t max) { uint16_t x = 0; float temp = max; x = (uint16_t)( (value / temp) * 8.0); x%=8; switch(display) { case LEDS_LOAD: leddigitbuffer[2] = smallbar_translate[x]; break; case LEDS_GEN: leddigitbuffer[3] = smallbar_translate[x]; break; } } static void print_bar_bottom(uint16_t in, uint16_t out, uint16_t max) { uint16_t x; float temp = max; if(out == in) { leddigitbuffer[0] = bigbar_translate[7][0]; leddigitbuffer[1] = bigbar_translate[7][1]; return; } else if( out > in ) { x = (uint16_t)( ((out - in) / temp) * 8.0); x = x+8; } else { x = (uint16_t)( ((in - out) / temp) * 8.0); x = 7-x; } if(x > 14) x = 14; if(x < 0) x = 0; leddigitbuffer[0] = bigbar_translate[x][0]; leddigitbuffer[1] = bigbar_translate[x][1]; } void process_command() { if(strstr(command_in,"A") != NULL) { // we have an A and B (from check in work_uart() // so our message should be complete and consist of: // A$voltage,$current_in,$current_out,$power_in,$power_out,loadsw,dumpsw,gensw\n //A12.5,65464,00000,00000,00000,1,0,1B char *token; uint8_t tokencounter = 0; char *start = strrchr(command_in, 'A'); // remove first (B is ignored by atoi) start++; token = strtok(start, ","); while( token ) { switch(tokencounter) { case 0: voltage = atoi(token); break; case 1: current_in = atoi(token); break; case 2: current_out = atoi(token); break; case 3: power_gen = atoi(token); break; case 4: power_load = atoi(token); break; case 5: if(atoi(token) == 1) loadsw = 1; else loadsw = 0; break; case 6: if(atoi(token) == 1) dumpsw = 1; else dumpsw = 0; break; case 7: if(atoi(token) == 1) gensw = 1; else gensw = 0; break; } tokencounter++; token = strtok(NULL, ","); } } } static void work_uart(){ unsigned int c = uart_getc(); if ( !(c & UART_NO_DATA) ) { data_in[data_count] = c; if (data_in[data_count] == 'B') { data_count = 0; memcpy(command_in, data_in, BUFSIZE); memset(data_in, 0, BUFSIZE); process_command(); } else { data_count++; } } } static void demo_display(void) { for(uint8_t i = 0; i< 16;i++) { leddigitbuffer[0] = bigbar_translate[i][0]; leddigitbuffer[1] = bigbar_translate[i][1]; wait(5); } for(uint8_t i = 0; i< 9;i++) { leddigitbuffer[2] = smallbar_translate[i]; wait(5); } for(uint8_t i = 0; i< 9;i++) { leddigitbuffer[3] = smallbar_translate[i]; wait(5); } for(uint8_t j = 0; j< 3;j++) { for(uint8_t i = 0; i< 6; i++) { digitbuffer[i] = 0xff; } wait(20); for(uint8_t i = 0; i< 6; i++) { digitbuffer[i] = 0x00; } wait(20); } for(uint8_t i = 0; i< 3;i++) { leddigitbuffer[i] = 0x00; } } int main(void) { ports_init(); timer_init(); uart_init(UART_BAUD_SELECT(19200,F_CPU)); memset(data_in, 0, BUFSIZE); demo_display(); while(1) { work_uart(); if(syscounter >= 100) { uart_putc('a'); // send a to receive values print_sevenseg(0, power_gen); print_sevenseg(1, power_load); print_bar(LEDS_GEN, current_in, CURRENT_MAX); print_bar(LEDS_LOAD, current_out, CURRENT_MAX); print_bar_bottom(current_in, current_out, 10000); syscounter = 0; } } return(0); } // system timer SIGNAL(TIMER1_COMPA_vect) { syscounter++; // output to sevensegment and leds // make this here to reduce display flicker digit++; if(digit >5) digit = 0; leddigit++; if(leddigit >3) leddigit = 0; SEVENSEG_PORT = digitbuffer[digit]; SEVENSEGDIG_PORT = _BV(digit+DIG0); LED_PORT = leddigitbuffer[leddigit]; LEDDIG_PORT = _BV(leddigit); }