Reflow oven controller firmware
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

268 lines
4.7 KiB

/* fields.c */
#include <stddef.h>
#include <string.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include "common.h"
#include "fields.h"
#include "menu.h"
#include "config.h"
uint8_t field_row; // XXX ?
uint8_t field_values[DISPLAY_CHARS];
static uint8_t field_index(char c)
{
return ((uint8_t)(c) & (uint8_t)15)-1;
}
//#define field(c) fields[((uint8_t)(c) & (uint8_t)15)-1]
#define field(c) fields[field_index(c)]
uint8_t field_length(char c)
{
return field(c).length;
}
bool field_is_text(char c)
{
return field(c).display == NULL;
}
PGM_P field_text(char c, uint8_t n)
{
return get_string(&field(c).display[n]);
}
uint8_t field_display_entries(char c)
{
return field(c).display_entries;
}
bool is_field(char c) {
return (c > 0) && (c < 32);
}
bool is_editable(char c) {
return (c > 16) && (c < 32);
}
PGM_P get_string(PGM_P const *addr)
{
PGM_P ptr;
memcpy_P(&ptr, addr, sizeof(PGM_P));
return ptr;
}
uint8_t find_field(uint8_t n)
{
char c;
uint8_t index = 0;
char type = 0;
while ((c = menu_getchar(index)) != '\0') {
index++;
if (type && (type == c))
continue;
if (is_field(c)) {
type = c;
if (n == 0)
return index-1;
n--;
} else {
type = 0;
}
}
return 255;
}
uint8_t find_field_length_by_place(uint8_t index)
{
uint8_t orig_index = index;
char type = menu_getchar(index);
uint8_t tlen = field_length(type);
while (menu_getchar(index) == type)
index += tlen;
return index - orig_index;
}
uint8_t find_field_length(uint8_t index)
{
return find_field_length_by_place(find_field(index));
}
uint8_t find_field_number(uint8_t index)
{
uint8_t n, p;
for (n = 0; (p = find_field(n)) != 255; n++)
{
if (p == index)
return n;
}
return 255;
}
uint8_t find_editable_field(uint8_t index, bool left)
{
int8_t increment = left?(-1):1;
char c;
uint8_t len;
if (index >= 255)
return 255;
len = strlen_P(get_string(&menu_current_p->text[field_row]));
if (left && (index >= len))
index = len-1;
while ((c = menu_getchar(index)) != '\0') {
if (is_editable(c))
return index;
index += increment;
}
return 255;
}
void write_field_enum(uint8_t field, uint8_t val)
{
uint8_t p = find_field(field);
field_values[p] = val;
}
uint8_t read_field_enum(uint8_t field)
{
uint8_t p = find_field(field);
return field_values[p];
}
uint16_t read_field_uint16(uint8_t field)
{
uint8_t i;
uint16_t val = 0;
uint8_t p = find_field(field);
uint8_t l = find_field_length(field);
for (i = 0; i < l; i++) {
val = val * 10;
val += field_values[p+i];
}
return val;
}
void write_field_uint16(uint8_t field, uint16_t val)
{
uint8_t i;
uint8_t p = find_field(field);
uint8_t l = find_field_length(field);
for (i = l; i; i--) {
field_values[p+i-1] = val % 10;
val = val / 10;
}
}
void write_field_integer_part(uint8_t field, int32_t val)
{
if (val < 0)
val = -val;
write_field_uint16(field, val >> 12);
}
void write_field_fractional_part(uint8_t field, int32_t val)
{
uint8_t i;
uint16_t v;
uint8_t p = find_field(field);
uint8_t l = find_field_length(field);
if (val < 0)
val = -val;
v = val & 0xfff;
for (i = 0; i < l; i++) {
uint8_t digit;
v = v * 10;
digit = (v >> 12) % 10;
v = v - (digit << 12);
field_values[p+i] = digit;
}
}
int32_t round_dp(int32_t n, uint8_t dp)
{
int32_t rval = 0x800;
int i;
/* Round away from zero. Remove this bit
* to round up
*/
if (n < 0)
rval = -rval;
for (i = 0; i < dp; i++)
rval = rval / 10;
return n + rval;
}
uint32_t read_field_fracint(int8_t index, bool frac)
{
int32_t val, v_int, v_frac;
uint8_t sign = read_field_enum(index++);
v_int = read_field_uint16(index++);
if (frac) {
uint8_t l_frac;
v_frac = read_field_uint16(index);
l_frac = find_field_length(index);
v_frac = v_frac << 12;
while (l_frac--)
v_frac = v_frac / 10;
} else {
v_frac = 0;
}
val = (v_int << 12) + v_frac;
if (sign == FIELD_SIGN_NEGATIVE)
val = -val;
return val;
}
void write_field_fracint(uint8_t index, bool sign, bool frac, int32_t val)
{
uint8_t l_frac;
l_frac = find_field_length(index+1+(sign?1:0));
val = round_dp(val, frac?l_frac:0);
if (sign)
write_field_enum(index++, (val<0)?FIELD_SIGN_NEGATIVE:FIELD_SIGN_POSITIVE);
write_field_integer_part(index++, val);
if (frac)
write_field_fractional_part(index, val);
}
void write_field_temperature(uint8_t index, bool frac, temp_t k_temp)
{
int32_t temp = temperature_from_kelvin(k_temp);
write_field_fracint(index, TRUE, frac, temp);
write_field_enum(index+2+(frac?1:0), config.units);
}