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_sensor.cpp	Tue Apr 08 16:34:20 2014 +0000
@@ -0,0 +1,477 @@
+#include <string.h>
+#include <stdint.h>
+#include "mbed.h"
+#include "sens_itf.h"
+#include "sens_util.h"
+#include "../util/buf_io.h"
+#include "../util/crc16.h"
+#include "../pt/pt.h"
+#include "SLCD.h"
+#include "MMA8451Q.h"
+
+#define SENS_ITF_SENSOR_DBG_FRAME     1
+#define SENS_ITF_DBG_FRAME 1
+#define SENS_ITF_SENSOR_NUM_OF_POINTS 5
+
+#define MMA8451_I2C_ADDRESS (0x1d<<1)
+
+static uint8_t main_svr_addr[SENS_ITF_SERVER_ADDR_SIZE];
+static uint8_t secon_svr_addr[SENS_ITF_SERVER_ADDR_SIZE];
+static uint8_t rx_frame[SENS_ITF_MAX_FRAME_SIZE];
+static volatile uint8_t num_rx_bytes;
+static Timeout rx_trmout_timer ;
+static Ticker acq_data_timer;
+static sens_itf_point_ctrl_t sensor_points;
+static sens_itf_cmd_brd_id_t board_info;
+static struct pt pt_updt;
+static struct pt pt_data;
+static volatile uint8_t frame_timeout;
+static volatile uint8_t acq_data ;
+static DigitalOut  greenLED(LED1);
+static DigitalOut  redLED(LED2);
+static AnalogIn    lightSensor(PTE22);
+static SLCD        sLCD;
+static Serial      pcSerial(USBTX, USBRX);
+static MMA8451Q    acc(PTE25, PTE24, MMA8451_I2C_ADDRESS);
+static InterruptIn mode_switch(SW3);    
+static volatile uint8_t  view_mode;
+
+void scroll_message(char *message, unsigned char len)
+{
+    sLCD.All_Segments(0);
+    
+    for (int start = 0; start < len - 4; start++)
+    {
+        for (int digit = 0; digit < 4; digit++)
+            sLCD.putc(message[start + digit]);
+        wait(0.4);
+    }
+}
+
+static void dump_frame(uint8_t *frame, uint8_t size)
+{
+	int n,m;
+	char buf[64];
+	
+	buf[0] = buf[1] = buf[2] = buf[3] = ' ';
+	
+	for(n = 0, m = 4; n < size ; n++, m+=3)
+	{
+		sprintf(&buf[m],"%02X_",frame[n]);
+	}
+	
+	buf[m] = buf[m+1] = buf[m+2] = buf[m+3] = ' ';
+	buf[m+4] = '\0';
+	
+	m +=4;
+	scroll_message(buf,m);
+	
+}
+	
+static uint8_t sens_itf_get_point_type(uint8_t point)
+{
+    return sensor_points.points[point].desc.type;
+}
+
+static uint8_t sens_itf_get_number_of_points(void)
+{
+    return SENS_ITF_SENSOR_NUM_OF_POINTS;
+}
+
+static sens_itf_cmd_point_desc_t *sens_itf_get_point_desc(uint8_t point)
+{
+    sens_itf_cmd_point_desc_t *d = 0;
+
+    if (point < sens_itf_get_number_of_points())
+        d = &sensor_points.points[point].desc;
+
+    return d;
+}
+
+static sens_itf_cmd_point_t *sens_itf_get_point_value(uint8_t point)
+{
+    sens_itf_cmd_point_t *v = 0;
+
+    if (point < sens_itf_get_number_of_points())
+        v = &sensor_points.points[point].value;
+
+    return v;
+}
+
+static uint8_t sens_itf_set_point_value(uint8_t point, sens_itf_cmd_point_t *v)
+{
+    uint8_t ret = 0;
+
+    if (point < sens_itf_get_number_of_points())
+    {
+        sensor_points.points[point].value = *v;
+        ret = 1;
+    }
+    else
+    {
+        ret = 0;
+    }
+
+    return ret;
+}
+
+static sens_itf_cmd_brd_id_t *sens_itf_get_board_info(void)
+{
+    return &board_info;
+}
+
+static uint8_t sens_itf_sensor_send_frame(uint8_t *frame, uint8_t size)
+{
+    //dump_frame(frame, size);
+    
+    for(int n = 0 ; n < size ; n++)
+    	pcSerial.putc((unsigned int )frame[n]);
+    //pcSerial.puts((char *)frame,size); // puts returns the size sent ?
+    return size;
+}
+
+static uint8_t sens_itf_sensor_check_register_map(sens_itf_cmd_req_t *cmd, sens_itf_cmd_res_t *ans, uint8_t *frame)
+{
+    uint8_t size = 0;
+    if ( // check global register map for valid address ranges
+                ((cmd->hdr.addr > SENS_ITF_REGMAP_SVR_SEC_ADDR) && 
+                (cmd->hdr.addr < SENS_ITF_REGMAP_POINT_DESC_1)) ||
+                (cmd->hdr.addr > SENS_ITF_REGMAP_WRITE_POINT_DATA_32) ||
+                // check local register map - reading
+                ((cmd->hdr.addr >= SENS_ITF_REGMAP_READ_POINT_DATA_1) && 
+                (cmd->hdr.addr <= SENS_ITF_REGMAP_READ_POINT_DATA_32) &&
+                ((cmd->hdr.addr - SENS_ITF_REGMAP_READ_POINT_DATA_1) >= sens_itf_get_number_of_points())) ||
+                // check local register map - writing
+                ((cmd->hdr.addr >= SENS_ITF_REGMAP_WRITE_POINT_DATA_1) && 
+                (cmd->hdr.addr <= SENS_ITF_REGMAP_WRITE_POINT_DATA_32) &&
+                ((cmd->hdr.addr - SENS_ITF_REGMAP_WRITE_POINT_DATA_1) >= sens_itf_get_number_of_points())))
+    {
+        sens_util_log(SENS_ITF_SENSOR_DBG_FRAME, "Invalid register address %02X",cmd->hdr.addr);
+        ans->hdr.status = SENS_ITF_ANS_REGISTER_NOT_IMPLEMENTED;
+        size = sens_itf_pack_cmd_res(ans, frame);
+    }
+    return size;
+}
+
+static uint8_t sens_itf_sensor_writings(sens_itf_cmd_req_t *cmd, sens_itf_cmd_res_t *ans, uint8_t *frame)
+{
+    uint8_t size = 0;
+    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;
+        //sLCD.printf("R%dV%d",point,cmd->payload.point_value_cmd.value.u8);
+        //wait(0.5);
+        uint8_t acr = sens_itf_get_point_desc(point)->access_rights & SENS_ITF_ACCESS_WRITE_ONLY;
+            
+        if (acr)
+        {
+            ans->hdr.status = SENS_ITF_ANS_OK;
+            sens_itf_set_point_value(point,&cmd->payload.point_value_cmd);
+        }
+        else
+        {
+            sens_util_log(SENS_ITF_SENSOR_DBG_FRAME, "Point %d does not allow writings",point);                
+            ans->hdr.status = SENS_ITF_ANS_READY_ONLY;
+        }
+        size = sens_itf_pack_cmd_res(ans, frame);
+    }
+    return size;
+}
+
+static uint8_t sens_itf_sensor_readings(sens_itf_cmd_req_t *cmd, sens_itf_cmd_res_t *ans, uint8_t *frame)
+{
+    uint8_t size = 0;
+    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;
+        uint8_t acr = sens_itf_get_point_desc(point)->access_rights & SENS_ITF_ANS_READY_ONLY;
+            
+        if (acr)
+        {
+            ans->hdr.status = SENS_ITF_ANS_OK;
+            ans->payload.point_value_cmd = *sens_itf_get_point_value(point);
+        }
+        else
+        {
+            sens_util_log(SENS_ITF_SENSOR_DBG_FRAME, "Point %d does not allow readings",point);                
+            ans->hdr.status = SENS_ITF_ANS_WRITE_ONLY;
+        }
+        size = sens_itf_pack_cmd_res(ans, frame);
+    }
+    return size;
+}
+
+static uint8_t sens_itf_check_other_cmds(sens_itf_cmd_req_t *cmd, sens_itf_cmd_res_t *ans, uint8_t *frame)
+{
+    uint8_t size = 0;
+    switch (cmd->hdr.addr)
+    {
+        case SENS_ITF_REGMAP_ITF_VERSION:
+            ans->payload.itf_version_cmd.version = SENS_ITF_LATEST_VERSION;
+            break;
+        case SENS_ITF_REGMAP_BRD_ID:
+            memcpy(&ans->payload.brd_id_cmd,sens_itf_get_board_info(),sizeof(sens_itf_cmd_brd_id_t));
+            break;
+        case SENS_ITF_REGMAP_BRD_STATUS:
+            ans->payload.brd_status_cmd.status = 0; // TBD
+            break;
+        case SENS_ITF_REGMAP_BRD_CMD:
+            ans->payload.command_res_cmd.status = 0; // TBD
+            break;
+        case SENS_ITF_REGMAP_READ_BAT_STATUS:
+            ans->payload.bat_status_cmd.status = 0; // TBD
+            break;
+        case SENS_ITF_REGMAP_READ_BAT_CHARGE:
+            ans->payload.bat_charge_cmd.charge = 100; // TBD
+            break;
+        case SENS_ITF_REGMAP_SVR_MAIN_ADDR:
+            memcpy(ans->payload.svr_addr_cmd.addr,main_svr_addr, SENS_ITF_SERVER_ADDR_SIZE); 
+            break;
+        case SENS_ITF_REGMAP_SVR_SEC_ADDR:
+            memcpy(ans->payload.svr_addr_cmd.addr,secon_svr_addr, 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(&ans->payload.point_desc_cmd, &sensor_points.points[point].desc, sizeof(sens_itf_cmd_point_desc_t));
+    }
+        
+    ans->hdr.status = SENS_ITF_ANS_OK;
+    size = sens_itf_pack_cmd_res(ans, frame);
+    return size;
+}
+static void sens_itf_process_cmd(uint8_t *frame, uint8_t num_rx_bytes)
+{
+    uint8_t ret;
+    uint8_t size = 0;
+    sens_itf_cmd_req_t cmd;
+    sens_itf_cmd_res_t ans;
+
+    ret = sens_itf_unpack_cmd_req(&cmd, frame, num_rx_bytes);
+
+    if (ret > 0)
+    {
+        ans.hdr.addr = cmd.hdr.addr;
+        
+        size = sens_itf_sensor_check_register_map(&cmd, &ans,frame);
+        if (size == 0)
+            size = sens_itf_sensor_writings(&cmd, &ans,frame);
+
+        if (size == 0)
+            size = sens_itf_sensor_readings(&cmd, &ans,frame);
+ 
+        if (size == 0)
+            size = sens_itf_check_other_cmds(&cmd, &ans,frame);
+
+        if (size == 0)
+        {
+            ans.hdr.status = SENS_ITF_ANS_ERROR;
+            sLCD.printf("   D");
+        }
+ 
+        size = sens_itf_pack_cmd_res(&ans,frame);
+        sens_itf_sensor_send_frame(frame, size);
+    }
+}
+
+void sens_itf_init_point_db(void)
+{
+    uint8_t n;
+    char *point_names[SENS_ITF_POINT_NAME_SIZE] = { "LIGHT", "LEDG", "ACCX", "ACCY", "ACCXZ" };
+    uint8_t data_types[SENS_ITF_POINT_NAME_SIZE] = {SENS_ITF_DT_U8, SENS_ITF_DT_U8, SENS_ITF_DT_FLOAT, SENS_ITF_DT_FLOAT, SENS_ITF_DT_FLOAT};
+    uint8_t access_rights[SENS_ITF_POINT_NAME_SIZE] = { SENS_ITF_ACCESS_READ_ONLY, SENS_ITF_ACCESS_WRITE_ONLY, SENS_ITF_ACCESS_READ_ONLY,
+        SENS_ITF_ACCESS_READ_ONLY, SENS_ITF_ACCESS_READ_ONLY};
+    uint32_t sampling_time[SENS_ITF_POINT_NAME_SIZE] = {4*10, 0, 4*15, 4*20, 4*25};
+
+	memset(&sensor_points, 0, sizeof(sensor_points));
+	memset(&board_info, 0, sizeof(board_info));
+	
+    strcpy((char *)board_info.model, "KL46Z");
+    strcpy((char *)board_info.manufactor, "TESLA");
+    board_info.sensor_id = 0xDEADBEEF;
+    board_info.hardware_revision = 0x01;
+    board_info.num_of_points = SENS_ITF_SENSOR_NUM_OF_POINTS;
+    board_info.cabalities = SENS_ITF_CAPABILITIES_DISPLAY |
+        SENS_ITF_CAPABILITIES_WPAN_STATUS | 
+        SENS_ITF_CAPABILITIES_BATTERY_STATUS;
+
+    sensor_points.num_of_points = SENS_ITF_SENSOR_NUM_OF_POINTS;
+
+    for (n = 0; n < SENS_ITF_SENSOR_NUM_OF_POINTS; n++)
+    {
+        strcpy((char *)sensor_points.points[n].desc.name, point_names[n]);
+        sensor_points.points[n].desc.type = data_types[n];
+        sensor_points.points[n].desc.unit = 0; // TDB
+        sensor_points.points[n].desc.access_rights = access_rights[n];
+        sensor_points.points[n].desc.sampling_time_x250ms = sampling_time[n];
+        sensor_points.points[n].value.type = data_types[n];
+    }
+}
+
+static void sens_itf_rx_tmrout_timer_func(void)
+{
+	//greenLED = greenLED == 1 ? 0 : 1; 
+    frame_timeout = 1;
+}
+
+static void sens_itf_acq_data_timer_func(void)
+{
+    redLED = redLED == 1 ? 0 : 1;   
+    acq_data = 1;
+}
+
+static void sens_itf_rx_tmrout_timer_reesched(void)
+{
+	rx_trmout_timer.detach();
+	rx_trmout_timer.attach_us(sens_itf_rx_tmrout_timer_func,500*1000);
+}
+
+// Serial or SPI interrupt, called when a new byte is received
+static void sens_itf_sensor_rx_byte(void)
+{
+    uint8_t value;
+    
+    // DISABLE INTERRUPTS
+    if (frame_timeout)
+        return;
+
+	value = (uint8_t) pcSerial.getc();
+	
+    if (num_rx_bytes < SENS_ITF_MAX_FRAME_SIZE)
+        rx_frame[num_rx_bytes] = value;
+    
+    num_rx_bytes++;
+    if (num_rx_bytes >= SENS_ITF_MAX_FRAME_SIZE)
+        num_rx_bytes = 0;
+
+    sens_itf_rx_tmrout_timer_reesched();
+    // ENABLE INTERRUPTS
+}
+
+uint8_t sens_itf_sensor_init(void)
+{
+
+    sens_itf_init_point_db();
+    memcpy(main_svr_addr,"1212121212121212",SENS_ITF_SERVER_ADDR_SIZE);
+    memcpy(secon_svr_addr,"aabbccddeeff1122",SENS_ITF_SERVER_ADDR_SIZE);
+    num_rx_bytes = 0;
+    acq_data = 0;
+    frame_timeout = 0;
+    greenLED = 0; 
+    redLED = 1;
+    sens_itf_rx_tmrout_timer_reesched();
+    acq_data_timer.attach(sens_itf_acq_data_timer_func,2);
+	pcSerial.attach(sens_itf_sensor_rx_byte);
+	
+    return 1;
+}
+
+static int pt_data_func(struct pt *pt)
+{
+    PT_BEGIN(pt);
+
+    while (1)
+    {
+        // wait a frame timeout
+        PT_WAIT_UNTIL(pt, frame_timeout == 1);
+
+        if (num_rx_bytes > 0)
+        {
+            // process it
+            sens_itf_process_cmd(rx_frame, num_rx_bytes);
+            num_rx_bytes = 0;
+        }
+
+        // restart reception
+        frame_timeout = 0;
+        sens_itf_rx_tmrout_timer_reesched();
+    }
+
+    PT_END(pt);
+}
+
+static int pt_updt_func(struct pt *pt)
+{
+    PT_BEGIN(pt);
+
+    while (1)
+    {
+	    char buf[5];    
+	    uint8_t v;
+	    
+        // wait job
+        PT_WAIT_UNTIL(pt, acq_data == 1);
+
+	    v = (uint8_t)(lightSensor.read()*100);  
+	    sensor_points.points[0].value.value.u8 = v;
+	    greenLED = sensor_points.points[1].value.value.u8;
+	    sensor_points.points[2].value.value.fp32 = 1.0 - abs(acc.getAccX());
+	    sensor_points.points[3].value.value.fp32 = 1.0 - abs(acc.getAccY());
+	    sensor_points.points[4].value.value.fp32 = 1.0 - abs(acc.getAccZ());
+	    
+	    sLCD.All_Segments(0);
+	    switch(view_mode)
+	    {
+	    	case 0:
+			  	sprintf(buf,"L %2d",v);
+	    		sLCD.printf("%s",buf);   	
+	    		break;
+	    	case 1:
+			  	sprintf(buf,"%4d",(uint16_t) (sensor_points.points[2].value.value.fp32*1000));
+	    		sLCD.printf("%s",buf);   	
+	    		break;
+	    	case 2:
+			  	sprintf(buf,"%4d",(uint16_t) (sensor_points.points[3].value.value.fp32*1000));
+	    		sLCD.printf("%s",buf);   	
+	    		break;
+	    	case 3:
+			  	sprintf(buf,"%4d",(uint16_t) (sensor_points.points[4].value.value.fp32*1000));
+	    		sLCD.printf("%s",buf);   	
+	    		break;
+	    	default:
+	  		  	break;	
+	    }
+   
+        acq_data = 0;
+    }
+
+    PT_END(pt);
+}
+
+void set_mode(void)
+{
+	view_mode = ++view_mode > 3 ? 0 : view_mode;
+}
+
+void main(void)
+{
+    frame_timeout = 0;
+    acq_data = 0;
+    view_mode = 0;
+
+    sLCD.All_Segments(0); 
+    sLCD.DP2(0);
+    sLCD.printf("INIT"); 
+	pcSerial.baud(115200);
+    sens_itf_sensor_init();
+    
+    mode_switch.rise(set_mode);
+    
+    PT_INIT(&pt_data);
+    PT_INIT(&pt_updt);
+
+	
+    while(1)
+    {
+        pt_data_func(&pt_data);
+        pt_updt_func(&pt_updt);
+    }    
+}
+