Prevent redundant writes and start implementing parser timeout

This commit is contained in:
2024-09-22 23:26:48 +02:00
parent a4ed6be3de
commit 9458db03f7
3 changed files with 88 additions and 29 deletions

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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];