Generic communication interface between the wireless board (mote) and the sensor board. Any kind of sensor board can be connected to the mote using this specification given it provides a SPI peripheral, one input pin with interrupt capability and one digital output. The sensor board must implement a special register set from which all required information can be retrieved. Protocol: http://is.gd/wuQorh Github: http://is.gd/ySj1L9

Dependencies:   mbed-src

Revision:
1:acdf490d94a7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sens_itf/sens_itf.c	Tue Apr 08 16:34:20 2014 +0000
@@ -0,0 +1,407 @@
+#include <string.h>
+#include <stdint.h>
+#include "sens_itf.h"
+#include "../util/buf_io.h"
+#include "../util/crc16.h"
+
+#define SENS_ITF_DBG_FRAME 1
+
+uint8_t sens_itf_unpack_point_value(sens_itf_cmd_point_t *point, uint8_t *buf)
+{
+    uint8_t size = 0;
+
+    switch (point->type)
+    {
+    case SENS_ITF_DT_U8:
+        point->value.u8 = buf_io_get8_fl(buf);
+        size = 1;
+        break;
+    case SENS_ITF_DT_S8:
+        point->value.s8 = buf_io_get8_fl(buf);
+        size = 1;
+        break;
+    case SENS_ITF_DT_U16:
+        point->value.u16 = buf_io_get16_fl(buf);
+        size = 2;
+        break;
+    case SENS_ITF_DT_S16:
+        point->value.s16 = buf_io_get16_fl(buf);
+        size = 2;
+        break;
+    case SENS_ITF_DT_U32:
+        point->value.u32 = buf_io_get32_fl(buf);
+        size = 4;
+        break;
+    case SENS_ITF_DT_S32:
+        point->value.s32 = buf_io_get32_fl(buf);
+        size = 4;
+        break;
+    case SENS_ITF_DT_U64:
+        point->value.u64 = buf_io_get64_fl(buf);
+        size = 8;
+        break;
+    case SENS_ITF_DT_S64:
+        point->value.s64 = buf_io_get64_fl(buf);
+        size = 8;
+        break;
+    case SENS_ITF_DT_FLOAT:
+        point->value.fp32 = buf_io_getf_fl(buf);
+        size = 4;
+        break;
+    case SENS_ITF_DT_DOUBLE:
+        point->value.fp64 = buf_io_getd_fl(buf);
+        size = 8;
+        break;
+    default:
+        break;
+    }
+
+    return size;
+}
+
+uint8_t sens_itf_pack_point_value(const sens_itf_cmd_point_t *point, uint8_t *buf)
+{
+    uint8_t size = 0;
+
+    switch (point->type)
+    {
+    case SENS_ITF_DT_U8:
+        buf_io_put8_tl(point->value.u8, buf);
+        size = 1;
+        break;
+    case SENS_ITF_DT_S8:
+        buf_io_put8_tl(point->value.s8, buf);
+        size = 1;
+        break;
+    case SENS_ITF_DT_U16:
+        buf_io_put16_tl(point->value.u16, buf);
+        size = 2;
+        break;
+    case SENS_ITF_DT_S16:
+        buf_io_put16_tl(point->value.s16, buf);
+        size = 2;
+        break;
+    case SENS_ITF_DT_U32:
+        buf_io_put32_tl(point->value.u32, buf);
+        size = 4;
+        break;
+    case SENS_ITF_DT_S32:
+        buf_io_put32_tl(point->value.s32, buf);
+        size = 4;
+        break;
+    case SENS_ITF_DT_U64:
+        buf_io_put64_tl(point->value.u64, buf);
+        size = 8;
+        break;
+    case SENS_ITF_DT_S64:
+        buf_io_put64_tl(point->value.s64, buf);
+        size = 8;
+        break;
+    case SENS_ITF_DT_FLOAT:
+        buf_io_putf_tl(point->value.fp32, buf);
+        size = 4;
+        break;
+    case SENS_ITF_DT_DOUBLE:
+        buf_io_putd_tl(point->value.fp64, buf);
+        size = 8;
+        break;
+    default:
+        break;
+    }
+
+    return size;
+}
+
+uint8_t sens_itf_unpack_cmd_req(sens_itf_cmd_req_t *cmd, uint8_t *frame, uint8_t frame_size)
+{
+    uint8_t *buf = frame;
+    uint16_t crc;
+    uint16_t frame_crc;
+    uint8_t size;
+
+    if (frame_size < 3)
+    {
+        //OS_UTIL_LOG(SENS_ITF_DBG_FRAME, ("Invalid frame size %d", frame_size));
+        return 0;
+    }
+    
+    // minimal header decoding
+    cmd->hdr.size = buf_io_get8_fl_ap(buf);
+    cmd->hdr.addr = buf_io_get8_fl_ap(buf);
+
+    frame_crc = buf_io_get16_fl(&frame[cmd->hdr.size]);
+    crc = crc16_calc(frame, cmd->hdr.size);
+    cmd->crc = frame_crc;
+
+    if (frame_crc != crc)
+    {
+        //OS_UTIL_LOG(SENS_ITF_DBG_FRAME, ("Invalid CRC %04X <> %04X", frame_crc, crc));
+        return 0;
+    }
+    
+    switch (cmd->hdr.addr)
+    {
+    case SENS_ITF_REGMAP_BRD_CMD:
+        cmd->payload.command_cmd.cmd = buf_io_get8_fl_ap(buf);
+        break;
+    case SENS_ITF_REGMAP_WRITE_BAT_STATUS:
+        cmd->payload.bat_status_cmd.status = buf_io_get8_fl_ap(buf);
+        break;
+    case SENS_ITF_REGMAP_WRITE_BAT_CHARGE:
+        cmd->payload.bat_charge_cmd.charge = buf_io_get8_fl_ap(buf);
+        break;
+    case SENS_ITF_REGMAP_DSP_WRITE:
+        cmd->payload.write_display_cmd.line = buf_io_get8_fl_ap(buf);
+        memcpy(cmd->payload.write_display_cmd.msg,buf,SENS_ITF_DSP_MSG_MAX_SIZE);
+        buf += SENS_ITF_DSP_MSG_MAX_SIZE;
+        break;
+    case SENS_ITF_REGMAP_WPAN_STATUS:
+        cmd->payload.wpan_status_cmd.status = buf_io_get8_fl_ap(buf);
+        break;
+    case SENS_ITF_REGMAP_WPAN_STRENGTH:
+        cmd->payload.wpan_strength_cmd.strenght = buf_io_get8_fl_ap(buf);
+        break;
+    default:
+        break;
+    }
+
+    if ((cmd->hdr.addr >= SENS_ITF_REGMAP_WRITE_POINT_DATA_1) && 
+        (cmd->hdr.addr <= SENS_ITF_REGMAP_WRITE_POINT_DATA_32))
+    {
+        //uint8_t point = cmd->hdr.addr - SENS_ITF_REGMAP_WRITE_POINT_DATA_1;
+        cmd->payload.point_value_cmd.type =  buf_io_get8_fl_ap(buf);
+        buf += sens_itf_unpack_point_value(&cmd->payload.point_value_cmd, buf);
+    }
+
+    size = cmd->hdr.size + 2; // + crc 
+    return size;
+}
+
+uint8_t sens_itf_pack_cmd_res(sens_itf_cmd_res_t *cmd, uint8_t *frame)
+{
+    uint8_t *buf = &frame[1];
+    uint8_t size = 0;
+    uint16_t crc;
+
+    buf_io_put8_tl_ap(cmd->hdr.addr, buf);
+    buf_io_put8_tl_ap(cmd->hdr.status, buf);
+
+    // only fill command when status is OK, otherwise an error will be reported
+    if (cmd->hdr.status == SENS_ITF_ANS_OK)
+    {
+        switch (cmd->hdr.addr)
+        {
+        case SENS_ITF_REGMAP_ITF_VERSION:
+            buf_io_put8_tl_ap(cmd->payload.itf_version_cmd.version, buf);
+            break;
+        case SENS_ITF_REGMAP_BRD_ID:
+            memcpy(buf, cmd->payload.brd_id_cmd.model, SENS_ITF_MODEL_NAME_SIZE);
+            buf += SENS_ITF_MODEL_NAME_SIZE;
+            memcpy(buf, cmd->payload.brd_id_cmd.manufactor, SENS_ITF_MANUF_NAME_SIZE);
+            buf += SENS_ITF_MODEL_NAME_SIZE;
+            buf_io_put32_tl_ap(cmd->payload.brd_id_cmd.sensor_id, buf);
+            buf_io_put8_tl_ap(cmd->payload.brd_id_cmd.hardware_revision, buf);
+            buf_io_put8_tl_ap(cmd->payload.brd_id_cmd.num_of_points, buf);
+            buf_io_put8_tl_ap(cmd->payload.brd_id_cmd.cabalities, buf);
+            break;
+        case SENS_ITF_REGMAP_BRD_STATUS:
+            buf_io_put8_tl_ap(cmd->payload.brd_status_cmd.status, buf);
+            break;
+        case SENS_ITF_REGMAP_BRD_CMD:
+            buf_io_put8_tl_ap(cmd->payload.command_res_cmd.status, buf);
+            break;
+        case SENS_ITF_REGMAP_READ_BAT_STATUS:
+            buf_io_put8_tl_ap(cmd->payload.bat_status_cmd.status, buf);
+            break;
+        case SENS_ITF_REGMAP_READ_BAT_CHARGE:
+            buf_io_put8_tl_ap(cmd->payload.bat_charge_cmd.charge, buf);
+            break;
+        case SENS_ITF_REGMAP_SVR_MAIN_ADDR:
+        case SENS_ITF_REGMAP_SVR_SEC_ADDR:
+            memcpy(buf, cmd->payload.svr_addr_cmd.addr, SENS_ITF_SERVER_ADDR_SIZE);
+            buf += SENS_ITF_SERVER_ADDR_SIZE;
+            break;
+        default:
+            break;
+        }
+
+        if ((cmd->hdr.addr >= SENS_ITF_REGMAP_POINT_DESC_1) &&
+            (cmd->hdr.addr <= SENS_ITF_REGMAP_POINT_DESC_32))
+        {
+            //uint8_t point = cmd->hdr.addr - SENS_ITF_REGMAP_POINT_DESC_1;
+            memcpy(buf, cmd->payload.point_desc_cmd.name, SENS_ITF_POINT_NAME_SIZE);
+            buf += SENS_ITF_POINT_NAME_SIZE;
+            buf_io_put8_tl_ap(cmd->payload.point_desc_cmd.type, buf);
+            buf_io_put8_tl_ap(cmd->payload.point_desc_cmd.unit, buf);
+            buf_io_put8_tl_ap(cmd->payload.point_desc_cmd.access_rights, buf);
+            buf_io_put32_tl_ap(cmd->payload.point_desc_cmd.sampling_time_x250ms, buf);
+        }
+
+        if ((cmd->hdr.addr >= SENS_ITF_REGMAP_READ_POINT_DATA_1) &&
+            (cmd->hdr.addr <= SENS_ITF_REGMAP_READ_POINT_DATA_32))
+        {
+            //uint8_t point = cmd->hdr.addr - SENS_ITF_REGMAP_READ_POINT_DATA_1;
+            buf_io_put8_tl_ap(cmd->payload.point_value_cmd.type,buf);
+            buf += sens_itf_pack_point_value(&cmd->payload.point_value_cmd, buf);
+        }
+    }
+
+    size = buf - frame;
+    buf_io_put8_tl(size, frame);
+    crc = crc16_calc(frame, size);
+    cmd->crc = crc;
+    cmd->hdr.size = size;
+    buf_io_put16_tl(crc, buf);
+    
+    size += 2; // +crc 
+    return size;
+}
+
+
+uint8_t sens_itf_unpack_cmd_res(sens_itf_cmd_res_t * cmd, uint8_t *frame, uint8_t frame_size)
+{
+    uint8_t size;
+    uint8_t *buf = frame;
+    uint16_t crc;
+    uint16_t frame_crc;
+
+    if (frame_size < 3)
+    {
+        cmd->hdr.status = SENS_ITF_ANS_ERROR;
+        return 0;
+    }
+    
+    // minimal header decoding
+    cmd->hdr.size = buf_io_get8_fl_ap(buf);
+    cmd->hdr.addr = buf_io_get8_fl_ap(buf);
+    cmd->hdr.status = buf_io_get8_fl_ap(buf);
+
+    frame_crc = buf_io_get16_fl(&frame[cmd->hdr.size]);
+    crc = crc16_calc(frame, cmd->hdr.size);
+    cmd->crc = frame_crc;
+
+    if (frame_crc != crc)
+    {
+        //OS_UTIL_LOG(SENS_ITF_DBG_FRAME, ("Invalid CRC %04X <> %04X", frame_crc, crc));
+        cmd->hdr.status = SENS_ITF_ANS_CRC_ERROR;
+        return 0;
+    }
+
+    if (cmd->hdr.status != SENS_ITF_ANS_OK)
+    {
+        //OS_UTIL_LOG(SENS_ITF_DBG_FRAME, ("Response error %d", cmd->hdr.status));
+        return 0;
+    }
+
+    switch (cmd->hdr.addr)
+    {
+    case SENS_ITF_REGMAP_ITF_VERSION:
+        cmd->payload.itf_version_cmd.version = buf_io_get8_fl_ap(buf);
+        break;
+    case SENS_ITF_REGMAP_BRD_ID:
+        memcpy(cmd->payload.brd_id_cmd.model, buf, SENS_ITF_MODEL_NAME_SIZE);
+        buf += SENS_ITF_MODEL_NAME_SIZE;
+        memcpy(cmd->payload.brd_id_cmd.manufactor, buf, SENS_ITF_MANUF_NAME_SIZE);
+        buf += SENS_ITF_MODEL_NAME_SIZE;
+        cmd->payload.brd_id_cmd.sensor_id = buf_io_get32_fl_ap(buf);
+        cmd->payload.brd_id_cmd.hardware_revision = buf_io_get8_fl_ap(buf);
+        cmd->payload.brd_id_cmd.num_of_points = buf_io_get8_fl_ap(buf);
+        cmd->payload.brd_id_cmd.cabalities = buf_io_get8_fl_ap(buf);
+        break;
+    case SENS_ITF_REGMAP_BRD_STATUS:
+        cmd->payload.brd_status_cmd.status = buf_io_get8_fl_ap(buf);
+        break;
+    case SENS_ITF_REGMAP_BRD_CMD:
+        cmd->payload.command_res_cmd.status = buf_io_get8_fl_ap(buf);
+        break;
+    case SENS_ITF_REGMAP_READ_BAT_STATUS:
+        cmd->payload.bat_status_cmd.status = buf_io_get8_fl_ap(buf);
+        break;
+    case SENS_ITF_REGMAP_READ_BAT_CHARGE:
+        cmd->payload.bat_charge_cmd.charge = buf_io_get8_fl_ap(buf);
+        break;
+    case SENS_ITF_REGMAP_SVR_MAIN_ADDR:
+    case SENS_ITF_REGMAP_SVR_SEC_ADDR:
+        memcpy(cmd->payload.svr_addr_cmd.addr, buf, SENS_ITF_SERVER_ADDR_SIZE);
+        buf += SENS_ITF_SERVER_ADDR_SIZE;
+        break;
+    default:
+        break;
+    }
+
+    if ((cmd->hdr.addr >= SENS_ITF_REGMAP_POINT_DESC_1) && 
+        (cmd->hdr.addr <= SENS_ITF_REGMAP_POINT_DESC_32))
+    {
+        memcpy(cmd->payload.point_desc_cmd.name, buf, SENS_ITF_POINT_NAME_SIZE);
+        buf += SENS_ITF_POINT_NAME_SIZE;
+        cmd->payload.point_desc_cmd.type = buf_io_get8_fl_ap(buf);
+        cmd->payload.point_desc_cmd.unit = buf_io_get8_fl_ap(buf);
+        cmd->payload.point_desc_cmd.access_rights = buf_io_get8_fl_ap(buf);
+        cmd->payload.point_desc_cmd.sampling_time_x250ms = buf_io_get32_fl_ap(buf);
+    }
+
+    if ((cmd->hdr.addr >= SENS_ITF_REGMAP_READ_POINT_DATA_1) &&
+        (cmd->hdr.addr <= SENS_ITF_REGMAP_READ_POINT_DATA_32))
+    {
+        cmd->payload.point_value_cmd.type = buf_io_get8_fl_ap(buf);
+        buf += sens_itf_unpack_point_value(&cmd->payload.point_value_cmd, buf);
+    }
+
+    size = cmd->hdr.size + 2; // crc 
+    return size;
+}
+
+uint8_t sens_itf_pack_cmd_req(sens_itf_cmd_req_t *cmd, uint8_t *frame)
+{
+    uint8_t *buf = &frame[1];
+    uint8_t size = 0;
+    uint16_t crc;
+
+    // address
+    // commands without arguments are handled only with this line
+    buf_io_put8_tl_ap(cmd->hdr.addr, buf);
+    
+    switch (cmd->hdr.addr)
+    {
+    case SENS_ITF_REGMAP_BRD_CMD:
+        buf_io_put8_tl_ap(cmd->payload.command_cmd.cmd, buf);
+        break;
+    case SENS_ITF_REGMAP_WRITE_BAT_STATUS:
+        buf_io_put8_tl_ap(cmd->payload.bat_status_cmd.status, buf);
+        break;
+    case SENS_ITF_REGMAP_WRITE_BAT_CHARGE:
+        buf_io_put8_tl_ap(cmd->payload.bat_charge_cmd.charge, buf);
+        break;
+    case SENS_ITF_REGMAP_DSP_WRITE:
+        buf_io_put8_tl_ap(cmd->payload.write_display_cmd.line, buf);
+        memcpy(buf, cmd->payload.write_display_cmd.msg, SENS_ITF_DSP_MSG_MAX_SIZE);
+        buf += SENS_ITF_DSP_MSG_MAX_SIZE;
+        break;
+    case SENS_ITF_REGMAP_WPAN_STATUS:
+        buf_io_put8_tl_ap(cmd->payload.wpan_status_cmd.status,buf);
+        break;
+    case SENS_ITF_REGMAP_WPAN_STRENGTH:
+        buf_io_put8_tl_ap(cmd->payload.wpan_strength_cmd.strenght,buf);
+        break;
+    default:
+        break;
+    }
+
+    if ((cmd->hdr.addr >= SENS_ITF_REGMAP_WRITE_POINT_DATA_1) && 
+        (cmd->hdr.addr <= SENS_ITF_REGMAP_WRITE_POINT_DATA_32))
+    {
+        buf_io_put8_tl_ap(cmd->payload.point_value_cmd.type, buf);
+        buf += sens_itf_pack_point_value(&cmd->payload.point_value_cmd, buf);
+    }
+
+    size = buf - frame;
+    buf_io_put8_tl(size, frame);
+    crc = crc16_calc(frame, size);
+    cmd->crc = crc;
+    cmd->hdr.size = size;
+    buf_io_put16_tl(crc, buf);
+
+    size += 2; // + crc
+
+    return size;
+}