You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

1376 lines
35 KiB

/***********************************************************************************************************************
* 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 <string.h>
#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#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("<end>\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("<ACK>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 */