Prevent redundant writes and start implementing parser timeout
This commit is contained in:
@@ -3,21 +3,8 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static void Puts(const char *str)
|
static void Puts(const char *str);
|
||||||
{
|
static void PrintArgs(const char *fmt, va_list ap);
|
||||||
while (*str != '\0') {
|
|
||||||
USART_Putc(*str++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void PrintArgs(const char *fmt, va_list ap)
|
|
||||||
{
|
|
||||||
char msg[256];
|
|
||||||
|
|
||||||
vsnprintf(msg, sizeof(msg), fmt, ap);
|
|
||||||
|
|
||||||
Puts(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Print(const char *fmt, ...)
|
void Print(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
@@ -51,3 +38,19 @@ void Error(const char *fmt, ...)
|
|||||||
|
|
||||||
// XXX: Force reset?
|
// XXX: Force reset?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void Puts(const char *str)
|
||||||
|
{
|
||||||
|
while (*str != '\0') {
|
||||||
|
USART_Putc(*str++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PrintArgs(const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
char msg[256];
|
||||||
|
|
||||||
|
vsnprintf(msg, sizeof(msg), fmt, ap);
|
||||||
|
|
||||||
|
Puts(msg);
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,27 +3,44 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
|
||||||
#define CMD_MAX_LEN 128
|
#define CMD_MAX_LEN 128
|
||||||
|
|
||||||
// TODO: Write documentation.
|
// TODO: Write documentation.
|
||||||
// TODO: Implement start and stop commands.
|
// TODO: Implement start and stop commands.
|
||||||
// TODO: Reset command buffer on timeout?
|
// TODO: Reset command buffer on timeout.
|
||||||
|
|
||||||
static char cmdbuf[CMD_MAX_LEN + 1];
|
static char cmdbuf[CMD_MAX_LEN + 1];
|
||||||
static char *tail = cmdbuf + CMD_MAX_LEN - 1;
|
static char *tail = cmdbuf + CMD_MAX_LEN - 1;
|
||||||
static char *head = cmdbuf;
|
static char *head = cmdbuf;
|
||||||
|
|
||||||
static bool ParseLine(cmd_t *out);
|
static bool ParseLine(cmd_t *out);
|
||||||
|
static void StartTimer(void);
|
||||||
|
static bool IsTimedOut(void);
|
||||||
|
static void StopTimer(void);
|
||||||
|
|
||||||
bool CMD_Parse(char ch, cmd_t *out)
|
bool CMD_Parse(char ch, cmd_t *out)
|
||||||
{
|
{
|
||||||
bool is_valid;
|
bool is_valid;
|
||||||
|
|
||||||
if (ch == '\n' || ch == '\r') {
|
// FIXME: Reset command buffer on timeout:
|
||||||
|
// No newline character is received if the serial
|
||||||
|
// buffer is full and the ending is discarded. This
|
||||||
|
// means that after a command that is too long, the
|
||||||
|
// next command will not be parsed properly.
|
||||||
|
|
||||||
|
if (head == cmdbuf) {
|
||||||
|
StartTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsTimedOut() ||
|
||||||
|
(ch == '\n' || ch == '\r')) {
|
||||||
is_valid = ParseLine(out);
|
is_valid = ParseLine(out);
|
||||||
tail = cmdbuf + CMD_MAX_LEN - 1;
|
tail = cmdbuf + CMD_MAX_LEN - 1;
|
||||||
head = cmdbuf;
|
head = cmdbuf;
|
||||||
|
StopTimer();
|
||||||
|
|
||||||
return is_valid;
|
return is_valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,3 +87,20 @@ static bool ParseLine(cmd_t *out)
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void StartTimer(void)
|
||||||
|
{
|
||||||
|
TCNT0 = 0x00;
|
||||||
|
TCCR0 = BIT(CS00) | BIT(CS02);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsTimedOut(void)
|
||||||
|
{
|
||||||
|
return false; // TIFR & BIT(TOV0)
|
||||||
|
}
|
||||||
|
|
||||||
|
static void StopTimer(void)
|
||||||
|
{
|
||||||
|
TCNT0 = 0x00;
|
||||||
|
TIFR = BIT(TOV0);
|
||||||
|
}
|
||||||
|
|||||||
46
src/main.c
46
src/main.c
@@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
// TODO: Implement command parser timeout for large input.
|
||||||
// TODO: Config header for chip specifics like EEPROM size.
|
// TODO: Config header for chip specifics like EEPROM size.
|
||||||
// TODO: Only update EEPROM if value differs from previous.
|
|
||||||
// TODO: Check thermistor conversion results /w thermometer.
|
// TODO: Check thermistor conversion results /w thermometer.
|
||||||
// TODO: Implement primary state machine for update loop.
|
// TODO: Implement primary state machine for update loop.
|
||||||
// TODO: Migrate to ATMega 1284P-PU for 2nd 16-bit timer.
|
// TODO: Migrate to ATMega 1284P-PU for 2nd 16-bit timer.
|
||||||
@@ -31,7 +31,8 @@ static float relh;
|
|||||||
|
|
||||||
static int Init(void);
|
static int Init(void);
|
||||||
static void Update(void);
|
static void Update(void);
|
||||||
static void UpdateSensors(void);
|
static void SetTarget(float t, float td);
|
||||||
|
static void GetSensorState(void);
|
||||||
|
|
||||||
static int Init(void)
|
static int Init(void)
|
||||||
{
|
{
|
||||||
@@ -85,7 +86,7 @@ static int Init(void)
|
|||||||
|
|
||||||
if (MEM_Read(&mem) == 0) {
|
if (MEM_Read(&mem) == 0) {
|
||||||
Info("Found persistent configuration in EEPROM!");
|
Info("Found persistent configuration in EEPROM!");
|
||||||
Info("Setting targets TEMP='%.2fC', DEWP='%.2fC'.",
|
Info("Using targets TEMP='%.2fC', DEWP='%.2fC'.",
|
||||||
mem.temp, mem.dewp);
|
mem.temp, mem.dewp);
|
||||||
|
|
||||||
temp_target = mem.temp;
|
temp_target = mem.temp;
|
||||||
@@ -139,7 +140,6 @@ static void Update(void)
|
|||||||
{
|
{
|
||||||
char ch;
|
char ch;
|
||||||
cmd_t cmd;
|
cmd_t cmd;
|
||||||
mem_block_t mem;
|
|
||||||
|
|
||||||
// Parse serial commands
|
// Parse serial commands
|
||||||
while ((ch = USART_Getc()) >= 0) {
|
while ((ch = USART_Getc()) >= 0) {
|
||||||
@@ -148,18 +148,14 @@ static void Update(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch(cmd.type) {
|
switch(cmd.type) {
|
||||||
case T_SET: // Configure new persistent target
|
case T_SET: // Set new persistent target
|
||||||
Info("Setting new target TEMP='%.2fC'...", cmd.args[0]);
|
SetTarget(cmd.args[0], cmd.args[1]);
|
||||||
Info("Setting new target DEWP='%.2fC'...", cmd.args[1]);
|
|
||||||
mem.temp = temp_target = cmd.args[0];
|
|
||||||
mem.dewp = dewp_target = cmd.args[1];
|
|
||||||
MEM_Write(&mem);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Poll sensor values
|
// Poll sensor values
|
||||||
UpdateSensors();
|
GetSensorState();
|
||||||
|
|
||||||
// Handle state
|
// Handle state
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@@ -174,7 +170,33 @@ static void Update(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UpdateSensors(void)
|
static void SetTarget(float t, float td)
|
||||||
|
{
|
||||||
|
mem_block_t mem;
|
||||||
|
|
||||||
|
Info("=======================================");
|
||||||
|
Info("Setting temperature target to '%.2fC'.", t);
|
||||||
|
Info("Setting dewpoint target to '%.2fC'.", td);
|
||||||
|
Info("=======================================");
|
||||||
|
|
||||||
|
if (MEM_Read(&mem) == 0) {
|
||||||
|
if (t == mem.temp && td == mem.dewp) {
|
||||||
|
return; // Nothing to do
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mem.temp = t;
|
||||||
|
mem.dewp = td;
|
||||||
|
|
||||||
|
// Keep in EEPROM
|
||||||
|
MEM_Write(&mem);
|
||||||
|
|
||||||
|
// Update state
|
||||||
|
temp_target = t;
|
||||||
|
dewp_target = td;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GetSensorState(void)
|
||||||
{
|
{
|
||||||
word raw;
|
word raw;
|
||||||
float t[6], rh[3], dp[3];
|
float t[6], rh[3], dp[3];
|
||||||
|
|||||||
Reference in New Issue
Block a user