diff options
| author | Aditya Naik | 2020-04-27 16:13:09 -0400 |
|---|---|---|
| committer | Aditya Naik | 2020-05-14 11:03:33 -0400 |
| commit | f5109a42e901608515b57e5256f56a841a0a05c1 (patch) | |
| tree | b7bea963c1b6993695c50021af6db17c266fd4f8 | |
| parent | 42a683033594289ddc520dffec652967e366e785 (diff) | |
This CL adds structures for bookkeeping for dataflow based on the dataflow protocol. It also adds a master and slave-side implementation of a single root-to-tree path in the protocol, which involves SOR=1 (master denoting a slave send operation) and DOC=5 (slave denoting data send operation). CL includes dataflow status typedef, SOR code typedef, DOC/SOR encoding, transmitting and decoding, CTS/data encoding, transmitting and decoding.
Commit by: Aditya Naik
Reviewed by: None
Task list: 2cabf06b6a354e83aed9a1c7ff22bd14
49ca5b3a768a48778259d3a449890ccb
d34854d85c7947f5b63bc897136c6c28
88a636ba03c24d3bac77ccc9ab9822db
| -rw-r--r-- | .gitignore | 3 | ||||
| -rw-r--r-- | src/dataflow.h | 44 | ||||
| -rw-r--r-- | src/main-data.c | 397 |
3 files changed, 434 insertions, 10 deletions
@@ -11,4 +11,5 @@ uctrl-firmware.txt *.o *.bin *~ -MDK-ARM/
\ No newline at end of file +MDK-ARM/ +tmp.org
\ No newline at end of file diff --git a/src/dataflow.h b/src/dataflow.h index 15d15cd..700bbdc 100644 --- a/src/dataflow.h +++ b/src/dataflow.h @@ -1,5 +1,45 @@ +/* + * + * Dataflow Status Enumeration + * + * This typedef governs the dataflow state machine. Enums should be self explanatory + * + * TODO Handle other DF pathways for slave RX datapoint and slave RX command + * + * |------------+-----+----------------------------------------+---------------------+-------------------------| + * | Status | Int | Status Invariant | Action | Next Status | + * |------------+-----+----------------------------------------+---------------------+-------------------------| + * | DF_IDLE | 0 | Ready to send m2s_SOR | Send m2s_SOR | DF_RX_DOC or ??? | + * | DF_RX_DOC | 1 | Sent m2s_SOR; ready to receive s2m_DOC | Receive s2m_DOC | DF_CTS | + * | DF_CTS | 2 | Received m2s_SOR; ready to send DF_CTS | Send m2s_CTS | DF_RX_DATA or DF_RX_CMD | + * | DF_RX_DATA | 3 | Sent m2s_CTS; receive s2m_data | Receive s2m_data | DF_SUCCESS | + * | DF_RX_CMD | 4 | sent m2s_CTS receive s2m_command | Receive s2m_command | DF_SUCCESS | + * |------------+-----+----------------------------------------+---------------------+-------------------------| + * + * +*/ + typedef enum dataflow_status { - DATA_SUCCESS = 0, - DATA_FAIL = 1 + DF_IDLE = 0, + DF_RX_DOC = 1, + DF_CTS = 2, + DF_RX_DATA = 3, + DF_RX_CMD = 4, + DF_SUCCESS = 5, + DF_FAIL = 6 } dataflow_status_t; + +typedef enum SOR_codes { + SLAVE_TX = 1, + SLAVE_RX_DATAPOINT = 2, + SLAVE_RX_COMMAND = 3 +} SOR_codes_t; + +typedef enum DOC_codes { + CMD_UNICAST = 1, + CMD_MULTICAST = 2, + CMD_BROADCAST = 3, + RESERVED = 4, + DATA = 5 +} DOC_codes_t; diff --git a/src/main-data.c b/src/main-data.c index 4314e9e..5f45562 100644 --- a/src/main-data.c +++ b/src/main-data.c @@ -23,6 +23,7 @@ #include "config.h" #include "dataflow.h" #include "handshake.pb.h" +#include "data.pb.h" /* Private Macros */ #define device_MDR s2m_MDR_response @@ -45,6 +46,7 @@ device_info_t *device_info[BUS_DEVICE_LIMIT] = {NULL}; subscription_info_t* subs_info[BUS_DEVICE_LIMIT]; uint32_t allocated[4]={0}; uint8_t dev_sts[BUS_DEVICE_LIMIT] = {OFFLINE}; +uint8_t data_idx; /* Function prototypes */ void SystemClock_Config(void); @@ -54,12 +56,12 @@ static void MX_USART1_UART_Init(void); bool decode_subscriptions_callback(pb_istream_t *istream, const pb_field_t *field, void **args); hs_status_t handshake(uint32_t i2c_addr); -dataflow_status_t device_dataflow(uint8_t i2c_addr); +dataflow_status_t device_dataflow(uint8_t i2c_addr, uint32_t SOR_code); bool todo_hs_or_not_todo_hs(uint8_t i2c_addr); state_t get_state_from_hs_status(uint16_t device_addr, hs_status_t hs_status); bool encode_subscription_callback(pb_ostream_t *ostream, const pb_field_t *field, void * const *arg); - - +bool encode_datapoint_callback(pb_ostream_t *ostream, const pb_field_t *field, void * const *arg); +bool decode_data_callback(pb_istream_t *istream, const pb_field_t *field, void **args); /** * @brief The application entry point. * @retval int @@ -118,10 +120,103 @@ int main(void) device_info[dev_idx]->MDR = module_MDR; /* dataflow */ + device_dataflow(0x05, 1); #else /* Slave code*/ { - + uint8_t SOR_buf[m2s_SOR_size] = {0}, debug_buf[128], term[]="\r\n"; + if (HAL_I2C_Slave_Receive(&hi2c1, (uint8_t*)SOR_buf, m2s_SOR_size, 10000) != HAL_OK) { + sprintf((char*)debug_buf, "Failed to get SOR\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + } + else { + sprintf((char*)debug_buf, "Got SOR\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + } + m2s_SOR SOR_message; + pb_istream_t SOR_istream = pb_istream_from_buffer(SOR_buf, 2); + if (!pb_decode(&SOR_istream, m2s_SOR_fields, &SOR_message)) { + sprintf((char*)debug_buf, "SOR decode error\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + } + else { + sprintf((char*)debug_buf, "SOR decoded; code: %ld\r\n", SOR_message.SOR_code); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + } + + if (SOR_message.SOR_code == 1) { + uint8_t data_buf[128]; + size_t data_enc_size; + s2m_data data; + data.datapoints.funcs.encode = encode_datapoint_callback; + pb_ostream_t data_ostream = pb_ostream_from_buffer(data_buf, sizeof(data_buf)); + if (!pb_encode(&data_ostream, s2m_data_fields, &data)) { + sprintf((char*)debug_buf, "Data encoding error\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + Error_Handler(); + } + data_enc_size = data_ostream.bytes_written; + + s2m_DOC doc = s2m_DOC_init_zero; + uint8_t doc_buf[s2m_DOC_size]; + doc.DOC_code = 5; + doc.tx_length = data_enc_size; + pb_ostream_t doc_ostream = pb_ostream_from_buffer(doc_buf, 4); + + if (!pb_encode(&doc_ostream, s2m_DOC_fields, &doc)) { + sprintf((char*)debug_buf, "DOC encoding error\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + Error_Handler(); + } + + sprintf((char*)debug_buf, "s2m_DOC encoded length: %d\r\n", doc_ostream.bytes_written); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + + if (HAL_I2C_Slave_Transmit(&hi2c1, (uint8_t*)doc_buf, 4, 10000) != HAL_OK) { + sprintf((char*)debug_buf, "DOC I2C send error: %ld\r\n", HAL_I2C_GetError(&hi2c1)); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + Error_Handler(); + } + else { + sprintf((char*)debug_buf, "SENT DOC\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + } + + uint8_t CTS_buf[8]; + + if (HAL_I2C_Slave_Receive(&hi2c1, (uint8_t*)CTS_buf, 2, 10000) != HAL_OK) { + sprintf((char*)debug_buf, "Failed to get CTS: %ld\r\n", HAL_I2C_GetError(&hi2c1)); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + Error_Handler(); + } + else { + sprintf((char*)debug_buf, "Got CTS\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + } + + if (HAL_I2C_Slave_Transmit(&hi2c1, (uint8_t*)data_buf, data_enc_size, 10000) != HAL_OK) { + sprintf((char*)debug_buf, "Data I2C send error: %ld\r\n", HAL_I2C_GetError(&hi2c1)); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + Error_Handler(); + } + else { + sprintf((char*)debug_buf, "SENT DATA\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + } + } } #endif /* MASTER */ @@ -430,11 +525,251 @@ __DEBUG_BLOCK_END: return hs_sts; } -dataflow_status_t device_dataflow(uint8_t i2c_addr) +dataflow_status_t device_dataflow(uint8_t i2c_addr, uint32_t SOR_code) { - uint8_t dev_idx = GET_IDX_FROM_ADDR(i2c_addr); - dataflow_status_t status; + uint8_t dev_idx = GET_IDX_FROM_ADDR(i2c_addr); + dataflow_status_t df_status = DF_IDLE; + + uint8_t *SOR_buf, *DOC_buf, *CTS_buf, *data_buf; + uint32_t AF_error_counter = 0; + uint32_t data_len = 0; + _datapoint datapoints[16]; + m2s_SOR SOR_message = m2s_SOR_init_default; + s2m_DOC DOC_message = s2m_DOC_init_zero; + /* TODO Add default values to the CTS message in proto */ + m2s_CTS CTS_message = m2s_CTS_init_default; + s2m_data data_message = s2m_data_init_zero; +#if defined(TESTING_ENABLE) || defined(DEBUG_ENABLE) + uint8_t debug_buf[128]; +#endif +#ifdef TESTING_ENABLE + uint8_t term[] = "\r\n"; +#endif + + while (df_status != DF_SUCCESS && df_status != DF_FAIL) { + switch (df_status) { + case (DF_IDLE): + { + SOR_buf = malloc(sizeof(m2s_SOR)); + pb_ostream_t SOR_stream = pb_ostream_from_buffer(SOR_buf, sizeof(SOR_buf)); + SOR_message.SOR_code = SOR_code; + if (!pb_encode(&SOR_stream, m2s_SOR_fields, &SOR_message)) { + df_status = DF_FAIL; +#ifdef DEBUG_ENABLE + goto __DF_SOR_ENC_FAIL; + __DF_SOR_ENC_FAIL_END: + __asm__("nop"); +#endif + } + else { + if (HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)i2c_addr, (uint8_t*)SOR_buf, + m2s_SOR_size, 10000) != HAL_OK) { + df_status = DF_FAIL; +#ifdef DEBUG_ENABLE + goto __DF_SOR_I2C_ERROR; + __DF_SOR_I2C_ERROR_END: + __asm__("nop"); +#endif + } + else { + if (SOR_code == SLAVE_TX) { + df_status = DF_RX_DOC; + } + else if (SOR_code == SLAVE_RX_DATAPOINT) { + /* TODO */ + } + else if (SOR_code == SLAVE_RX_COMMAND) { + /* TODO */ + } + } + } + break; + } + case (DF_RX_DOC): + { + DOC_buf = (uint8_t*)malloc(4); + AF_error_counter = 0; + while (HAL_I2C_Master_Receive(&hi2c1, (uint16_t)i2c_addr, + (uint8_t*)DOC_buf, 4, 1000) != HAL_OK) { + if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF) { + df_status = DF_FAIL; +#ifdef DEBUG_ENABLE + goto __DF_DOC_I2C_ERROR; + __DF_DOC_I2C_ERROR_END: + __asm__("nop"); +#endif + break; + } + else if (++AF_error_counter > 4000) { + df_status = DF_FAIL; + break; + } + } + if (df_status != DF_FAIL) { + pb_istream_t DOC_istream = pb_istream_from_buffer(DOC_buf, 4); + if (!pb_decode(&DOC_istream, s2m_DOC_fields, &DOC_message)) { + df_status = DF_FAIL; +#ifdef DEBUG_ENABLE + goto __DF_DOC_DECODE_ERROR; + __DF_DOC_DECODE_ERROR_END: + __asm__("nop"); +#endif + } + else { + if (DOC_message.DOC_code == DATA) { + df_status = DF_CTS; + data_len = DOC_message.tx_length; + } + else if (DOC_message.DOC_code == CMD_UNICAST) { + /* TODO */ + } + else if (DOC_message.DOC_code == CMD_MULTICAST) { + /* TODO */ + } + else if (DOC_message.DOC_code == CMD_BROADCAST) { + /* TODO */ + } + } + } + break; + } + case (DF_CTS): + { + CTS_buf = (uint8_t*)malloc(8); + pb_ostream_t CTS_ostream = pb_ostream_from_buffer(CTS_buf, 8); + CTS_message.timeout = 100; + + if (!pb_encode(&CTS_ostream, m2s_CTS_fields, &CTS_message)) { + df_status = DF_FAIL; +#ifdef DEBUG_ENABLE + goto __DF_CTS_ENC_FAIL; + __DF_CTS_ENC_FAIL_END: + __asm__("nop"); +#endif + } + else { + HAL_Delay(100); + if (HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)i2c_addr, (uint8_t*)CTS_buf, + 2, 10000) != HAL_OK) { + df_status = DF_FAIL; +#ifdef DEBUG_ENABLE + goto __DF_CTS_I2C_ERROR; + __DF_CTS_I2C_ERROR_END: + __asm__("nop"); +#endif + } + else { + if (DOC_message.DOC_code == DATA) { + df_status = DF_RX_DATA; + } + else { + /* TODO */ + } + } + } + break; + } + case (DF_RX_DATA): + { + data_buf = (uint8_t*)malloc(128); + AF_error_counter = 0; + while (HAL_I2C_Master_Receive(&hi2c1, (uint16_t)i2c_addr, + (uint8_t*)data_buf, data_len, 10000) != HAL_OK) { + if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF) { + df_status = DF_FAIL; +#ifdef DEBUG_ENABLE + goto __DF_DATA_I2C_ERROR; + __DF_DATA_I2C_ERROR_END: + __asm__("nop"); +#endif + break; + } + else if (++AF_error_counter > 1500) { + df_status = DF_FAIL; + break; + } + } + if (df_status != DF_FAIL) { + data_idx = 0; + data_message.datapoints.funcs.decode = decode_data_callback; + data_message.datapoints.arg = (void*)datapoints; + pb_istream_t data_istream = pb_istream_from_buffer(data_buf, data_len); + if (!pb_decode(&data_istream, s2m_data_fields, &data_message)) { + df_status = DF_FAIL; +#ifdef DEBUG_ENABLE + goto __DF_DATA_DECODE_ERROR; + __DF_DATA_DECODE_ERROR_END: + __asm__("nop"); +#endif + } + else { + df_status = DF_SUCCESS; + } + } + break; + } + } + } + +#ifdef TESTING_ENABLE + { + goto __DF_TESTING_BLOCK_END; + + __DF_TESTING_BLOCK_END: + __asm__("nop"); + } +#endif + +#ifdef DEBUG_ENABLE + { + goto __DF_DEBUG_BLOCK_END; + __DF_SOR_ENC_FAIL: + sprintf((char*)debug_buf, "SOR encoding error\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + goto __DF_SOR_ENC_FAIL_END; + __DF_SOR_I2C_ERROR: + sprintf((char*)debug_buf, "Unable to send SOR request. I2C error: %ld\r\n", HAL_I2C_GetError(&hi2c1)); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + goto __DF_SOR_I2C_ERROR_END; + __DF_DOC_I2C_ERROR: + sprintf((char*)debug_buf, "Unable to receive DOC. I2C error: %ld\r\n", HAL_I2C_GetError(&hi2c1)); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + goto __DF_DOC_I2C_ERROR_END; + __DF_DOC_DECODE_ERROR: + sprintf((char*)debug_buf, "DOC decoding error\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + goto __DF_DOC_DECODE_ERROR_END; + __DF_CTS_ENC_FAIL: + sprintf((char*)debug_buf, "CTS encoding error\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + goto __DF_CTS_ENC_FAIL_END; + __DF_CTS_I2C_ERROR: + sprintf((char*)debug_buf, "CTS I2C error: %ld\r\n", HAL_I2C_GetError(&hi2c1)); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + goto __DF_CTS_I2C_ERROR_END; + __DF_DATA_I2C_ERROR: + sprintf((char*)debug_buf, "Unable to receive data. I2C error: %ld\r\n", HAL_I2C_GetError(&hi2c1)); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + goto __DF_DATA_I2C_ERROR_END; + __DF_DATA_DECODE_ERROR: + sprintf((char*)debug_buf, "Data decoding error\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + goto __DF_DATA_DECODE_ERROR_END; + __DF_DEBUG_BLOCK_END: + __asm__("nop"); + } +#endif + + return df_status; } bool decode_subscriptions_callback(pb_istream_t *istream, const pb_field_t *field, void **args) @@ -536,6 +871,54 @@ bool encode_subscription_callback(pb_ostream_t *ostream, const pb_field_t *field return true; } +bool encode_datapoint_callback(pb_ostream_t *ostream, const pb_field_t *field, void * const *arg) +{ + if (ostream != NULL && field->tag == s2m_data_datapoints_tag) { + for (int i = 0; i < 4; i++) { + _datapoint datapoint = _datapoint_init_zero; + datapoint.entity_id = 1; + datapoint.data = 20.70+((float)i/100); + if (!pb_encode_tag_for_field(ostream, field)) + return false; + if (!pb_encode_submessage(ostream, _datapoint_fields, &datapoint)) + return false; + } + } + else + return false; + return true; +} + +bool decode_data_callback(pb_istream_t *istream, const pb_field_t *field, void **args) +{ + _datapoint loc_datapoint = _datapoint_init_zero; + _datapoint *datapoint = *args; + + if (!pb_decode(istream, _datapoint_fields, &loc_datapoint)) + return false; + + datapoint[data_idx].data = datapoint[data_idx].entity_id = 0; + + datapoint[data_idx].entity_id = loc_datapoint.entity_id; + datapoint[data_idx].data = loc_datapoint.data; + + if (loc_datapoint.has_channel_id) { + datapoint[data_idx].has_channel_id = true; + datapoint[data_idx].channel_id = loc_datapoint.channel_id; + } + if (loc_datapoint.has_unit_id) { + datapoint[data_idx].has_unit_id = true; + datapoint[data_idx].unit_id = loc_datapoint.unit_id; + } + if (loc_datapoint.has_timestamp) { + datapoint[data_idx].has_timestamp = true; + datapoint[data_idx].timestamp = loc_datapoint.timestamp; + } + + data_idx++; + return true; +} + /** * @brief System Clock Configuration * @retval None |
