/*********************************************************************************************************************** * DISCLAIMER * This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. * No other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all * applicable laws, including copyright laws. * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING THIS SOFTWARE, WHETHER EXPRESS, IMPLIED * OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY * LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE FOR ANY DIRECT, * INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR * ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability * of this software. By using this software, you agree to the additional terms and conditions found by accessing the * following link: * http://www.renesas.com/disclaimer * * Copyright (C) 2012, 2021 Renesas Electronics Corporation. All rights reserved. ***********************************************************************************************************************/ /*********************************************************************************************************************** * File Name : r_main.c * Version : CodeGenerator for RL78/F14 V2.03.07.02 [08 Nov 2021] * Device(s) : R5F10PPJ * Tool-Chain : CCRL * Description : This file implements main function. * Creation Date: 2026-06-08 ***********************************************************************************************************************/ /*********************************************************************************************************************** Includes ***********************************************************************************************************************/ #include "r_cg_macrodriver.h" #include "r_cg_cgc.h" #include "r_cg_port.h" #include "r_cg_serial.h" #include "r_cg_wdt.h" /* Start user code for include. Do not edit comment generated here */ #include "common.h" #include "gatectrl.h" #include #include #include #include #include "app_types.h" #include "app_cmd_parser.h" #include "app_scheduler.h" #include "app_owi_service.h" /* End user code. Do not edit comment generated here */ #include "r_cg_userdefine.h" /*********************************************************************************************************************** Pragma directive ***********************************************************************************************************************/ /* Start user code for pragma. Do not edit comment generated here */ #define CMD_MAX 529 #define UART_RX_BUF_SIZE_LOCAL 1024 #define OWI_LONG_READ_SETTLE_US 30000U #define OWI_LONG_READ_RETRY_US 10000U #define OWI_CONNECT_SETTLE_US 2000U #define POWER_STARTUP_SETTLE_MS 500U #define START_RELAY_SETTLE_MS 1000U #define GAUGE_RAW_NIBBLE_COUNT 24u #define GAUGE_FRAME_NIBBLE_COUNT 13u #define GAUGE_ALIGN_MAX_START 11 #define GAUGE_EDGE_TIMEOUT_US 30000U #define GAUGE_STOP_SETTLE_MS 10U #define GAUGE_START_SETTLE_MS 20U #define GAUGE_DATA_SAMPLE_US 10U volatile uint8_t uart_rx_done = 0; volatile uint16_t uart_rx_index = 0; volatile uint8_t uart_rx_buffer[UART_RX_BUF_SIZE] = {0}; volatile uint16_t uart_rx_length = 0; uint8_t g_fixed_addr = 0; #define RELAY_PORT P14 #define RELAY_PM PM14 #define RELAY_MASK 0x01u /* P14.0 */ /* End user code. Do not edit comment generated here */ /*********************************************************************************************************************** Global variables and functions ***********************************************************************************************************************/ /* Start user code for global. Do not edit comment generated here */ typedef struct { volatile uint8_t *req_p; volatile uint8_t *req_pm; volatile uint8_t *req_pu; uint8_t req_mask; volatile uint8_t *ck_p; volatile uint8_t *ck_pm; volatile uint8_t *ck_pu; uint8_t ck_mask; volatile uint8_t *data_p; volatile uint8_t *data_pm; volatile uint8_t *data_pu; uint8_t data_mask; } gauge_pins_t; typedef struct { uint8_t rawBuf[24]; uint8_t frame[13]; float value; int decimal; uint8_t valid; } gauge_state_t; typedef struct { const gauge_pins_t *pins; gauge_state_t *state; uint8_t active; uint8_t ok; uint8_t wait_state; uint8_t bit_index; uint8_t nibble_index; uint8_t nibble; uint32_t timeout_us; } gauge_capture_t; /* req, ck, data ¼ø¼­ */ static gauge_pins_t LEFT_GAUGE = { &P15, &PM15, &PU15, 0x02u, /* REQ P15.1 */ &P6, &PM6, &PU6, 0x40u, /* CK P6.6 */ &P0, &PM0, &PU0, 0x01u /* DATA P0.0 */ }; static gauge_pins_t RIGHT_GAUGE = { &P15, &PM15, &PU15, 0x01u, /* REQ P15.0 */ &P6, &PM6, &PU6, 0x80u, /* CK P6.7 */ &P15, &PM15, &PU15, 0x40u /* DATA P15.6 */ }; static gauge_state_t leftGauge; static gauge_state_t rightGauge; static struct { uint8_t active; app_job_t job; } g_runtime; static void send_end_response(void) { PC_PRINT("\r\n"); } static void out_print(const char *s) { if (s) { PC_PRINT(s); } } static void uart1_send_string_safe(const char *s) { if (s) { uart1_send_string(s); } } static void app_kick_wdt(void) { R_WDT_Restart(); } static void delay_ms_wdt(uint16_t total_ms) { while (total_ms != 0u) { uint16_t step = (total_ms > 10u) ? 10u : total_ms; delay_ms(step); app_kick_wdt(); total_ms = (uint16_t)(total_ms - step); } } static unsigned char hex2byte(char h, char l) { unsigned char hi, lo; if (h >= 'a' && h <= 'f') h -= 32; if (l >= 'a' && l <= 'f') l -= 32; hi = (h >= 'A') ? (unsigned char)(h - 'A' + 10) : (unsigned char)(h - '0'); lo = (l >= 'A') ? (unsigned char)(l - 'A' + 10) : (unsigned char)(l - '0'); return (unsigned char)((hi << 4) | lo); } static void relay_init(void) { /* P14.0 output */ RELAY_PM &= (uint8_t)~RELAY_MASK; /* ±âº» OFF */ RELAY_PORT |= RELAY_MASK; } static void relay_on(void) { RELAY_PORT &= (uint8_t)~RELAY_MASK; } static void relay_off(void) { RELAY_PORT |= RELAY_MASK; } static void gauge_req_start(const gauge_pins_t *g) { if (!g) return; /* Arduino: digitalWrite(req, HIGH) */ *(g->req_pm) &= (uint8_t)~(g->req_mask); /* output */ *(g->req_p) |= g->req_mask; /* HIGH */ } static void gauge_req_stop(const gauge_pins_t *g) { if (!g) return; /* Arduino: digitalWrite(req, LOW) */ *(g->req_pm) &= (uint8_t)~(g->req_mask); /* output */ *(g->req_p) &= (uint8_t)~(g->req_mask); /* LOW */ } static int gauge_read_pin(volatile uint8_t *port, uint8_t mask) { return ((*port & mask) != 0u) ? 1 : 0; } static uint8_t gauge_wait_pin_state(volatile uint8_t *port, uint8_t mask, int state, uint32_t timeout_us) { while (timeout_us--) { if (gauge_read_pin(port, mask) == state) { return 1u; } delay_us(1u); } return 0u; } static uint8_t gauge_read_nibble(const gauge_pins_t *g, uint8_t *outNibble) { uint8_t k = 0; int j; if (!g || !outNibble) return 0u; for (j = 0; j < 4; j++) { if (!gauge_wait_pin_state(g->ck_p, g->ck_mask, 1u, 30000u)) { return 0u; } if (!gauge_wait_pin_state(g->ck_p, g->ck_mask, 0u, 30000u)) { return 0u; } delay_us(10u); if ((*(g->data_p)) & g->data_mask) { k |= (uint8_t)(1u << j); } } *outNibble = k; return 1u; } static uint8_t gauge_is_valid_frame(const uint8_t *n) { int i; if (!n) return 0u; if (!(n[0] == 0xFu && n[1] == 0xFu && n[2] == 0xFu && n[3] == 0xFu)) { return 0u; } if (!(n[4] == 0x0u || n[4] == 0x8u)) { return 0u; } for (i = 5; i <= 10; i++) { if (n[i] > 9u) { return 0u; } } if (n[11] > 5u) { return 0u; } if (!(n[12] == 0x0u || n[12] == 0x8u)) { return 0u; } return 1u; } static uint8_t gauge_read_aligned_frame(const gauge_pins_t *g, gauge_state_t *s) { int i; int start; if (!g || !s) return 0u; gauge_req_stop(g); delay_ms(10u); gauge_req_start(g); delay_ms(20u); for (i = 0; i < 24; i++) { if (!gauge_read_nibble(g, &s->rawBuf[i])) { gauge_req_stop(g); return 0u; } } gauge_req_stop(g); for (start = 0; start <= 11; start++) { for (i = 0; i < 13; i++) { s->frame[i] = s->rawBuf[start + i]; } if (gauge_is_valid_frame(s->frame)) { return 1u; } } return 0u; } static uint8_t gauge_decode_value(const uint8_t *n, float *value, int *decimal) { long digits; uint8_t isNegative; int i; if (!n || !value || !decimal) return 0u; digits = (long)n[5] * 100000L + (long)n[6] * 10000L + (long)n[7] * 1000L + (long)n[8] * 100L + (long)n[9] * 10L + (long)n[10]; *decimal = (int)n[11]; isNegative = (n[4] == 0x8u) ? 1u : 0u; *value = (float)digits; for (i = 0; i < *decimal; i++) { *value /= 10.0f; } if (isNegative) { *value = -*value; } return 1u; } static void gauge_reset_state(gauge_state_t *s) { if (!s) return; memset(s->rawBuf, 0, sizeof(s->rawBuf)); memset(s->frame, 0, sizeof(s->frame)); s->valid = 0u; s->value = 0.0f; s->decimal = 3; } static uint8_t gauge_align_captured_frame(gauge_state_t *s) { int i; int start; if (!s) return 0u; for (start = 0; start <= GAUGE_ALIGN_MAX_START; start++) { for (i = 0; i < (int)GAUGE_FRAME_NIBBLE_COUNT; i++) { s->frame[i] = s->rawBuf[start + i]; } if (gauge_is_valid_frame(s->frame)) { return 1u; } } return 0u; } static void gauge_capture_init(gauge_capture_t *c, const gauge_pins_t *g, gauge_state_t *s) { if (!c) return; c->pins = g; c->state = s; c->active = (uint8_t)((g && s) ? 1u : 0u); c->ok = 0u; c->wait_state = 1u; c->bit_index = 0u; c->nibble_index = 0u; c->nibble = 0u; c->timeout_us = GAUGE_EDGE_TIMEOUT_US; } static void gauge_capture_step(gauge_capture_t *c) { if (!c || !c->active) return; if (gauge_read_pin(c->pins->ck_p, c->pins->ck_mask) == (int)c->wait_state) { if (c->wait_state) { c->wait_state = 0u; c->timeout_us = GAUGE_EDGE_TIMEOUT_US; return; } delay_us(GAUGE_DATA_SAMPLE_US); if ((*(c->pins->data_p)) & c->pins->data_mask) { c->nibble |= (uint8_t)(1u << c->bit_index); } c->bit_index++; if (c->bit_index >= 4u) { c->state->rawBuf[c->nibble_index] = c->nibble; c->nibble_index++; c->nibble = 0u; c->bit_index = 0u; if (c->nibble_index >= GAUGE_RAW_NIBBLE_COUNT) { c->active = 0u; c->ok = 1u; return; } } c->wait_state = 1u; c->timeout_us = GAUGE_EDGE_TIMEOUT_US; return; } if (c->timeout_us == 0u) { c->active = 0u; c->ok = 0u; return; } c->timeout_us--; } static uint8_t gauge_finish_captured_frame(const gauge_capture_t *c) { gauge_state_t *s; if (!c || !c->state || !c->ok) return 0u; s = c->state; s->valid = 0u; if (!gauge_align_captured_frame(s)) { return 0u; } if (!gauge_decode_value(s->frame, &s->value, &s->decimal)) { return 0u; } s->valid = 1u; return 1u; } static uint8_t gauge_read_pair(const gauge_pins_t *left_g, gauge_state_t *left_s, const gauge_pins_t *right_g, gauge_state_t *right_s) { gauge_capture_t left_cap; gauge_capture_t right_cap; uint8_t left_ok; uint8_t right_ok; if (!left_g || !left_s || !right_g || !right_s) return 0u; gauge_reset_state(left_s); gauge_reset_state(right_s); gauge_req_stop(left_g); gauge_req_stop(right_g); delay_ms(GAUGE_STOP_SETTLE_MS); gauge_req_start(left_g); gauge_req_start(right_g); delay_ms(GAUGE_START_SETTLE_MS); gauge_capture_init(&left_cap, left_g, left_s); gauge_capture_init(&right_cap, right_g, right_s); while (left_cap.active || right_cap.active) { gauge_capture_step(&left_cap); gauge_capture_step(&right_cap); if (left_cap.active || right_cap.active) { delay_us(1u); } } gauge_req_stop(left_g); gauge_req_stop(right_g); left_ok = gauge_finish_captured_frame(&left_cap); right_ok = gauge_finish_captured_frame(&right_cap); return (uint8_t)(left_ok && right_ok); } static uint8_t gauge_read(const gauge_pins_t *g, gauge_state_t *s) { if (!g || !s) return 0u; s->valid = 0u; s->value = 0.0f; s->decimal = 3; if (!gauge_read_aligned_frame(g, s)) { return 0u; } if (!gauge_decode_value(s->frame, &s->value, &s->decimal)) { return 0u; } s->valid = 1u; return 1u; } static void gauge_format_value(char *dst, int dst_sz, const char *label, const gauge_state_t *s) { (void)dst_sz; if (!dst || !label || !s) return; if (s->valid) { sprintf(dst, "%s%.*f", label, s->decimal, s->value); } else { sprintf(dst, "%sERR", label); } } static void gauge_setup_pins(const gauge_pins_t *g) { if (!g) return; /* REQ ±âº» LOW(output) */ *(g->req_pm) &= (uint8_t)~(g->req_mask); *(g->req_p) &= (uint8_t)~(g->req_mask); *(g->req_pu) &= (uint8_t)~(g->req_mask); /* CK / DATA = input */ *(g->ck_pm) |= g->ck_mask; *(g->data_pm) |= g->data_mask; /* Arduino INPUT_PULLUP°ú ¸ÂÃã */ *(g->ck_pu) |= g->ck_mask; *(g->data_pu) |= g->data_mask; } static int build_line_from_rx(const volatile uint8_t *rx_buf, int rx_len, char *line, int line_sz) { int i; int idx = 0; if (!rx_buf || !line || line_sz <= 1) return 0; for (i = 0; i < rx_len; i++) { char c = (char)rx_buf[i]; if (c == '\r' || c == '\n' || c == '\0') { continue; } if (idx < (line_sz - 1)) { line[idx++] = c; } } line[idx] = '\0'; return idx; } static void print_owi_write_result(const app_owi_result_t *r) { char buf[48]; if (!r) { out_print("Fail\r\n"); return; } if (r->ok && !r->timeout) { out_print("51\r\n"); } else { (void)sprintf(buf, "Fail\r\n"); out_print(buf); } } static void reset_channel_gate_defaults(uint8_t ch) { if (ch >= 1u && ch <= 20u) { Gate_SetByNum(ch, 0u, 0u, 1u); } } static void print_owi_read_result(const app_owi_result_t *r, uint8_t reset_ch) { char out[(2 * OWI_IO_MAX_BYTES) + 40]; uint16_t p = 0; uint16_t i; uint16_t start; uint16_t count; if (!r || !r->ok || r->read_len == 0) { out_print("Fail\r\n"); reset_channel_gate_defaults(reset_ch); return; } /* ±âº»Àº Àüü Ãâ·Â */ start = 0u; count = r->read_len; /* NVM read 127¹ÙÀÌÆ®ÀÏ ¶§´Â ¸¶Áö¸· 8¹ÙÀÌÆ®¸¸ Ãâ·Â => 16 hex chars */ if (r->read_len == 127u) { if (r->read_len >= 8u) { start = (uint16_t)(r->read_len - 8u); count = 8u; } } if ((uint32_t)start + (uint32_t)count > (uint32_t)OWI_IO_MAX_BYTES) { if (start >= OWI_IO_MAX_BYTES) { count = 0u; } else { count = (uint16_t)(OWI_IO_MAX_BYTES - start); } } for (i = 0; i < count; i++) { uint8_t b = r->data[start + i]; out[p++] = "0123456789ABCDEF"[b >> 4]; out[p++] = "0123456789ABCDEF"[b & 0x0F]; } if (r->timeout) { p += (uint16_t)sprintf(&out[p], " !TO(B%u b%u)", (unsigned)r->timeout_byte_index, (unsigned)r->timeout_bit_index); } out[p++] = '\r'; out[p++] = '\n'; out[p] = '\0'; out_print(out); reset_channel_gate_defaults(reset_ch); } static void runtime_reset(void) { memset(&g_runtime, 0, sizeof(g_runtime)); } static uint8_t is_x_off_cmd(const char *line) { if (!line) return 0; return (uint8_t)( (line[0] == 'x' || line[0] == 'X') && isdigit((unsigned char)line[1]) && isdigit((unsigned char)line[2]) && (line[3] == 'o' || line[3] == 'O') && line[4] == '\0' ); } static uint8_t is_start_cmd(const char *line) { if (!line) return 0u; return (uint8_t)( (line[0] == 's' || line[0] == 'S') && (line[1] == 't' || line[1] == 'T') && (line[2] == 'a' || line[2] == 'A') && (line[3] == 'r' || line[3] == 'R') && (line[4] == 't' || line[4] == 'T') && line[5] == '\0' ); } static uint8_t is_stop_cmd(const char *line) { if (!line) return 0u; return (uint8_t)( (line[0] == 's' || line[0] == 'S') && (line[1] == 't' || line[1] == 'T') && (line[2] == 'o' || line[2] == 'O') && (line[3] == 'p' || line[3] == 'P') && line[4] == '\0' ); } static uint8_t is_long_owi_read_len(uint16_t len) { return (uint8_t)((len == 119u || len == 127u) ? 1u : 0u); } static app_owi_result_t do_stable_owi_read(uint8_t id, uint16_t read_len) { app_owi_result_t r; if (is_long_owi_read_len(read_len)) { delay_us(OWI_LONG_READ_SETTLE_US); app_kick_wdt(); } r = app_owi_read_basic(id, (int)read_len); app_kick_wdt(); if ((!r.ok || r.timeout || r.read_len < read_len) && is_long_owi_read_len(read_len)) { delay_us(OWI_LONG_READ_RETRY_US); app_kick_wdt(); r = app_owi_read_basic(id, (int)read_len); app_kick_wdt(); } return r; } static uint8_t copy_nvm_tail8(const app_owi_result_t *r, uint8_t *tail8) { uint16_t start; uint16_t i; if (!r || !tail8) return 0u; if (!r->ok || r->timeout || r->read_len < 127u) return 0u; start = (uint16_t)(r->read_len - 8u); for (i = 0; i < 8u; i++) { tail8[i] = r->data[start + i]; } return 1u; } static void tail8_to_hex16(const uint8_t *tail8, char *out_hex) { uint8_t i; if (!tail8 || !out_hex) return; for (i = 0; i < 8u; i++) { out_hex[2u * i] = "0123456789ABCDEF"[tail8[i] >> 4]; out_hex[2u * i + 1] = "0123456789ABCDEF"[tail8[i] & 0x0Fu]; } out_hex[16] = '\0'; } static uint8_t read_connected_nvm_tail8(uint8_t *tail8) { app_owi_result_t r_write_nvm; app_owi_result_t r_read_nvm; static const uint8_t nvm_cmd[3] = { 0x26u, 0x00u, 0x3Eu }; if (!tail8) return 0u; r_write_nvm = app_owi_write_basic(0x28u, nvm_cmd, 3u); if (!r_write_nvm.ok || r_write_nvm.timeout) return 0u; delay_us(2000u); r_read_nvm = do_stable_owi_read(0x28u, 127u); if (!copy_nvm_tail8(&r_read_nvm, tail8)) return 0u; return 1u; } static uint8_t read_connected_nvm_last16(uint8_t ch, uint8_t hash_on, uint8_t anaout_on, uint8_t check_on, char *out_hex) { app_owi_result_t r_write1; app_owi_result_t r_read2; app_owi_result_t r_write3; app_owi_result_t r_read3; static const uint8_t connect_cmd[3] = { 0x72u, 0x7Eu, 0xA9u }; static const uint8_t expect_7272[2] = { 0x72u, 0x72u }; static const uint8_t expect_7c[3] = { 0x7Cu, 0x78u, 0x01u }; uint8_t cmd_7c = 0x7Cu; uint8_t tail8[8]; if (!out_hex) return 0u; if (ch < 1u || ch > 20u) return 0u; Cal_Init(); Gate_SetByNum(ch, hash_on, anaout_on, check_on); GateCtrl_SelectChannel(ch); r_write1 = app_owi_write_t_basic(0x28u, connect_cmd, 3u); if (!r_write1.ok || r_write1.timeout) return 0u; delay_us(2000u); r_read2 = app_owi_read_basic(0x28u, 2); if (!r_read2.ok || r_read2.timeout || r_read2.read_len < 2u) return 0u; if (memcmp(r_read2.data, expect_7272, 2u) != 0) return 0u; r_write3 = app_owi_write_t_basic(0x28u, &cmd_7c, 1u); if (!r_write3.ok || r_write3.timeout) return 0u; delay_us(2000u); r_read3 = app_owi_read_basic(0x28u, 3); if (!r_read3.ok || r_read3.timeout || r_read3.read_len < 3u) return 0u; if (memcmp(r_read3.data, expect_7c, 3u) != 0) return 0u; if (!read_connected_nvm_tail8(tail8)) return 0u; tail8_to_hex16(tail8, out_hex); return 1u; } static int run_connect_verify_one_channel(const app_job_t *job, uint8_t ch) { app_owi_result_t r_write1; app_owi_result_t r_read2; app_owi_result_t r_write3; app_owi_result_t r_read3; uint8_t write1_data[3]; uint8_t expected_tail[3]; uint8_t cmd_7c = 0x7Cu; uint8_t attempt; if (!job) return 0; if (job->len != 6u) return 0; if (ch < 1u || ch > 20u) return 0; memcpy(write1_data, &job->payload[0], 3u); memcpy(expected_tail, &job->payload[3], 3u); for (attempt = 0u; attempt < 2u; attempt++) { if (attempt > 0u) { Cal_Init(); app_kick_wdt(); } Cal_Init(); Gate_SetByNum(ch, job->hash_on, job->anaout_on, job->check_on); GateCtrl_SelectChannel(ch); /* 1) first 3-byte write */ r_write1 = app_owi_write_t_basic(0x28u, write1_data, 3u); if (!r_write1.ok || r_write1.timeout) { app_kick_wdt(); continue; } delay_us(OWI_CONNECT_SETTLE_US); app_kick_wdt(); /* 2) read 2 bytes -> must be 72 72 */ r_read2 = app_owi_read_basic(0x28u, 2); if (!r_read2.ok || r_read2.timeout || r_read2.read_len < 2u || r_read2.data[0] != 0x72u || r_read2.data[1] != 0x72u) { delay_us(OWI_CONNECT_SETTLE_US); app_kick_wdt(); r_read2 = app_owi_read_basic(0x28u, 2); } if (!r_read2.ok || r_read2.timeout || r_read2.read_len < 2u) { app_kick_wdt(); continue; } if (r_read2.data[0] != 0x72u || r_read2.data[1] != 0x72u) { app_kick_wdt(); continue; } /* 3) write 7C */ r_write3 = app_owi_write_t_basic(0x28u, &cmd_7c, 1u); if (!r_write3.ok || r_write3.timeout) { app_kick_wdt(); continue; } delay_us(OWI_CONNECT_SETTLE_US); app_kick_wdt(); /* 4) read 3 bytes -> compare with expected tail */ r_read3 = app_owi_read_basic(0x28u, 3); if (!r_read3.ok || r_read3.timeout || r_read3.read_len < 3u || memcmp(r_read3.data, expected_tail, 3u) != 0) { delay_us(OWI_CONNECT_SETTLE_US); app_kick_wdt(); r_read3 = app_owi_read_basic(0x28u, 3); } if (!r_read3.ok || r_read3.timeout || r_read3.read_len < 3u) { app_kick_wdt(); continue; } if (memcmp(r_read3.data, expected_tail, 3u) == 0) { return 1; } } return 0; } static int execute_connect_verify_sequence(const app_job_t *job) { uint8_t ch; uint8_t success_count = 0; if (!job) return 0; if (job->type != APP_JOB_PROTO_OW) return 0; if (job->proto != APP_PROTO_OWIT) return 0; if (job->id != 0x28u) return 0; if (job->len != 6u) return 0; if (job->channel == 0u) { for (ch = 1u; ch <= 20u; ch++) { uint8_t ok = (uint8_t)run_connect_verify_one_channel(job, ch); if (ok) { success_count++; } } if (success_count == 0u) { out_print("Fail\r\n"); } send_end_response(); return 1; } if (job->channel < 1u || job->channel > 20u) { out_print("Err:ch_range\r\n"); send_end_response(); return 1; } if (run_connect_verify_one_channel(job, job->channel)) { out_print("Success\r\n"); } else { out_print("Fail\r\n"); } send_end_response(); return 1; } static int execute_direct_read_sequence(const app_job_t *job) { app_owi_result_t r_write; app_owi_result_t r_read; uint16_t read_len = 0u; if (!job) return 0; if (job->type != APP_JOB_PROTO_OW) return 0; if (job->proto != APP_PROTO_OWIW) return 0; if (job->id != 0x28u) return 0; if (job->len != 3u) return 0; if (job->channel < 1u || job->channel > 20u) { out_print("Fail\r\n"); send_end_response(); return 1; } Cal_Init(); Gate_SetByNum(job->channel, job->hash_on, job->anaout_on, job->check_on); GateCtrl_SelectChannel(job->channel); if (job->payload[0] == 0x2Eu && job->payload[1] == 0x00u && job->payload[2] == 0x1Fu) { read_len = 65u; } else if (job->payload[0] == 0x22u && job->payload[1] == 0x00u && job->payload[2] == 0x3Au) { read_len = 119u; } else if (job->payload[0] == 0x26u && job->payload[1] == 0x00u && job->payload[2] == 0x3Eu) { char nvm_hex[17]; char out[32]; if (read_connected_nvm_last16(job->channel, job->hash_on, job->anaout_on, job->check_on, nvm_hex)) { (void)sprintf(out, "%s\r\n", nvm_hex); out_print(out); } else { out_print("Fail\r\n"); } reset_channel_gate_defaults(job->channel); send_end_response(); return 1; } else { return 0; } r_write = app_owi_write_basic(0x28u, job->payload, 3u); if (!r_write.ok || r_write.timeout) { out_print("Fail\r\n"); reset_channel_gate_defaults(job->channel); send_end_response(); return 1; } r_read = do_stable_owi_read(0x28u, read_len); if (!r_read.ok || r_read.timeout || r_read.read_len < read_len) { out_print("Fail\r\n"); reset_channel_gate_defaults(job->channel); send_end_response(); return 1; } print_owi_read_result(&r_read, job->channel); send_end_response(); return 1; } static void do_nvm_read_after_gauge(void) { char nvm_hex[17]; if (read_connected_nvm_last16(1u, 1u, 0u, 1u, nvm_hex)) { out_print(nvm_hex); out_print("\r\n"); } else { out_print("Fail\r\n"); } } static int execute_owi_service_from_job(const app_job_t *job) { app_owi_result_t r; if (!job) return 0; if (execute_connect_verify_sequence(job)) { return 1; } if (execute_direct_read_sequence(job)) { return 1; } if (job->channel < 1u || job->channel > 20u) { out_print("Err:ch_range\r\n"); send_end_response(); return 1; } Cal_Init(); Gate_SetByNum(job->channel, job->hash_on, job->anaout_on, job->check_on); GateCtrl_SelectChannel(job->channel); if (job->type == APP_JOB_PROTO_OW) { if (job->proto == APP_PROTO_OWIT) { r = app_owi_write_t_basic(job->id, job->payload, (uint8_t)job->len); } else { r = app_owi_write_basic(job->id, job->payload, (uint8_t)job->len); } print_owi_write_result(&r); send_end_response(); return 1; } if (job->type == APP_JOB_PROTO_OR) { r = app_owi_read_basic(job->id, (int)job->len); print_owi_read_result(&r, job->channel); send_end_response(); return 1; } out_print("Err:job_exec\r\n"); send_end_response(); return 1; } static void process_local_legacy_line(const char *input_line) { char line[UART_RX_BUF_SIZE_LOCAL]; int idx; int pos = 2; uint8_t id; uint16_t byte_len; uint8_t cmd[CMD_MAX]; unsigned int k; app_owi_result_t r; uint8_t is_read = 0u; uint8_t is_write_t = 0u; if (!input_line) return; strncpy(line, input_line, sizeof(line) - 1); line[sizeof(line) - 1] = '\0'; idx = (int)strlen(line); if (idx < 7) { out_print("Err:short\r\n"); return; } if (!((line[0] == 'o' || line[0] == 'O') && ((line[1] == 'w' || line[1] == 'W') || (line[1] == 'r' || line[1] == 'R')))) { out_print("Err:unsupported\r\n"); return; } if (line[1] == 'r' || line[1] == 'R') { is_read = 1u; } if (!is_read && line[pos] == 't') { is_write_t = 1u; pos++; } if (line[pos] == '_' || line[pos] == ':') pos++; if (pos + 1 >= idx) { out_print("Err:id_short\r\n"); return; } id = hex2byte(line[pos], line[pos + 1]); pos += 2; if (pos + 2 >= idx || !isdigit((unsigned char)line[pos]) || !isdigit((unsigned char)line[pos + 1]) || !isdigit((unsigned char)line[pos + 2])) { out_print("Err:len_dec\r\n"); return; } byte_len = (uint16_t)(100 * (line[pos] - '0') + 10 * (line[pos + 1] - '0') + (line[pos + 2] - '0')); pos += 3; if (byte_len > CMD_MAX) { out_print("Err:len_range\r\n"); return; } if (!is_read) { if (byte_len == 0u) { out_print("Err:payload0\r\n"); return; } if (pos + ((int)byte_len * 2) != idx) { out_print("Err:len_mismatch\r\n"); return; } for (k = 0; k < byte_len; k++) { cmd[k] = hex2byte(line[pos + (int)(2 * k)], line[pos + (int)(2 * k + 1)]); } Cal_Init(); GateCtrl_SelectChannel(1u); if (is_write_t) { r = app_owi_write_t_basic(id, cmd, (uint8_t)byte_len); } else { r = app_owi_write_basic(id, cmd, (uint8_t)byte_len); } print_owi_write_result(&r); send_end_response(); return; } if (pos != idx || byte_len == 0u) { out_print("Err:read_no_payload\r\n"); return; } Cal_Init(); GateCtrl_SelectChannel(1u); r = app_owi_read_basic(id, (int)byte_len); print_owi_read_result(&r, 1u); send_end_response(); } static void process_one_line(app_cmd_src_t src, const volatile uint8_t *rx_buf, uint16_t rx_len) { char line[UART_RX_BUF_SIZE_LOCAL]; int idx; app_job_t job; (void)src; idx = build_line_from_rx(rx_buf, (int)rx_len, line, (int)sizeof(line)); if (idx <= 0) return; if (is_x_off_cmd(line)) { Cal_Init(); out_print("OFF\r\n"); send_end_response(); return; } if (is_start_cmd(line)) { char leftBuf[32]; char rightBuf[32]; char lineBuf[80]; relay_on(); delay_ms_wdt(15000U); if (!gauge_read_pair(&LEFT_GAUGE, &leftGauge, &RIGHT_GAUGE, &rightGauge)) { if (!leftGauge.valid) { gauge_read(&LEFT_GAUGE, &leftGauge); } if (!rightGauge.valid) { gauge_read(&RIGHT_GAUGE, &rightGauge); } } gauge_format_value(leftBuf, sizeof(leftBuf), "L:", &leftGauge); gauge_format_value(rightBuf, sizeof(rightBuf), "R:", &rightGauge); sprintf(lineBuf, "%s,%s\r\n", leftBuf,rightBuf); out_print(lineBuf); delay_ms_wdt(START_RELAY_SETTLE_MS); do_nvm_read_after_gauge(); delay_ms_wdt(100u); send_end_response(); return; } if (is_stop_cmd(line)) { relay_off(); out_print("RELAY OFF\r\n"); send_end_response(); return; } if (!app_cmd_parse_line(APP_CMD_SRC_PC, line, &job)) { out_print("Err:parse\r\n"); return; } if (!app_scheduler_push(&job)) { out_print("Err:queue_full\r\n"); } } static void app_runtime_try_start(void) { if (g_runtime.active) return; if (app_scheduler_pop(&g_runtime.job)) { g_runtime.active = 1u; } } static void app_job_tick(void) { app_runtime_try_start(); if (!g_runtime.active) return; switch (g_runtime.job.type) { case APP_JOB_PROTO_OW: case APP_JOB_PROTO_OR: if (!execute_owi_service_from_job(&g_runtime.job)) { out_print("Err:job_exec\r\n"); } runtime_reset(); return; case APP_JOB_FORWARD_LINE: out_print("Err:unsupported\r\n"); runtime_reset(); return; case APP_JOB_LOCAL_EXEC: process_local_legacy_line(g_runtime.job.line); runtime_reset(); return; default: runtime_reset(); return; } } /* End user code. Do not edit comment generated here */ void R_MAIN_UserInit(void); /*********************************************************************************************************************** * Function Name: main * Description : This function implements main function. * Arguments : None * Return Value : None ***********************************************************************************************************************/ void main(void) { R_MAIN_UserInit(); /* Start user code. Do not edit comment generated here */ R_WDT_Create(); R_WDT_Restart(); delay_ms_wdt(POWER_STARTUP_SETTLE_MS); relay_init(); gauge_setup_pins(&LEFT_GAUGE); gauge_setup_pins(&RIGHT_GAUGE); R_UART1_Create(); R_IICA0_Create(); R_UART1_Start(); app_scheduler_init(); runtime_reset(); Cal_Init(); uart1_send_string_safe("BOOT single-mode\r\n"); uart_rx_done = 0; uart_rx_index = 0; uart_rx_length = 0; R_UART1_Receive((uint8_t *)&uart_rx_buffer[0], 1); while (1U) { app_kick_wdt(); if (uart_rx_done) { process_one_line(APP_CMD_SRC_PC, uart_rx_buffer, uart_rx_length); uart_rx_done = 0; uart_rx_index = 0; uart_rx_length = 0; R_UART1_Receive((uint8_t *)&uart_rx_buffer[0], 1); } app_job_tick(); app_kick_wdt(); } /* End user code. Do not edit comment generated here */ } /*********************************************************************************************************************** * Function Name: R_MAIN_UserInit * Description : This function adds user code before implementing main function. * Arguments : None * Return Value : None ***********************************************************************************************************************/ void R_MAIN_UserInit(void) { /* Start user code. Do not edit comment generated here */ EI(); R_PORT_Create(); /* End user code. Do not edit comment generated here */ } /* Start user code for adding. Do not edit comment generated here */ /* End user code. Do not edit comment generated here */