Files
HendiControlFirmware/Control/firmware/HendiCtrl/main.c
T
jens feaf3666be [UART]
- fixed baudrate calculation

[Bootloader]
- set baudrate top 115200

[HendiCtrl]
- set baudrate top 115200
- revised and fixed command interpreter
- added new commands: SW_VERSION, SW_IDENTIFIER, DEBUG on/on, Remote enter, Remote exit
- oven is switched off on entering / exiting remote


git-svn-id: http://moon:8086/svn/projects/HendiControl@173 fda53097-d464-4ada-af97-ba876c37ca34
2019-03-30 11:48:05 +00:00

383 lines
8.0 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_DEBUG(a,...) \
if (g_debug) \
{ \
printf(a, ##__VA_ARGS__); \
}
#define PRINT_CRLF putchar(0x0D);putchar(0x0A);
#define PRINT_ANSWER(a,...) PRINT_CRLF; printf(a, ##__VA_ARGS__);
#define PRINT_PROMPT PRINT_CRLF; putchar(':');
#define USART_BAUDRATE (115200UL)
#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 const uint16_t POTI_HSYTERSE = 1;
int16_t adc_poti = 0;
int16_t adc_swin = 0;
int sw_in_last = 0;
size_t cmdStrSize = 0;
Fifo messageFifo;
uint16_t g_power = 0;
int g_debug = 0;
int g_switch = 0;
static const char SW_IDENTIFIER[] = "Hendi-Control";
static const char SW_VERSION[] = "v1.1";
FILE uart_file = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
typedef enum _eSwitch
{
SwitchOff = 0,
SwitchOn = 1
} Switch;
void setSwitch(int on)
{
g_switch = on;
const char *sw_str[2] = {"OFF", "ON"};
PRINT_DEBUG("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)
{
g_power = power;
PRINT_DEBUG("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("%s %s\n", SW_IDENTIFIER, SW_VERSION);
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
char c = (char)msg.m.uart.data;
cmdStr[cmdStrSize] = 0;
// Command finished with CR/LF
if (c == 0x0D)
{
char *pArgs = cmdStr;
cmdStrSize = 0;
while (*pArgs)
{
// Power Control
if (toupper(*pArgs) == 'P')
{
pArgs++;
if ((*pArgs) == '?')
{
PRINT_ANSWER("%04u", g_power);
pArgs++;
}
else
{
if (!isdigit(*pArgs))
{
break;
}
uint16_t arg = (uint16_t)strtol(pArgs, &pArgs, 10);
if (state == StateRemote)
{
setPower(arg);
}
}
}
// Switch Control
else if (toupper(*pArgs) == 'S')
{
pArgs++;
if ((*pArgs) == '?')
{
PRINT_ANSWER("%u", g_switch);
pArgs++;
}
else
{
if (!isdigit(*pArgs))
{
break;
}
uint16_t arg = (uint16_t)strtol(pArgs, &pArgs, 10);
if (state == StateRemote)
{
setSwitch(arg);
}
}
}
// Enter remote
else if (toupper(*pArgs) == 'R')
{
pArgs++;
if (state == StateNormal)
{
setPower(PowerLow);
setSwitch(SwitchOff);
state_next = StateRemote;
}
}
// Exit remote
else if (toupper(*pArgs) == 'X')
{
pArgs++;
if (state == StateRemote)
{
setPower(PowerLow);
setSwitch(SwitchOff);
state_next = StateNormal;
}
}
// Debug Control
else if (toupper(*pArgs) == 'D')
{
pArgs++;
if (!isdigit(*pArgs))
{
break;
}
g_debug = (uint16_t)strtol(pArgs, &pArgs, 10);
}
// SW identifier
else if (toupper(*pArgs) == 'I')
{
pArgs++;
PRINT_ANSWER("%s", SW_IDENTIFIER);
}
// Version
else if (toupper(*pArgs) == 'V')
{
pArgs++;
PRINT_ANSWER("%s", SW_VERSION);
}
// no match
else
{
pArgs++;
}
} // while (*pArgs)
timer_start(TIMER_TIMEOUT, TIMER_SW_DELAY_MS(10000));
PRINT_PROMPT;
}
else
{
if ((c != 0x0A) && (c != 0x0D))
{
if (cmdStrSize < (sizeof(cmdStr)-1))
{
cmdStr[cmdStrSize++] = c;
}
putchar(c);
}
} // if (c == 0x0D)
} // case Uart:
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) <= -(int16_t)POTI_HSYTERSE) || ((adc_curr - adc_poti) >= (int16_t)POTI_HSYTERSE))
{
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:
{
uint16_t interval = 1000;
uint16_t pulse = 50;
if (state == StateRemote)
{
interval = 500;
pulse = 50;
}
hb_state = !hb_state;
if (hb_state)
{
timer_start(timer_id, TIMER_SW_DELAY_MS(pulse));
}
else
{
timer_start(timer_id, TIMER_SW_DELAY_MS((interval-pulse)));
}
portSet(Led_HB, hb_state);
}
break;
case TIMER_TIMEOUT:
{
if (state == StateRemote)
{
PRINT_DEBUG("Remote 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_DEBUG ("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_DEBUG("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;
}
}