/* * uart_echo.c * * Created: 16.08.2018 17:39:49 * Author : jens */ #include #include #include #include #include #include #include "fifo.h" #include "message.h" #include "adc.h" #include "port.h" #include "timer.h" #include "uart.h" #include "i2c.h" #include "mcp42x6.h" #define ARDUINO_NANO 1 #define WITH_COMMAND_EVENTS 0 #define PRINT_PROMPT printf("\n:") #if ARDUINO_NANO #define F_CPU (16000000UL) // MHz #else #define F_CPU (18432000UL) // MHz #endif #define USART_BAUDRATE 38400UL #define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1) #define TIMER_HW_CLOCK (F_CPU/8) #define TIMER_IRQ_CLOCK 1000UL #define TIMER_HW_RELOAD (0xFFFF-(TIMER_HW_CLOCK/TIMER_IRQ_CLOCK)) #define TIMER_SW_DELAY_MS(dly) ((dly*TIMER_IRQ_CLOCK)/1000UL) static uint8_t ledState = 0; static int16_t adc_last = 0; static Fifo messageFifo; ISR(USART_RX_vect) { uint8_t rx_data = UDR0; #if WITH_COMMAND_EVENTS if (rx_data == ' ') { Msg_t msg = {Error, rx_data}; fifo_push(&messageFifo, &msg); } else if (rx_data >= '0' && rx_data <= '9') { Msg_t msg = {Command, rx_data}; fifo_push(&messageFifo, &msg); } #endif Msg_t msg = {Uart, rx_data}; fifo_push(&messageFifo, &msg); } FILE uart_file = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); void setSwitch(int on) { const char *sw_str[2] = {"OFF", "ON"}; printf("Set switch to %s\n", sw_str[on != 0]); portSet(PwrSwitch_out, on != 0); } void setPower(uint16_t power) { printf("Set Power to %d\n", power); uint8_t dac_cmd[] = {0x00, 0x00}; // 6.2 Write Volatile Memory (C2:C0 = ‘010’) size_t res = MCP47x6_write_volatile_dac(power, dac_cmd, sizeof(dac_cmd)); i2c_send(0x60, I2C_WRITE, dac_cmd, res); } typedef enum _eState_t { StateOff = 0, StateNormal = 1, StateRemote = 2, StateError = 3, State_NumStates } State_t; int main(void) { const char *state_str[State_NumStates] = {"Off","Normal","Remote","Error"}; State_t state = StateOff; State_t state_next = StateOff; fifo_init(&messageFifo, 64, sizeof(Msg_t), "Fifo"); /* Replace with your application code */ uart_init(BAUD_PRESCALE); timer_init(&messageFifo, TIMER_HW_RELOAD, TimerClockSel_PS_8); adc_init(&messageFifo); i2c_init(); port_init(); stdout = &uart_file; printf("\nHendi Control v1.0-beta\n"); uint8_t dac_cmd[] = {0x00, 0x00, 0x00}; // 6.1 Write Volatile DAC Register (C2:C0 = ‘00x’) size_t res = MCP47x6_write_volatile_mem(0x0000, dac_cmd, sizeof(dac_cmd)); i2c_send(0x60, I2C_WRITE, dac_cmd, res); sei(); char cmdStr[16]; size_t cmdStrSize = 0; PRINT_PROMPT; // Start Timer timer_start(TIMER_GENERAL, 0); timer_start(TIMER_ADC, 0); while (1) { state_next = state; Msg_t msg; if (!fifo_isEmpty(&messageFifo)) { cli(); fifo_pop(&messageFifo, &msg); sei(); switch(msg.code) { case Uart: { // Process Uart message cmdStr[cmdStrSize] = 0; if (cmdStrSize < sizeof(cmdStr)) { char c = msg.data; if (state != StateNormal && state != StateRemote) { break; } // Command finished with CR/LF if (c == 0x0A || c == 0x0D) { // Power Control if (toupper(cmdStr[0]) == 'P') { uint16_t arg = atol(cmdStr+1); setPower(arg); timer_start(TIMER_TIMEOUT, TIMER_SW_DELAY_MS(5000)); sei(); state_next = StateRemote; } // Switch Control if (toupper(cmdStr[0]) == 'S') { uint16_t arg = atol(cmdStr+1); setSwitch(arg); timer_start(TIMER_TIMEOUT, TIMER_SW_DELAY_MS(5000)); state_next = StateRemote; } cmdStrSize = 0; PRINT_PROMPT; } else { cmdStr[cmdStrSize++] = c; printf("%c", c); } } else { printf("Invalid command : %s\n", cmdStr); cmdStrSize = 0; } } break; case Command: { printf("Command : %c\n", msg.data); uint8_t dac_cmd[] = {0x00, 0x00}; // 6.2 Write Volatile Memory (C2:C0 = ‘010’) size_t res = MCP47x6_write_volatile_dac((uint16_t)(msg.data-'0')<<8, dac_cmd, sizeof(dac_cmd)); i2c_send(0x60, I2C_WRITE, dac_cmd, res); } break; case AdcComplete: { int16_t adc_curr = adc_getData(); if (adc_getChannel() == 6) { if (((adc_curr - adc_last) < -1) || ((adc_curr - adc_last) > 1)) { if (state == StateOff) { if (adc_curr > 2) { setSwitch(1); state_next = StateNormal; } } if (state == StateNormal || state == StateError) { if (adc_curr < 2) { state_next = StateOff; setSwitch(0); } if (state == StateNormal) { setPower(adc_curr << 2); } } } } adc_last = adc_curr; } break; case Timer: { int timer_id = msg.data; switch(timer_id) { case TIMER_GENERAL: { timer_start(timer_id, TIMER_SW_DELAY_MS(500)); switch(ledState) { case 0: PORTB = (PORTB & 0xFC) | 0x00; break; case 1: PORTB = (PORTB & 0xFC) | 0x01; break; case 2: PORTB = (PORTB & 0xFC) | 0x03; break; case 3: PORTB = (PORTB & 0xFC) | 0x02; break; } ledState++; if (ledState == 4) { ledState = 0; } } break; case TIMER_TIMEOUT: { printf("Timeout!\n"); setPower(0); setSwitch(0); state_next = StateError; } break; case TIMER_ADC: { timer_start(timer_id, TIMER_SW_DELAY_MS(50)); adc_start_conversion(0x06); } break; } } break; case Error: printf("Error!!!\n"); break; } } if (state != state_next) { printf("State change \"%s\" => \"%s\"\n", state_str[state], state_str[state_next]); } state = state_next; } }