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.
269 lines
4.7 KiB
269 lines
4.7 KiB
9 years ago
|
/* 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);
|
||
|
}
|
||
|
|