Framework for reading and writing variables in real time on any MBED platform.
DistantIO
This is the C implementation of the DistantIO slave framework.
Library is working but slight API breaks may occur in the future. C++ version is also in development.
To get the master-side implementation, see https://github.com/Overdrivr/DistantIO
distantio.cpp
- Committer:
- Overdrivr
- Date:
- 2015-10-16
- Revision:
- 6:72d46dbdbe7a
- Parent:
- 5:e8936f38a338
File content as of revision 6:72d46dbdbe7a:
/* * distantio.c * * Created on: Oct 13, 2014 * Author: B48923 */ #include "distantio.h" #include "crc.h" #include "string.h" #include "protocol.h" /* * WARNING : IMPLEMENTATION FOR LITTLE-ENDIAN PROCESSOR * TODO : HANDLE BOTH */ static log Log; uint32_t tmp; void _dIO_send_variable(uint16_t index,float extra_identifier_1,uint16_t extra_identifier_2=0); uint16_t _dIO_get_size(dio_type type); void _dIO_send_descriptor(uint16_t index); void _dIO_send_group_descriptor(uint16_t index); void dIO_init() { uint16_t i; char default_name[] = {"undef. "}; Log.amount = 0; for(i = 0 ; i < VARIABLES_AMOUNT ; i++) { Log.variables[i].size = 0; Log.variables[i].ptr = 0; Log.variables[i].writeable = 0; Log.variables[i].id = i; strncpy(Log.variables[i].name,default_name,NAMESIZE); Log.variables[i].send = 0; Log.variables[i].groupID = 0; } tmp=0; Log.current_group_id = 0; strncpy(Log.groups[0].name,"default",NAMESIZE); } uint8_t dIO_var(void* ptr, uint16_t size, dio_type type, uint8_t writeable, char* name, float refresh_rate) { // Too many variables, aborting if(Log.amount >= VARIABLES_AMOUNT) return 1; Log.variables[Log.amount].ptr = (uint8_t*) ptr; Log.variables[Log.amount].size = _dIO_get_size(type); Log.variables[Log.amount].writeable = writeable; Log.variables[Log.amount].type = type; Log.variables[Log.amount].groupID = Log.current_group_id; strncpy(Log.variables[Log.amount].name,name,NAMESIZE); Log.variables[Log.amount].refresh_rate = refresh_rate; Log.variables[Log.amount].last_refreshed = 0; Log.amount++; return 0; } void dIO_group(char* groupname) { Log.current_group_id++; strncpy(Log.groups[Log.current_group_id].name,groupname,NAMESIZE); } void dIO_decode(uint8_t* data,uint16_t datasize) { // First check data size if(datasize != FRAMESIZE) return; // Second, check CRC uint16_t crc_value = crc16(data,FRAMESIZE-2); uint16_t crc_rx = ((uint16_t)data[FRAMESIZE-2] << 8) | data[FRAMESIZE-1]; if(crc_value != crc_rx) return; // Process frame // First, identify command uint8_t command = data[0]; // Second, identify variable ID uint16_t ID = data[2] + (data[1] << 8); ID = (ID & 0x3FF); // Third, identify data type uint8_t type = data[3]; switch(command) { // User requested descriptors case 0x02: // Send variables for(uint16_t i = 0 ; i < Log.amount ; i++) _dIO_send_descriptor(i); // Send groups for(uint16_t i = 0 ; i <= Log.current_group_id ; i++) _dIO_send_group_descriptor(i); break; // User provided value to write case 0x04: if(ID >= Log.amount) return; if(Log.variables[ID].writeable == 0x00) return; if(Log.variables[ID].type != type) return; uint16_t start_address = DATASTART + DATASIZE - 1; // Copy contents directly into variable for(uint16_t i = 0 ; i < Log.variables[ID].size ; i++) { // Packet is big-endian, convert to little-endian uint8_t offset = start_address - i; *(Log.variables[ID].ptr + i) = *(data + offset); } break; // User requested variable read case 0x05: if(ID >= Log.amount) return; Log.variables[ID].send = 1; break; // User requested stop variable read case 0x06: if(ID >= Log.amount) return; Log.variables[ID].send = 0; break; } } void dIO_update(float current_time) { for(uint16_t i = 0 ; i < Log.amount ; i++) { if(Log.variables[i].send == 0) continue; if(current_time < Log.variables[i].last_refreshed + Log.variables[i].refresh_rate) continue; _dIO_send_variable(i,current_time); Log.variables[i].last_refreshed = current_time; } } void dIO_send_alive() { uint8_t buffer[FRAMESIZE]; buffer[0] = 0x03; // Compute crc uint16_t crc_value = crc16(buffer,FRAMESIZE - 2); // Write crc into buffer's last byte buffer[FRAMESIZE - 1] = crc_value & 0xFF; buffer[FRAMESIZE - 2] = (crc_value >> 8) & 0xFF; // Send frame to encoding encode(buffer,FRAMESIZE); } void dIO_emergency_send(void* ptr, uint16_t size, dio_type type, char* name, float recordingtime, uint16_t index) { uint8_t buffer[FRAMESIZE]; // Response code 0x09 buffer[0] = 0x09; // Write variable ID uint8_t * temp_ptr = (uint8_t*)(name); buffer[1] = *(temp_ptr + 1); buffer[2] = *(temp_ptr); // Write variable type buffer[3] = type; // Extra identifier 1 temp_ptr = (uint8_t*)(&recordingtime); buffer[4] = *(temp_ptr + 3); buffer[5] = *(temp_ptr + 2); buffer[6] = *(temp_ptr + 1); buffer[7] = *(temp_ptr ); // Extra identifier 2 temp_ptr = (uint8_t*)(&index); buffer[8] = *(temp_ptr + 1); buffer[9] = *(temp_ptr ); uint16_t i = 10; // Write data for(uint16_t k = 0 ; k < DATASIZE ; k++) { uint16_t off = DATASIZE - 1 - k; // Fill buffer with data if(off < size) { temp_ptr = (uint8_t*)(ptr) + off ; buffer[i++] = *temp_ptr; } // Fill remaining bits with 0 else { buffer[i++] = 0; } } // Compute crc uint16_t crc_value = crc16(buffer,i); // Write crc into buffer's last byte buffer[i++] = (crc_value >> 8) & 0xFF; buffer[i++] = crc_value & 0xFF; // Encode frame encode(buffer,i); } /* ------------------- PRIVATE FUNCTIONS ------------------ */ void _dIO_send_descriptor(uint16_t index) { if(index >= Log.amount) return; uint8_t buffer[FRAMESIZE]; uint8_t type; // Respond returned-descriptor buffer[0] = 0x00; // Write id uint16_t ID = ((Log.variables[index].groupID & 0x003F) << 10) + (index & 0x3FF); uint8_t * temp_ptr = (uint8_t*)(&ID); buffer[1] = *(temp_ptr + 1); buffer[2] = *(temp_ptr ); // Write type & writeable type = (uint8_t)(Log.variables[index].type); if(Log.variables[index].writeable) type += 0xF0; buffer[3] = type; //Write name uint16_t i = 4; // TODO : Replace with strncpy for(uint16_t k = 0 ; k < NAMESIZE ; k++) { if(k < strlen(Log.variables[index].name)) { buffer[i] = Log.variables[index].name[k]; i++; } else buffer[i++] = 0; } // Compute crc uint16_t crc_value = crc16(buffer,i); // Write crc into buffer's last byte buffer[i++] = (crc_value >> 8) & 0xFF; buffer[i++] = crc_value & 0xFF; // Encode frame encode(buffer,i); } void _dIO_send_group_descriptor(uint16_t index) { if(index > Log.current_group_id) return; uint8_t buffer[FRAMESIZE]; // Respond returned-descriptor buffer[0] = 0x00; // Write id uint16_t ID = (index & 0x3F) << 10; uint8_t * temp_ptr = (uint8_t*)(&ID); buffer[1] = *(temp_ptr + 1); buffer[2] = *(temp_ptr); // Write type buffer[3] = 0x07; //Write name uint16_t i = 4; for(uint16_t k = 0 ; k < NAMESIZE ; k++) { if(k < strlen(Log.groups[index].name)) { buffer[i] = Log.groups[index].name[k]; i++; } else buffer[i++] = 0; } // Compute crc uint16_t crc_value = crc16(buffer,i); // Write crc into buffer's last byte buffer[i++] = (crc_value >> 8) & 0xFF; buffer[i++] = crc_value & 0xFF; // Encode frame encode(buffer,i); } void _dIO_send_variable(uint16_t index,float extra_identifier_1,uint16_t extra_identifier_2) { if(index >= Log.amount) return; uint8_t buffer[FRAMESIZE]; // Response code 0x01 buffer[0] = 0x01; // Write variable ID uint16_t ID = ((Log.variables[index].groupID & 0x003F) << 10) + (index & 0x3FF); uint8_t * temp_ptr = (uint8_t*)(&ID); buffer[1] = *(temp_ptr + 1); buffer[2] = *(temp_ptr); // Write variable type buffer[3] = Log.variables[index].type; //TODO writeable // Extra identifier 1 temp_ptr = (uint8_t*)(&extra_identifier_1); buffer[4] = *(temp_ptr + 3); buffer[5] = *(temp_ptr + 2); buffer[6] = *(temp_ptr + 1); buffer[7] = *(temp_ptr ); // Extra identifier 2 temp_ptr = (uint8_t*)(&extra_identifier_2); buffer[8] = *(temp_ptr + 1); buffer[9] = *(temp_ptr ); uint16_t i = 10; // Write data for(uint16_t k = 0 ; k < DATASIZE ; k++) { uint16_t off = DATASIZE - 1 - k; // Fill buffer with data if(off < Log.variables[index].size) { temp_ptr = Log.variables[index].ptr + off ; buffer[i++] = *temp_ptr; } // Fill remaining bits with 0 else { buffer[i++] = 0; } } // Compute crc uint16_t crc_value = crc16(buffer,i); // Write crc into buffer's last byte buffer[i++] = (crc_value >> 8) & 0xFF; buffer[i++] = crc_value & 0xFF; // Encode frame encode(buffer,i); } uint16_t _dIO_get_size(dio_type type) { switch(type) { case dio_type_FLOAT: case dio_type_UINT32: case dio_type_INT32: return 4; case dio_type_UINT16: case dio_type_INT16: return 2; case dio_type_UINT8: case dio_type_INT8: default: return 1; } }