aboutsummaryrefslogtreecommitdiffstats
path: root/fw
diff options
context:
space:
mode:
Diffstat (limited to 'fw')
-rw-r--r--fw/dac.c2
-rw-r--r--fw/eeprom.c2
-rw-r--r--fw/main.c79
-rw-r--r--fw/table.c72
-rw-r--r--fw/table.h41
-rw-r--r--fw/tests/system/dac_systest.c16
-rw-r--r--fw/types.c50
-rw-r--r--fw/types.h20
8 files changed, 252 insertions, 30 deletions
diff --git a/fw/dac.c b/fw/dac.c
index 0c9fb90..aa83602 100644
--- a/fw/dac.c
+++ b/fw/dac.c
@@ -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) {
diff --git a/fw/main.c b/fw/main.c
index d035a02..3471d79 100644
--- a/fw/main.c
+++ b/fw/main.c
@@ -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;
- }
-}
diff --git a/fw/types.c b/fw/types.c
index d87c891..1064379 100644
--- a/fw/types.c
+++ b/fw/types.c
@@ -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;
+ }
}
diff --git a/fw/types.h b/fw/types.h
index ccdf0ae..7532c6b 100644
--- a/fw/types.h
+++ b/fw/types.h
@@ -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);