#include "app_config.h" #include "app_error.h" #include "elite_board.h" #include "pel.h" #include "elite_def.h" #include "nrf_delay.h" #include "nrf_gpio.h" #include "nrf_log.h" #include "adc_drv.h" #if (DEF_ELITE_MODEL == DEF_ELITE_PEL_V2_0) typedef struct { float val; uint32_t pin; uint32_t mask; } input_pin_t; typedef struct { uint16_t pattern_id; uint32_t pattern; } resistor_combination_t; typedef struct __PACKED { uint32_t notify_period; uint32_t total_notify_count; } characteristic_param_t; static bool data_char_notify_running; TaskHandle_t test_gpio_task_Handle = NULL; static pel_output_t output_data = { 0 }; static resistor_combination_t global_resis = { 0 }; const input_pin_t input_pin_tab[] = { { 0.5, INPUT_1_PIN, PEL_0P5R_MASK}, { 1.0, INPUT_2_PIN, PEL_1P0R_MASK}, { 2.0, INPUT_3_PIN, PEL_2P0R_MASK}, { 4.0, INPUT_4_PIN, PEL_4P0R_MASK}, { 8.0, INPUT_5_PIN, PEL_8P0R_MASK}, { 16.2, INPUT_6_PIN, PEL_16P2R_MASK}, { 32.4, INPUT_7_PIN, PEL_32P4R_MASK}, { 63.4, INPUT_8_PIN, PEL_63P4R_MASK}, { 127.0, INPUT_9_PIN, PEL_127R_MASK}, { 255.0, INPUT_10_PIN, PEL_255R_MASK}, { 511.0, INPUT_11_PIN, PEL_511R_MASK}, {1000.0, INPUT_12_PIN, PEL_1000R_MASK}, }; static float _load_set(uint32_t mask) { float ohms = 0; global_resis.pattern = mask; for (int32_t i = COUNTOF(input_pin_tab) - 1; i >= 0; i--) { if (input_pin_tab[i].mask & mask) { nrf_gpio_pin_clear(input_pin_tab[i].pin); ohms += input_pin_tab[i].val; NRF_LOG_INFO("enable R%-2d(" NRF_LOG_FLOAT_MARKER "ohm)", i + 1, NRF_LOG_FLOAT(input_pin_tab[i].val)); } else { nrf_gpio_pin_set(input_pin_tab[i].pin); } } return ohms; } void set_high_z_state(void) { NRF_LOG_INFO("high_z_state"); _load_set(0); } void set_pattern_resistor(uint16_t pattern_id) { const resistor_combination_t pattern_tab[] = { { 1, 0b111}, { 2, 0b011}, { 3, 0b101}, { 4, 0b001}, { 5, 0b111 << 1}, { 6, 0b011 << 1}, { 7, 0b101 << 1}, { 8, 0b001 << 1}, { 9, 0b111 << 2}, {10, 0b011 << 2}, {11, 0b101 << 2}, {12, 0b001 << 2}, {13, 0b111 << 3}, {14, 0b011 << 3}, {15, 0b101 << 3}, {16, 0b001 << 3}, {17, 0b111 << 4}, {18, 0b011 << 4}, {19, 0b101 << 4}, {20, 0b001 << 4}, {21, 0b111 << 5}, {22, 0b011 << 5}, {23, 0b101 << 5}, {24, 0b001 << 5}, {25, 0b111 << 6}, {26, 0b011 << 6}, {27, 0b101 << 6}, {28, 0b001 << 6}, {29, 0b111 << 7}, {30, 0b011 << 7}, {31, 0b101 << 7}, {32, 0b001 << 7}, {33, 0b111 << 8}, {34, 0b011 << 8}, {35, 0b101 << 8}, {36, 0b001 << 8}, {37, 0b111 << 9}, {38, 0b011 << 9}, {39, 0b101 << 9}, {40, 0b001 << 9}, {41, 0b11 << 10}, {42, 0b01 << 10}, {43, 0b1 << 11}, }; global_resis.pattern_id = pattern_id; for (int32_t i = 0; i < ARRAY_SIZE(pattern_tab); i++) { if (pattern_tab[i].pattern_id == pattern_id) { NRF_LOG_INFO("pattern_id[%d] = pattern:0x%08X", pattern_tab[i].pattern_id, pattern_tab[i].pattern); _load_set(pattern_tab[i].pattern); } } } void set_manual_resistor(uint16_t manual_val) { typedef union { struct { uint32_t R1_en : 1; uint32_t R2_en : 1; uint32_t R3_en : 1; uint32_t R4_en : 1; uint32_t R5_en : 1; uint32_t R6_en : 1; uint32_t R7_en : 1; uint32_t R8_en : 1; uint32_t R9_en : 1; uint32_t R10_en : 1; uint32_t R11_en : 1; uint32_t R12_en : 1; }; uint32_t val; } resis_t; resis_t resis = { 0 }; resis.R1_en = (manual_val >> 11) & 1; resis.R2_en = (manual_val >> 10) & 1; resis.R3_en = (manual_val >> 9) & 1; resis.R4_en = (manual_val >> 8) & 1; resis.R5_en = (manual_val >> 7) & 1; resis.R6_en = (manual_val >> 6) & 1; resis.R7_en = (manual_val >> 5) & 1; resis.R8_en = (manual_val >> 4) & 1; resis.R9_en = (manual_val >> 3) & 1; resis.R10_en = (manual_val >> 2) & 1; resis.R11_en = (manual_val >> 1) & 1; resis.R12_en = (manual_val >> 0) & 1; _load_set(resis.val); } static void _sample_measure_out_is_low(void) { nrf_gpio_pin_set(ANODE_PIN); nrf_gpio_pin_clear(CATHODE_PIN); nrf_gpio_pin_clear(SAMPLE_R_PIN); nrf_gpio_pin_clear(SAMPLE_V_PIN); nrf_delay_us(10); nrf_gpio_pin_toggle(ANODE_PIN); nrf_gpio_pin_toggle(CATHODE_PIN); nrf_delay_us(3); nrf_gpio_pin_toggle(SAMPLE_R_PIN); nrf_gpio_pin_toggle(SAMPLE_V_PIN); nrf_delay_us(5); nrf_gpio_pin_toggle(SAMPLE_R_PIN); nrf_gpio_pin_toggle(SAMPLE_V_PIN); nrf_gpio_pin_toggle(CATHODE_PIN); nrf_gpio_pin_toggle(ANODE_PIN); } static void _sample_measure_out_is_high(void) { nrf_gpio_pin_clear(ANODE_PIN); nrf_gpio_pin_set(CATHODE_PIN); nrf_gpio_pin_clear(SAMPLE_R_PIN); nrf_gpio_pin_clear(SAMPLE_V_PIN); nrf_delay_us(10); nrf_gpio_pin_toggle(ANODE_PIN); nrf_gpio_pin_toggle(CATHODE_PIN); nrf_delay_us(3); nrf_gpio_pin_toggle(SAMPLE_R_PIN); nrf_gpio_pin_toggle(SAMPLE_V_PIN); nrf_delay_us(5); nrf_gpio_pin_toggle(SAMPLE_R_PIN); nrf_gpio_pin_toggle(SAMPLE_V_PIN); nrf_gpio_pin_toggle(CATHODE_PIN); nrf_gpio_pin_toggle(ANODE_PIN); } void pel_relays_set(uint32_t measure_out) { if (measure_out) { nrf_gpio_pin_set(RELAY1_PIN); nrf_gpio_pin_clear(RELAY2_PIN); } else { nrf_gpio_pin_clear(RELAY1_PIN); nrf_gpio_pin_set(RELAY2_PIN); } /* delay 30ms */ vTaskDelay(pdMS_TO_TICKS(30)); } pel_output_t pel_smaple_and_convt_all(uint32_t measure_out, uint32_t load_mask) { uint32_t ch_list[] = { [OUTPUT_R1_IDX] = OUTPUT_R1_CHANNEL, [OUTPUT_R2_IDX] = OUTPUT_R2_CHANNEL, [OUTPUT_VO_IDX] = OUTPUT_VO_CHANNEL, [OUTPUT_VC_IDX] = OUTPUT_VC_CHANNEL, [OUTPUT_VE_IDX] = OUTPUT_VE_CHANNEL }; int32_t results[COUNTOF(ch_list)]; float f_results[COUNTOF(ch_list)]; /* config E-load */ _load_set(0); _load_set(load_mask); /* send a pulse to sample and then read ADC channels */ if (measure_out) { adc_read_mutiple_channels_ex(ch_list, results, COUNTOF(ch_list), _sample_measure_out_is_high); adc_read_multiple_milivolt_ex(ch_list, f_results, COUNTOF(ch_list), _sample_measure_out_is_high); } else { adc_read_mutiple_channels_ex(ch_list, results, COUNTOF(ch_list), _sample_measure_out_is_low); adc_read_multiple_milivolt_ex(ch_list, f_results, COUNTOF(ch_list), _sample_measure_out_is_low); } /* copy results */ output_data.output_r1 = results[OUTPUT_R1_IDX]; output_data.output_r2 = results[OUTPUT_R2_IDX]; output_data.output_vo = results[OUTPUT_VO_IDX]; output_data.output_vc = results[OUTPUT_VC_IDX]; output_data.output_ve = results[OUTPUT_VE_IDX]; { char str[128]; snprintf(str, sizeof(str), "%s: 0x%04lX, %.3fmV", "output_r1", output_data.output_r1, f_results[OUTPUT_R1_IDX]); NRF_LOG_INFO("%s", str); snprintf(str, sizeof(str), "%s: 0x%04lX, %.3fmV", "output_r2", output_data.output_r2, f_results[OUTPUT_R2_IDX]); NRF_LOG_INFO("%s", str); snprintf(str, sizeof(str), "%s: 0x%04lX, %.3fmV", "output_vo", output_data.output_vo, f_results[OUTPUT_VO_IDX]); NRF_LOG_INFO("%s", str); snprintf(str, sizeof(str), "%s: 0x%04lX, %.3fmV", "output_vc", output_data.output_vc, f_results[OUTPUT_VC_IDX]); NRF_LOG_INFO("%s", str); snprintf(str, sizeof(str), "%s: 0x%04lX, %.3fmV", "output_ve", output_data.output_ve, f_results[OUTPUT_VE_IDX]); NRF_LOG_INFO("%s", str); } return output_data; } #define VERSION_DATE_YEAR 24 #define VERSION_DATE_MONTH 12 #define VERSION_DATE_DAY 10 #define VERSION_DATE_HOUR 10 #define VERSION_DATE_MINUTE 8 static void cis_version(uint8_t *ins, uint16_t size) { NRF_LOG_INFO("%s", __FUNCTION__); uint8_t cis_ver[] = { CIS_VERSION, VERSION_DATE_YEAR, VERSION_DATE_MONTH, VERSION_DATE_DAY, VERSION_DATE_HOUR, VERSION_DATE_MINUTE, }; extern ret_code_t le_data_update(uint8_t * p_value, uint16_t len); le_data_update((void *)cis_ver, sizeof(cis_ver)); } static void vis_rst(uint8_t *ins, uint16_t size) { NRF_LOG_INFO("%s", __FUNCTION__); } void test_gpio_task(void *pArg) { const uint32_t pel_pins[] = { INPUT_1_PIN, INPUT_2_PIN, INPUT_3_PIN, INPUT_4_PIN, INPUT_5_PIN, INPUT_6_PIN, INPUT_7_PIN, INPUT_8_PIN, INPUT_9_PIN, INPUT_10_PIN, INPUT_11_PIN, INPUT_12_PIN, ANODE_PIN, CATHODE_PIN, SAMPLE_R_PIN, SAMPLE_V_PIN, RELAY1_PIN, RELAY2_PIN }; for (;;) { NRF_LOG_INFO("[test] all output pin set low"); for (int i = 0; i < COUNTOF(pel_pins); i++) { nrf_gpio_pin_clear(pel_pins[i]); } vTaskDelay(1000); NRF_LOG_INFO("[test] all output pin set high"); for (int i = 0; i < COUNTOF(pel_pins); i++) { nrf_gpio_pin_set(pel_pins[i]); } vTaskDelay(1000); NRF_LOG_INFO("[test] alternating high and low signals on all output pins"); for (int i = 0; i < COUNTOF(pel_pins); i++) { nrf_gpio_pin_clear(pel_pins[i]); } vTaskDelay(1000); for (int i = 0; i < COUNTOF(pel_pins); i++) { nrf_gpio_pin_set(pel_pins[i]); vTaskDelay(100); nrf_gpio_pin_clear(pel_pins[i]); } vTaskDelay(1000); } } static void decode_and_set_resistor_pattern(uint8_t *param) { uint16_t pattern_id = u8_to_u16(param[0], param[1]); set_pattern_resistor(pattern_id); } static void decode_and_set_manual_resistor(uint8_t *param) { uint16_t manual_val = u8_to_u16(param[0], param[1]); set_manual_resistor(manual_val); } static void dev_mode_input_resistor(uint8_t *ins) { NRF_LOG_INFO("[DEV MODE] %s", __FUNCTION__); struct __PACKED { uint8_t id : 4; uint8_t ins_type : 4; uint8_t pkg_size; uint8_t mode; uint8_t func_id; uint8_t opcode; uint8_t param[]; } *p_ins = (void *)ins; switch (p_ins->opcode) { case 0x00: set_high_z_state(); break; case 0x01: decode_and_set_resistor_pattern(p_ins->param); break; case 0x02: decode_and_set_manual_resistor(p_ins->param); break; default: break; } } static void data_char_update_once(void) { ret_code_t le_data_update(uint8_t * p_value, uint16_t len); typedef struct __PACKED { int32_t val_1; int32_t val_2; int32_t val_3; int32_t val_4; int32_t val_5; float val_6_f; float val_7_f; float val_8_f; float val_9_f; float val_10_f; } test_val_t; static test_val_t data = { .val_1 = 0, .val_2 = 100, .val_3 = 1000, .val_4 = 10000, .val_5 = 100000, .val_6_f = 1.0, .val_7_f = 5.0, .val_8_f = 10.0, .val_9_f = 15.0, .val_10_f = 20.0, }; { char str[128]; snprintf(str, sizeof(str), "val_1: 0x%08X, %d", data.val_1, data.val_1); NRF_LOG_INFO("%s", str); snprintf(str, sizeof(str), "val_2: 0x%08X, %d", data.val_2, data.val_2); NRF_LOG_INFO("%s", str); snprintf(str, sizeof(str), "val_3: 0x%08X, %d", data.val_3, data.val_3); NRF_LOG_INFO("%s", str); snprintf(str, sizeof(str), "val_4: 0x%08X, %d", data.val_4, data.val_4); NRF_LOG_INFO("%s", str); snprintf(str, sizeof(str), "val_5: 0x%08X, %d", data.val_5, data.val_5); NRF_LOG_INFO("%s", str); snprintf(str, sizeof(str), "val_6_f: %.7f", data.val_6_f, data.val_6_f); NRF_LOG_INFO("%s", str); snprintf(str, sizeof(str), "val_7_f: %.7f", data.val_7_f, data.val_7_f); NRF_LOG_INFO("%s", str); snprintf(str, sizeof(str), "val_8_f: %.7f", data.val_8_f, data.val_8_f); NRF_LOG_INFO("%s", str); snprintf(str, sizeof(str), "val_9_f: %.7f", data.val_9_f, data.val_9_f); NRF_LOG_INFO("%s", str); snprintf(str, sizeof(str), "val_10_f: %.7f", data.val_10_f, data.val_10_f); NRF_LOG_INFO("%s", str); } le_data_update((void *)&data, sizeof(data)); data.val_1++; data.val_2++; data.val_3++; data.val_4++; data.val_5++; data.val_6_f += 0.01; data.val_7_f += 0.01; data.val_8_f += 0.01; data.val_9_f += 0.01; data.val_10_f += 0.01; } static ret_code_t _send_data_char_notify_start_packet(void *p_buf, uint16_t p_buf_size, uint32_t loops) { memset(p_buf, 0x00, sizeof(p_buf)); for (uint32_t i = 0; i < loops; i++) { ret_code_t le_data_notify(uint8_t * p_value, uint16_t len); ret_code_t ret = le_data_notify((void *)p_buf, p_buf_size); if (ret != NRF_SUCCESS) { return ret; } } return NRF_SUCCESS; } static void start_data_char_notify_task(void *p_arg) { typedef struct __PACKED { uint8_t mem_board_id; uint32_t notify_time; uint8_t packet_seq; int32_t val_1; int32_t val_2; int32_t val_3; int32_t val_4; int32_t val_5; float val_6_f; float val_7_f; float val_8_f; float val_9_f; float val_10_f; uint16_t pattern_id; uint32_t pattern; } data_char_packet_t; bool first_data = true; data_char_packet_t packet_buf; characteristic_param_t *data_char_notify_param = (characteristic_param_t *)p_arg; data_char_notify_running = true; memset(&packet_buf, 0x00, sizeof(packet_buf)); _send_data_char_notify_start_packet(&packet_buf, sizeof(packet_buf), 4); for (;;) { if (data_char_notify_running) { if (first_data) { packet_buf.mem_board_id = 5; packet_buf.notify_time = xTaskGetTickCount(); packet_buf.packet_seq = 0; packet_buf.val_1 = 0; packet_buf.val_2 = 100; packet_buf.val_3 = 1000; packet_buf.val_4 = 10000; packet_buf.val_5 = 100000; packet_buf.val_6_f = 1.0; packet_buf.val_7_f = 5.0; packet_buf.val_8_f = 10.0; packet_buf.val_9_f = 15.0; packet_buf.val_10_f = 20.0; packet_buf.pattern_id = global_resis.pattern_id; packet_buf.pattern = global_resis.pattern; first_data = false; } else { packet_buf.mem_board_id = 5; packet_buf.notify_time = xTaskGetTickCount(); packet_buf.packet_seq += 1; packet_buf.val_1 += 1; packet_buf.val_2 += 1; packet_buf.val_3 += 1; packet_buf.val_4 += 1; packet_buf.val_5 += 1; packet_buf.val_6_f += 0.01; packet_buf.val_7_f += 0.01; packet_buf.val_8_f += 0.01; packet_buf.val_9_f += 0.01; packet_buf.val_10_f += 0.01; packet_buf.pattern_id = global_resis.pattern_id; packet_buf.pattern = global_resis.pattern; } ret_code_t le_data_notify(uint8_t * p_value, uint16_t len); ret_code_t ret = le_data_notify((void *)&packet_buf, sizeof(packet_buf)); { char str[128]; snprintf(str, sizeof(str), "{%d, %d, %d, %d, %d, %d, %d, %d, %.7f, %.7f, %.7f, %.7f, %.7f, %d, 0x%08X}", packet_buf.mem_board_id, packet_buf.notify_time, packet_buf.packet_seq, packet_buf.val_1, packet_buf.val_2, packet_buf.val_3, packet_buf.val_4, packet_buf.val_5, packet_buf.val_6_f, packet_buf.val_7_f, packet_buf.val_8_f, packet_buf.val_9_f, packet_buf.val_10_f, packet_buf.pattern_id, packet_buf.pattern); NRF_LOG_INFO("%s", str); } vTaskDelay(pdMS_TO_TICKS(data_char_notify_param->notify_period)); } else // stop data update process { free(data_char_notify_param); vTaskDelete(NULL); } } } static void decode_start_data_char_notify(uint8_t *param) { characteristic_param_t *data_char_notify_param = malloc(sizeof(characteristic_param_t)); if (data_char_notify_param == NULL) { NRF_LOG_ERROR("Failed to allocate memory for data_char_notify_param"); return; } data_char_notify_param->notify_period = u8_to_u32(param[0], param[1], param[2], param[3]); data_char_notify_param->total_notify_count = u8_to_u32(param[0], param[1], param[2], param[3]); data_char_notify_param->notify_period = 100; data_char_notify_param->total_notify_count = 5; xTaskCreate(start_data_char_notify_task, "start_data_char_notify_task", 2048, (void *)data_char_notify_param, 3, NULL); } static void stop_data_char_notify(void) { data_char_notify_running = false; } static void dev_mode_characteristic(uint8_t *ins) { NRF_LOG_INFO("[DEV MODE] %s", __FUNCTION__); struct __PACKED { uint8_t id : 4; uint8_t ins_type : 4; uint8_t pkg_size; uint8_t mode; uint8_t func_id; uint8_t opcode; uint8_t param[]; } *p_ins = (void *)ins; switch (p_ins->opcode) { case 0x00: data_char_update_once(); break; case 0x01: decode_start_data_char_notify(p_ins->param); break; case 0x02: stop_data_char_notify(); break; default: break; } } static void dev_mode(uint8_t *ins, uint16_t size) { struct __PACKED { uint8_t id : 4; uint8_t ins_type : 4; uint8_t pkg_size; uint8_t mode; uint8_t func_id; uint8_t opcode; uint8_t param[]; } *p_ins = (void *)ins; switch (p_ins->func_id) { case 0x00: dev_mode_input_resistor(ins); break; case 0xA3: dev_mode_characteristic(ins); break; default: break; } } const elite_instance_t pel_elite_instance = { .cis_func = { [CIS_VERSION] = cis_version, }, .vis_func = { [VIS_RST] = vis_rst, }, .ris_func = { [DEV_MODE] = dev_mode, } }; const elite_instance_t *pel_init(void) { return &pel_elite_instance; } #endif