Files
HendiControlFirmware/Control/firmware/uart_echo/main.c
T
jens 08fc6c9b3b - renamed project
git-svn-id: http://moon:8086/svn/projects/HendiControl@159 fda53097-d464-4ada-af97-ba876c37ca34
2019-03-30 00:50:29 +00:00

277 lines
5.8 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* uart_echo.c
*
* Created: 16.08.2018 17:39:49
* Author : jens
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include "machine.h"
#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 PRINT(a,...) printf(a, ##__VA_ARGS__)
#define PRINT_PROMPT putchar(0x0D);putchar(0x0A);putchar(':');
#define USART_BAUDRATE 9600UL
#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)
int16_t adc_poti = 0;
int16_t adc_swin = 0;
int sw_in_last = 0;
size_t cmdStrSize = 0;
Fifo messageFifo;
FILE uart_file = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
typedef enum _eSwitch
{
SwitchOff = 0,
SwitchOn = 1
} Switch;
void setSwitch(int on)
{
const char *sw_str[2] = {"OFF", "ON"};
PRINT("Set switch to %s\n", sw_str[on != 0]);
portSet(PwrSwitch_out, on != 0);
}
typedef enum _ePower
{
PowerLow = 4095,
PowerMax = 0
} Power;
void setPower(uint16_t power)
{
PRINT("Set Power to %u\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
{
StateNormal = 0,
StateRemote = 1,
StateError = 2,
State_NumStates
} State_t;
int main(void)
{
int hb_state = 0;
cli();
wdt_reset();
wdt_disable();
const char *state_str[State_NumStates] = {"Normal","Remote","Error"};
State_t state = StateNormal;
State_t state_next = StateNormal;
fifo_init(&messageFifo, 8, sizeof(Msg_t), "Fifo");
/* Replace with your application code */
uart_init(&messageFifo, USART_BAUDRATE);
timer_init(&messageFifo, TIMER_HW_RELOAD, TimerClockSel_PS_8);
adc_init(&messageFifo);
i2c_init();
port_init();
stdout = &uart_file;
printf("Hendi Control v1.1\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);
char cmdStr[16];
PRINT_PROMPT;
// Start Timer
timer_start(TIMER_GENERAL, 0);
timer_start(TIMER_ADC, 0);
setSwitch(1);
sei();
while (1)
{
state_next = state;
Msg_t msg;
if (!fifo_isEmpty(&messageFifo))
{
fifo_pop(&messageFifo, &msg);
switch(msg.code)
{
case Uart:
{
// Process Uart message
cmdStr[cmdStrSize] = 0;
char c = (char)msg.m.uart.data;
// Command finished with CR/LF
if (c == 0x0A || c == 0x0D)
{
PRINT_PROMPT;
if (cmdStrSize < 1)
{
break;
}
if (state == StateNormal || state == StateRemote)
{
// Power Control
if (toupper(cmdStr[0]) == 'P')
{
uint16_t arg = (uint16_t)strtol(cmdStr+1, (char **)NULL, 10);
setPower(arg);
timer_start(TIMER_TIMEOUT, TIMER_SW_DELAY_MS(5000));
state_next = StateRemote;
}
// Switch Control
if (toupper(cmdStr[0]) == 'S')
{
uint16_t arg = (uint16_t)strtol(cmdStr+1, (char **)NULL, 10);
setSwitch(arg);
timer_start(TIMER_TIMEOUT, TIMER_SW_DELAY_MS(5000));
state_next = StateRemote;
}
// Switch Control
if (toupper(cmdStr[0]) == 'X')
{
timer_stop(TIMER_TIMEOUT);
setPower(PowerLow);
setSwitch(SwitchOff);
}
}
cmdStrSize = 0;
}
else
{
if (cmdStrSize < (sizeof(cmdStr)-1))
{
cmdStr[cmdStrSize++] = c;
}
putchar(c);
}
}
break;
case AdcComplete:
{
uint8_t adc_ch = msg.m.adc.ch;
int16_t adc_curr = (int16_t)msg.m.adc.data;
if (adc_ch == 0)
{
if (((adc_curr - adc_poti) < -1) || ((adc_curr - adc_poti) > 1))
{
if (state == StateNormal)
{
setPower(adc_curr << 2);
}
adc_poti = adc_curr;
}
}
if (adc_ch == 2)
{
adc_swin = adc_curr;
}
}
break;
case Timer:
{
int timer_id = msg.m.timer.ch;
switch(timer_id)
{
case TIMER_GENERAL:
{
hb_state = !hb_state;
if (hb_state)
{
timer_start(timer_id, TIMER_SW_DELAY_MS(50));
}
else
{
timer_start(timer_id, TIMER_SW_DELAY_MS(950));
}
portSet(Led_HB, hb_state);
}
break;
case TIMER_TIMEOUT:
{
PRINT("Timeout!\n");
state_next = StateError;
}
break;
case TIMER_ADC:
{
timer_start(timer_id, TIMER_SW_DELAY_MS(50));
int sw_in = adc_swin > 512;
if (sw_in != sw_in_last)
{
PRINT ("PwrSwitch_in = %d\n", sw_in);
if (sw_in == 0)
{
if (state == StateError || state == StateRemote)
{
setSwitch(SwitchOn);
state_next = StateNormal;
}
}
}
sw_in_last = sw_in;
adc_enqueue_conversion(0);
adc_enqueue_conversion(2);
}
break;
}
}
break;
case NOP:
break;
}
}
if (state != state_next)
{
PRINT("State change \"%s\" => \"%s\"\n", state_str[state], state_str[state_next]);
if (state_next == StateError)
{
setPower(PowerLow);
setSwitch(SwitchOff);
portSet(Led_ERR, 1);
}
if (state_next == StateNormal)
{
portSet(Led_ERR, 0);
}
}
state = state_next;
}
}