diff options
| author | Aditya Naik | 2020-06-17 16:55:22 -0400 |
|---|---|---|
| committer | Aditya Naik | 2020-06-18 16:13:36 -0400 |
| commit | 0746618ebe57ba8d452ad5cc907ddd478b512898 (patch) | |
| tree | e9a3599120fdafe1d779a07164f25eb4e6d53132 /src/slave-cmd.c | |
| parent | 8883bdbccf223824935f36a77566d7af19ab4908 (diff) | |
This CL adds support for dataflow branch 2, which includes master processing of DOC 1, 2, 3 for SOR 1 and SOR 3, adding support for master command processing and routing. Slave command generators and receivers are also added for testing master command functionality. CL also adds minor changes to debug scripts and overall cleanup; changes to dataflow structures to support command functionality; dedicated function for handling CTS reception from slaves.
Task list: b1d2ba1914ab4621bd004ad0a636e09d
2c17aeea4e73433fa5a49d310c7526b1
5e15eda1eecb482a9bd4e6ec4ef2af0e
75b4f8b2792a4be69caf830c720d3e7c
Diffstat (limited to 'src/slave-cmd.c')
| -rw-r--r-- | src/slave-cmd.c | 529 |
1 files changed, 529 insertions, 0 deletions
diff --git a/src/slave-cmd.c b/src/slave-cmd.c new file mode 100644 index 0000000..5a7153e --- /dev/null +++ b/src/slave-cmd.c @@ -0,0 +1,529 @@ +/** +****************************************************************************** +* @file : main.c +* @brief : Main program body +****************************************************************************** +* @attention +* +* +****************************************************************************** +*/ + +/* Standard library includes */ +#include <stdio.h> + +/* Library includes */ +#include <pb_encode.h> +#include <pb_decode.h> + +/* Project includes */ +#include "main.h" +#include "devices.h" +#include "config.h" +#include "dataflow.h" +#include "handshake.pb.h" +#include "data.pb.h" + +/* Private Macros */ +#define device_MDR s2m_MDR_response +#define GET_IDX_FROM_ADDR(i2c_addr) i2c_addr-1 +#define GET_ADDR_FROM_IDX(idx) idx+1 +#define GET_BIT_FROM_IDX(a, b) a[b>>5]&(1<<(b%32)) +#define SET_BIT_FROM_IDX(a, b) a[b>>5]|=(1<<(b%32)) +#define COUNTOF(__BUFFER__) (sizeof(__BUFFER__) / sizeof(*(__BUFFER__))) + +#define I2C_ADDRESS 0x09<<1 +#define BUS_DEVICE_LIMIT 128 + +/* Macro to toggle between master and slave firmware */ + +/* Private globals */ +I2C_HandleTypeDef hi2c1; +UART_HandleTypeDef huart1; +uint8_t cmd_str[128]; +uint8_t str_ptr = 0; +pb_byte_t str_buf[18]; + +/* Function prototypes */ +void SystemClock_Config(void); +static void MX_GPIO_Init(void); +static void MX_I2C1_Init(void); +static void MX_USART1_UART_Init(void); + +bool decode_subscriptions_callback(pb_istream_t *istream, const pb_field_t *field, void **args); +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); +bool encode_cmd_string_callback(pb_ostream_t *ostream, const pb_field_t *field, void * const *arg); +bool decode_cmd_string_callback(pb_istream_t *istream, const pb_field_t *field, void **args); +bool handshake(void); +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + /* MCU Configuration */ + + /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ + HAL_Init(); + + /* Configure the system clock */ + SystemClock_Config(); + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_I2C1_Init(); + MX_USART1_UART_Init(); + + uint8_t reset_string[] = "\r\n\n==========COMMAND SLAVE RESET=========\r\n\n"; + HAL_UART_Transmit(&huart1, reset_string, sizeof(reset_string), 100); + + + while (handshake() == false); + uint8_t debug_buf[128] = {0}; + HAL_Delay(1000); + while (1) { + uint8_t SOR_buf[2] = {0}; + if (HAL_I2C_Slave_Receive(&hi2c1, (uint8_t*)SOR_buf, 2, 1000) != 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); + continue; + } + else { + sprintf((char*)debug_buf, "Got SOR: %d \r\n", SOR_buf[0]); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + } + + if (SOR_buf[0] == 1) { + + uint8_t cmd_buf[128]; + size_t cmd_enc_size; + cmd_str[0] = 0x1; cmd_str[1] = 0x2; cmd_str[2] = 0x3; cmd_str[3] = 0x6; + command cmd = command_init_zero; + cmd.dest_module_id = 0x4; + cmd.cmd_str.funcs.encode = encode_cmd_string_callback; + pb_ostream_t cmd_ostream = pb_ostream_from_buffer(cmd_buf, sizeof(cmd_buf)); + + + if (!pb_encode(&cmd_ostream, command_fields, &cmd)) { + sprintf((char*)debug_buf, "Command encoding error\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + continue; + } + cmd_enc_size = cmd_ostream.bytes_written; + + uint8_t doc_buf[4] = {cmd.dest_module_id, 0x1, 0x0, cmd_enc_size}; + 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); + continue; + } + else { + sprintf((char*)debug_buf, "Sent command DOC\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + } + + uint8_t CTS_buf[2] = {0x0, 0x0}; + if (HAL_I2C_Slave_Receive(&hi2c1, (uint8_t*)CTS_buf, 2, 1000) != 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); + continue; + } + else { + sprintf((char*)debug_buf, "Got CTS: %d, data size: %d\r\n", CTS_buf[0], cmd_enc_size); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + } + + if (HAL_I2C_Slave_Transmit(&hi2c1, (uint8_t*)cmd_buf, + cmd_enc_size, 1000) != 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); + continue; + } + else { + sprintf((char*)debug_buf, "Sent command\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + continue; + } + } + else if (SOR_buf[0] == 2) { + uint8_t CTS_buf[] = {0x0, 0x1}; + uint8_t len_buf[4], *MDR_buf, *data_buf; + /* _datapoint datapoints[16]; */ + + HAL_I2C_Slave_Transmit(&hi2c1, CTS_buf, 2, 10000); + sprintf((char*)debug_buf, "Sent CTS\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + + HAL_I2C_Slave_Receive(&hi2c1, len_buf, 4, 1000); + + uint16_t MDR_len = len_buf[1]+(len_buf[0]<<8); + MDR_buf = malloc(MDR_len); + uint16_t data_len = len_buf[3]+(len_buf[2]<<8); + data_buf = malloc(data_len); + + sprintf((char*)debug_buf, "Got lengths. MDR: %d, data: %d\r\n", MDR_len, data_len); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + + HAL_I2C_Slave_Transmit(&hi2c1, CTS_buf, 2, 10000); + HAL_I2C_Slave_Receive(&hi2c1, MDR_buf, MDR_len, 10000); + HAL_I2C_Slave_Receive(&hi2c1, data_buf, data_len, 10000); + + _datapoint datapoint_message; + s2m_MDR_response MDR_message; + pb_istream_t MDR_istream = pb_istream_from_buffer(MDR_buf, MDR_len); + pb_istream_t data_istream = pb_istream_from_buffer(data_buf, data_len); + + pb_decode(&MDR_istream, s2m_MDR_response_fields, &MDR_message); + pb_decode(&data_istream, _datapoint_fields, &datapoint_message); + + sprintf((char*)debug_buf, "Got data from %ld, running version %f\r\n\tdata 0: %f\r\n", MDR_message.module_id, MDR_message.MDR_version, datapoint_message.data); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + } + else if (SOR_buf[0] == 3) { + uint8_t CTS_buf[] = {0x0, 0x1}, len_buf[4], *cmd_buf; + + HAL_I2C_Slave_Transmit(&hi2c1, CTS_buf, 2, 10000); + HAL_I2C_Slave_Receive(&hi2c1, len_buf, 4, 10000); + uint8_t cmd_len = len_buf[1]; + cmd_buf = malloc(cmd_len*sizeof(uint8_t)); + HAL_I2C_Slave_Transmit(&hi2c1, CTS_buf, 2, 10000); + HAL_I2C_Slave_Receive(&hi2c1, cmd_buf, cmd_len, 10000); + + command cmd_decode=command_init_zero; + pb_istream_t cmd_istream = pb_istream_from_buffer(cmd_buf, cmd_len); + cmd_decode.cmd_str.funcs.decode=decode_cmd_string_callback; + pb_decode(&cmd_istream, command_fields, &cmd_decode); + sprintf((char*)debug_buf, "Got cmd\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + } + else { + uint8_t doc_buf[4] = {0x0, 0x0, 0x0, 0x0}; + 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); + continue; + } + else { + sprintf((char*)debug_buf, "Sent idle DOC\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + continue; + } + } + } +} + + +bool handshake(void) +{ + uint8_t MDR_buf[128], debug_buf[128]={0}, term[]="\r\n"; + size_t MDR_enc_size; + s2m_MDR_response res; + res.MDR_version = 0.1; + res.module_id = 0x5; + res.module_class = 1; + res.entity_id=1; + + res.subscriptions.funcs.encode=encode_subscription_callback; + pb_ostream_t ostream = pb_ostream_from_buffer(MDR_buf, sizeof(MDR_buf)); + if(!pb_encode(&ostream, s2m_MDR_response_fields, &res)) { +#ifdef DEBUG_ENABLE + uint8_t err_buf[] = "MDR encoding error\r\n"; + HAL_UART_Transmit(&huart1, err_buf, sizeof(err_buf), 100); +#endif + return false; + } + MDR_enc_size = ostream.bytes_written; + +#ifdef TESTING_ENABLE + sprintf((char*)debug_buf, "MDR Encoded size: %d\r\n", MDR_enc_size); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); + + uint8_t bufbuf[] = "MDR Buffer: "; + HAL_UART_Transmit(&huart1, bufbuf, sizeof(bufbuf), 100); + for(int x=0; x<MDR_enc_size; x++) { + sprintf((char*)debug_buf+x, "%x", MDR_buf[x]); + } + HAL_UART_Transmit(&huart1, debug_buf, MDR_enc_size, 100); + HAL_UART_Transmit(&huart1, term, 2, 100); + memset(debug_buf, 0, 128); +#endif + + uint8_t MDR_ACK_buf[2] = {MDR_enc_size, 0xFF}; + uint8_t MDR_req_buf[2] = {0x0, 0x0}; + + if (HAL_I2C_Slave_Receive(&hi2c1, (uint8_t*)MDR_req_buf, 2, 10000) != HAL_OK) { +#ifdef DEBUG_ENABLE + uint8_t debug_buf[] = "Failed to get MDR req\r\n"; + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); +#endif + return false; + } + +#ifdef TESTING_ENABLE + sprintf((char*)debug_buf, "Got requested record type: %d\r\n", MDR_req_buf[1]); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); +#endif + + if (HAL_I2C_Slave_Transmit(&hi2c1, (uint8_t*)MDR_ACK_buf, 2, 10000) != HAL_OK) { +#ifdef DEBUG_ENABLE + sprintf((char*)debug_buf, "Unable to send MDR ACK. I2C error: %ld\r\n", HAL_I2C_GetError(&hi2c1)); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); +#endif + return false; + } + + uint8_t MDR_CTS_buf[2] = {0x0, 0x0}; + + if (HAL_I2C_Slave_Receive(&hi2c1, (uint8_t*)MDR_CTS_buf, 2, 10000) != HAL_OK) { +#ifdef DEBUG_ENABLE + sprintf((char*)debug_buf, "Failed to get MDR CTS\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); +#endif + return false; + } + + if (HAL_I2C_Slave_Transmit(&hi2c1, (uint8_t*)MDR_buf, MDR_enc_size, 10000) != HAL_OK) { +#ifdef DEBUG_ENABLE + sprintf((char*)debug_buf, "Unable to send MDR. I2C error: %ld\r\n", + HAL_I2C_GetError(&hi2c1)); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); +#endif + return false; + } +#ifdef DEBUG_ENABLE + sprintf((char*)debug_buf, "Successfully sent MDR\r\n"); + HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100); + memset(debug_buf, 0, 128); +#endif + + /* TODO Final ACK from master */ + return true; +} + + +bool encode_subscription_callback(pb_ostream_t *ostream, const pb_field_t *field, void * const *arg) +{ + if(ostream!=NULL && field->tag == s2m_MDR_response_subscriptions_tag) { + for (int x=0; x<5; x++) { + _subscriptions subs; + subs.module_id = x+1; + subs.has_module_id=true; + subs.has_entity_id=false; + subs.has_module_class=false; + subs.has_i2c_address=false; + if(!pb_encode_tag_for_field(ostream, field)) { + return false; + } + if(!pb_encode_submessage(ostream, _subscriptions_fields, &subs)) { + return false; + } + } + } + else{ + return false; + } + 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 encode_cmd_string_callback(pb_ostream_t *ostream, const pb_field_t *field, void * const *arg) +{ + if (ostream != NULL && field->tag == command_cmd_str_tag) { + if (!pb_encode_tag_for_field(ostream, field)) + return false; + return pb_encode_string(ostream, cmd_str, strlen((char*)cmd_str)); + } + return true; +} + +bool decode_cmd_string_callback(pb_istream_t *istream, const pb_field_t *field, void **args) +{ + while (istream->bytes_left) { + if (!pb_read(istream, &str_buf[str_ptr++], 1)) + return false; + } + return true; +} + +/** + * @brief System Clock Configuration + * @retval None + */ +void SystemClock_Config(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + + /** Configure the main internal regulator output voltage + */ + __HAL_RCC_PWR_CLK_ENABLE(); + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2); + /** Initializes the CPU, AHB and APB busses clocks + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) + { + Error_Handler(); + } + /** Initializes the CPU, AHB and APB busses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK + |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) + { + Error_Handler(); + } +} + +/** + * @brief I2C1 Initialization Function + * @param None + * @retval None + */ +static void MX_I2C1_Init(void) +{ + hi2c1.Instance = I2C1; + hi2c1.Init.ClockSpeed = 100000; + hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; + hi2c1.Init.OwnAddress1 = I2C_ADDRESS; + hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + hi2c1.Init.OwnAddress2 = 0xFF; + hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + /* hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_ENABLE; */ + if (HAL_I2C_Init(&hi2c1) != HAL_OK) + { + Error_Handler(); + } + +} + +/** + * @brief USART1 Initialization Function + * @param None + * @retval None + */ +static void MX_USART1_UART_Init(void) +{ + huart1.Instance = USART2; + huart1.Init.BaudRate = 9600; + huart1.Init.WordLength = UART_WORDLENGTH_8B; + huart1.Init.StopBits = UART_STOPBITS_1; + huart1.Init.Parity = UART_PARITY_NONE; + huart1.Init.Mode = UART_MODE_TX_RX; + huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart1.Init.OverSampling = UART_OVERSAMPLING_16; + if (HAL_UART_Init(&huart1) != HAL_OK) + { + Error_Handler(); + } + +} + +/** + * @brief GPIO Initialization Function + * @param None + * @retval None + */ +static void MX_GPIO_Init(void) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOH_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(led_GPIO_Port, led_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pin : led_Pin */ + GPIO_InitStruct.Pin = led_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(led_GPIO_Port, &GPIO_InitStruct); + +} + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return state */ + while (1) { + HAL_GPIO_TogglePin(led_GPIO_Port, led_Pin); + HAL_Delay(1000); + } + /* USER CODE END Error_Handler_Debug */ +} + +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line number, + tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ |
