diff options
Diffstat (limited to 'fw/main.c')
| -rw-r--r-- | fw/main.c | 167 |
1 files changed, 125 insertions, 42 deletions
@@ -2,6 +2,7 @@ #include <stdbool.h> #include <stdint.h> +#include <string.h> #include "system.h" #include "types.h" @@ -14,10 +15,22 @@ // TODO: auto baud detection #define CAN_TIMING CAN_TIMING_10K +// Parameters +typedef enum { + TACH = 0, + SPEED, + AN1, + AN2, + AN3, + AN4, + + NPARAM, +} Param; + // Table Control filter. // Used for writing/reading calibration tables. static const CanId tblCtrlFilter = { - .type = CAN_ID_EXT, + .isExt = true, .eid = {0x00, 0x20, 0x27, 0x01}, // 12720XXh }; @@ -25,7 +38,7 @@ static const CanId tblCtrlFilter = { // Used for writing/reading the CAN ID associated with each parameter. // See `doc/datafmt.ps'. static const CanId idCtrlFilter = { - .type = CAN_ID_EXT, + .isExt = true, .eid = {0x00, 0x21, 0x27, 0x01}, // 127210Xh }; @@ -34,7 +47,7 @@ static const CanId idCtrlFilter = { // and CAN IDs for each parameter. // This mask is the union of the two control message filters. static const CanId rxb0Mask = { - .type = CAN_ID_EXT, + .isExt = true, .eid = {0x00, 0x21, 0x27, 0x01}, // 1272100h }; @@ -42,7 +55,7 @@ static const CanId rxb0Mask = { // RXB1 is used for receiving parameter values. // The mask is permissive: all messages are accepted and filtered in software. static const CanId rxb1Mask = { - .type = CAN_ID_EXT, + .isExt = true, .eid = {0u, 0u, 0u, 0u}, // accept all messages }; @@ -58,53 +71,33 @@ static const Table an4Tbl = {{0x05, 0x00}}; // EEPROM address of CAN ID for each parameter. // Each of these addresses holds a U32 CAN ID. -static const EepromAddr tachIdAddr = {0x06, 0x00}; // tachometer -static const EepromAddr speedIdAddr = {0x06, 0x04}; // speedometer -static const EepromAddr an1IdAddr = {0x06, 0x08}; // analog channels... -static const EepromAddr an2IdAddr = {0x06, 0x0C}; -static const EepromAddr an3IdAddr = {0x06, 0x10}; -static const EepromAddr an4IdAddr = {0x06, 0x14}; - -static volatile CanId tachId; // tachometer -static volatile CanId speedId; // speedometer -static volatile CanId an1Id; // analog channels... -static volatile CanId an2Id; -static volatile CanId an3Id; -static volatile CanId an4Id; +static const EepromAddr paramIdAddrs[NPARAM] = { + [TACH] = {0x06, 0x00}, // tachometer + [SPEED] = {0x06, 0x04}, // speedometer + [AN1] = {0x06, 0x08}, // analog channels... + [AN2] = {0x06, 0x0C}, + [AN3] = {0x06, 0x10}, + [AN4] = {0x06, 0x14}, +}; + +// CAN ID of each parameter +static volatile CanId paramIds[NPARAM]; // Load parameters' CAN IDs from EEPROM static Status loadParamIds(void) { - U8 oldGie; + U8 oldGie, k; Status status; // Disable interrupts so the volatile address pointers can be passed safely oldGie = INTCONbits.GIE; INTCONbits.GIE = 0; - status = eepromReadCanId(tachIdAddr, (CanId*)&tachId); - if (status != OK) { - return FAIL; - } - status = eepromReadCanId(speedIdAddr, (CanId*)&speedId); - if (status != OK) { - return FAIL; - } - status = eepromReadCanId(an1IdAddr, (CanId*)&an1Id); - if (status != OK) { - return FAIL; - } - status = eepromReadCanId(an2IdAddr, (CanId*)&an2Id); - if (status != OK) { - return FAIL; - } - status = eepromReadCanId(an3IdAddr, (CanId*)&an3Id); - if (status != OK) { - return FAIL; - } - status = eepromReadCanId(an4IdAddr, (CanId*)&an4Id); - if (status != OK) { - return FAIL; + for (k = 0u; k < NPARAM; k++) { + status = eepromReadCanId(paramIdAddrs[k], (CanId*)¶mIds[k]); + if (status != OK) { + return FAIL; + } } // Restore previous interrupt setting @@ -163,11 +156,101 @@ handleTblCtrlFrame(const CanFrame *frame) { // TODO } +// Transmit the response to an ID Control REMOTE FRAME. +// The response is an ID Control DATA FRAME containing the CAN ID +// of the requested parameter. +static Status +respondIdCtrl(Param param) { + CanFrame response; + CanId paramId; + Status status; + + // Read parameter's CAN ID from EEPROM + if ((U8)param < NPARAM) { + status = eepromReadCanId(paramIdAddrs[param], ¶mId); + if (status != OK) { + return FAIL; // read failed + } + } else { + return FAIL; // invalid parameter + } + + // Pack param ID into response's DATA FIELD + response.id = (CanId) { + .isExt = true, + .eid = {param & 0xF, 0x21, 0x27, 0x01}, // 127210Xh + }; + response.rtr = false; + if (paramId.isExt) { // extended + response.dlc = 4u; // U32 + // BE <- LE + response.data[0u] = paramId.eid[3u] & 0x1F; + response.data[1u] = paramId.eid[2u]; + response.data[2u] = paramId.eid[1u]; + response.data[3u] = paramId.eid[0u]; + } else { // standard + response.dlc = 2u; // U16 + response.data[0u] = paramId.sid.hi & 0x7; + response.data[1u] = paramId.sid.lo; + } + + // Transmit response + return canTx(&response); +} + +// Set the CAN ID associated with a parameter in response to an ID Control DATA FRAME. +static Status +setParamId(const CanFrame *frame) { + CanId paramId; + Param param; + Status status; + + // Extract param ID from DATA FIELD + if (frame->dlc == 4u) { // extended + paramId.isExt = true; + // LE <- BE + paramId.eid[0u] = frame->data[3u]; + paramId.eid[1u] = frame->data[2u]; + paramId.eid[2u] = frame->data[1u]; + paramId.eid[3u] = frame->data[0u] & 0x1F; + } else if (frame->dlc == 2u) { // standard + paramId.isExt = false; + paramId.sid.lo = frame->data[1u]; + paramId.sid.hi = frame->data[0u] & 0x7; + } else { + return FAIL; // invalid DLC + } + + // Extract param # from Control Frame's ID + param = frame->id.eid[0u] & 0xF; + if ((U8)param >= NPARAM) { + return FAIL; // invalid parameter + } + + // Update copy in EEPROM + status = eepromWriteCanId(paramIdAddrs[param], ¶mId); + if (status != OK) { + return FAIL; // write failed + } + + // Update copy in PIC's RAM + paramIds[param] = paramId; + + return OK; +} + // Handle an ID Control Frame. // See `doc/datafmt.ps' static Status handleIdCtrlFrame(const CanFrame *frame) { - // TODO + Param param; + + if (frame->rtr) { // REMOTE + param = frame->id.eid[0u] & 0xF; + return respondIdCtrl(param); // respond with the parameter's CAN ID + } else { // DATA + return setParamId(frame); + } } // Handle a frame potentially holding a parameter value. |