diff options
Diffstat (limited to 'fw')
| -rw-r--r-- | fw/dac.c | 2 | ||||
| -rw-r--r-- | fw/eeprom.c | 2 | ||||
| -rw-r--r-- | fw/main.c | 79 | ||||
| -rw-r--r-- | fw/table.c | 72 | ||||
| -rw-r--r-- | fw/table.h | 41 | ||||
| -rw-r--r-- | fw/tests/system/dac_systest.c | 16 | ||||
| -rw-r--r-- | fw/types.c | 50 | ||||
| -rw-r--r-- | fw/types.h | 20 |
8 files changed, 252 insertions, 30 deletions
@@ -31,7 +31,7 @@ dacInit(void) { static void set(U8 dacNum, Conf conf, U16 level) { - lshiftU16(&level, 2u); // D0 at bit 2 + level = lshiftU16(level, 2u); // D0 at bit 2 level.hi = (U8)conf | (level.hi & 0x0F); // set config bits if (dacNum == 1u) { diff --git a/fw/eeprom.c b/fw/eeprom.c index e832fa0..fdce167 100644 --- a/fw/eeprom.c +++ b/fw/eeprom.c @@ -118,7 +118,7 @@ eepromWrite(U16 addr, U8 *data, U8 size) { while (size--) { (void)spiTx(*data); data++; - addU16(&addr, 1u); + addr = addU16U8(addr, 1u); // Check if write crosses page boundary if (isPageStart(addr) && size) { @@ -5,15 +5,94 @@ #include "system.h" #include "types.h" +#include "table.h" #include "spi.h" #include "eeprom.h" +#include "dac.h" #include "can.h" +// Parameters: +// Each parameter has an associated CAN ID and calibration table in the EEPROM. +enum { + TACH = 0, + SPEED = 1, + AN1 = 2, + AN2 = 3, + AN3 = 4, + AN4 = 5, +} Parameter; + +// CAN ID for writing/reading calibration tables from a host PC. +// LSB of ID, 'X', indicates table and row number: X[7:5]{table #}, X[4:0]{row #}. +static const CanId tblCanId = { + .type = CAN_ID_EXT, + .eid = {0x00, 0x2F, 0x27, 0x01}, // 1272F0Xh +}; + +// CAN ID for writing/reading the CAN ID associated with each parameter +// from a host PC. +// LSB of ID, 'X', indicates a particular Parameter enum. +static const CanId paramCanId = { + .type = CAN_ID_EXT, + .eid = {0x10, 0x2F, 0x27, 0x01}, // 1272F1Xh +}; + +// Receive buffer 0 mask. +// RXB0 is used for control messages for reading/writing configuration tables and CAN IDs for each parameter, which are stored in the EEPROM. +// Mask all but the LSB of the Table and Parameter IDs. +static const CanId rxb0Mask = { + .type = CAN_ID_EXT, + .eid = {0x10, 0x2F, 0x27, 0x01}, // 1272F10h +}; + +// Calibration tables in EEPROM: +static Table tachTbl; +static Table speedTbl; +static Table an1Tbl; +static Table an2Tbl; +static Table an3Tbl; + +// Filter ID addresses in EEPROM: +// Each one of these addresses holds a CanId struct. +static U16 id1Addr; +static U16 id2Addr; +static U16 id3Addr; +static U16 id4Addr; +static U16 id5Addr; + void main(void) { + U16 offset; + + // Initialize calibration table EEPROM addresses + offset = (U16){0u, 0u}; + tachTbl = (Table){offset}; + offset = addU16U8(offset, TAB_SIZE); + speedTbl = (Table){offset}; + offset = addU16U8(offset, TAB_SIZE); + an1Tbl = (Table){offset}; + offset = addU16U8(offset, TAB_SIZE); + an2Tbl = (Table){offset}; + offset = addU16U8(offset, TAB_SIZE); + an3Tbl = (Table){offset}; + offset = addU16U8(offset, TAB_SIZE); + + // Initialize filter ID EEPROM addresses + id1Addr = offset; + offset = addU16U8(offset, sizeof(CanId)); + id2Addr = offset; + offset = addU16U8(offset, sizeof(CanId)); + id3Addr = offset; + offset = addU16U8(offset, sizeof(CanId)); + id4Addr = offset; + offset = addU16U8(offset, sizeof(CanId)); + id5Addr = offset; + offset = addU16U8(offset, sizeof(CanId)); + sysInit(); spiInit(); eepromInit(); + dacInit(); canInit(); for (;;) { diff --git a/fw/table.c b/fw/table.c new file mode 100644 index 0000000..a509082 --- /dev/null +++ b/fw/table.c @@ -0,0 +1,72 @@ +#include <xc.h> + +#include <stdint.h> + +#include "types.h" +#include "eeprom.h" + +#include "table.h" + +Status +tabWrite(const Table *tab, U8 k, U16 key, U16 val) { + if (k >= TAB_ROWS) { + return FAIL; + } + + U16 addr = addU16U8(tab->offset, k*TAB_ROW_SIZE); + U8 row[4u] = {key.lo, key.hi, val.lo, val.hi}; + return eepromWrite(addr, row, sizeof(row)); +} + +Status +tabRead(const Table *tab, U8 k, U16 *key, U16 *val) { + U16 addr; + U8 row[4u]; + Status status; + + if (k >= TAB_ROWS) { + return FAIL; + } + + addr = addU16U8(tab->offset, k*TAB_ROW_SIZE); + status = eepromRead(addr, row, sizeof(row)); + *key = (U16){.lo=row[0u], .hi=row[1u]}; + *val = (U16){.lo=row[2u], .hi=row[3u]}; + return status; +} + +Status +tabLookup(const Table *tab, U16 key, U16 *val) { + U8 k; + U16 tkey, tval1, tval2; + Status status; + I8 ord; + + // Search for key + for (k = 0u; (k < TAB_ROWS-1u); k++) { + status = tabRead(tab, k, &tkey, &tval1); + if (status != OK) { + return FAIL; + } + ord = cmpU16(key, tkey); + if (ord == 0u) { // found exact key + *val = tval1; + return OK; + } else if (ord > 0u) { // interpolate + status = tabRead(tab, k+1u, &tkey, &tval2); + if (status != OK) { + return FAIL; + } + // Mean: (tval1+tval2)/2 + *val = rshiftU16(addU16(tval1, tval2), 1u); + return OK; + } else { // less + // continue + } + } + + // Reached last row + *val = tval1; // last value in table + + return OK; +} diff --git a/fw/table.h b/fw/table.h new file mode 100644 index 0000000..91e981a --- /dev/null +++ b/fw/table.h @@ -0,0 +1,41 @@ +/* Table datastructure for storing calibrations in the EEPROM. + * + * A table has a fixed number of rows that define a key/value mapping. + * Keys and values are each U16. + * T: U16->U16 + * Numbers are stored little-endian. + * + * Keys must be monotonically increasing. + * + * Device: PIC16F1459 + * Compiler: XC8 v3.00 + * + * Usage: + * + * #include <stdint.h> + * #include "types.h" + * #include "table.h" + */ + +enum { + TAB_KEY_SIZE = 2, // U16 + TAB_VAL_SIZE = 2, // U16 + TAB_ROWS = 32, + TAB_ROW_SIZE = TAB_KEY_SIZE + TAB_VAL_SIZE, + TAB_SIZE = TAB_ROWS * TAB_ROW_SIZE, +}; + +typedef struct { + U16 offset; // starting address +} Table; + +// Set the key and value of row k. +Status tabWrite(const Table *tab, U8 k, U16 key, U16 val); + +// Read row k. +Status tabRead(const Table *tab, U8 k, U16 *key, U16 *val); + +// Lookup the value associated with given key. +// If key falls between two rows, the value is interpolated +// from the two adjacent. +Status tabLookup(const Table *tab, U16 key, U16 *val); diff --git a/fw/tests/system/dac_systest.c b/fw/tests/system/dac_systest.c index 8653f96..9497e3b 100644 --- a/fw/tests/system/dac_systest.c +++ b/fw/tests/system/dac_systest.c @@ -19,19 +19,3 @@ main(void) { } } - -void -__interrupt() isr(void) { - static U8 ctr = 0u; - static U16 level = {0, 0}; - - if (TMR1IF) { - ctr++; - if (ctr == 23u) { // 1s period - ctr = 0u; - dacSet1a(level); - addU16(&level, 50u); - } - TMR1IF = 0; - } -} @@ -4,16 +4,50 @@ #include "types.h" -void -addU16(U16 *a, U8 b) { - a->lo += b; +U16 +addU16(U16 a, U16 b) { + a.hi += b.hi; + a.lo += b.lo; if (STATUSbits.C) { - a->hi++; + a.hi++; } + return a; } -void -lshiftU16(U16 *a, U8 b) { - a->hi = (U8)(a->hi << b) | (a->lo >> (8u-b)); - a->lo <<= b; +U16 +addU16U8(U16 a, U8 b) { + a.lo += b; + if (STATUSbits.C) { + a.hi++; + } + return a; +} + +U16 +lshiftU16(U16 a, U8 b) { + a.hi = (U8)(a.hi << b) | (a.lo >> (8u-b)); + a.lo <<= b; + return a; +} + +U16 +rshiftU16(U16 a, U8 b) { + a.lo = (U8)((a.hi >> (8u-b)) << (8u-b)) | (U8)(a.lo >> b); + a.hi >>= b; + return a; +} + +I8 +cmpU16(U16 a, U16 b) { + if (a.hi > b.hi) { + return 1; + } else if (a.hi < b.hi) { + return -1; + } else if (a.lo > b.lo) { + return 1; + } else if (a.lo < b.lo) { + return -1; + } else { + return 0; + } } @@ -13,6 +13,7 @@ typedef enum { } Status; typedef uint8_t U8; +typedef int8_t I8; typedef struct { U8 hi, lo; @@ -21,8 +22,19 @@ typedef struct { // Little-endian 32-bit unsigned integer. typedef U8 U32[4]; -// *a = *a+b -void addU16(U16 *a, U8 b); +// a + b +U16 addU16(U16 a, U16 b); -// *a = *a<<b -void lshiftU16(U16 *a, U8 b); +// a + b +U16 addU16U8(U16 a, U8 b); + +// a << b +U16 lshiftU16(U16 a, U8 b); + +// a >> b +U16 rshiftU16(U16 a, U8 b); + +// -1 if a < b +// 0 if a == b +// +1 if a > b +I8 cmpU16(U16 a, U16 b); |