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.
1197 lines
30 KiB
1197 lines
30 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-04-13
|
|
***********************************************************************************************************************/
|
|
|
|
/***********************************************************************************************************************
|
|
Includes
|
|
***********************************************************************************************************************/
|
|
#include "r_cg_macrodriver.h"
|
|
#include "r_cg_cgc.h"
|
|
#include "r_cg_port.h"
|
|
#include "r_cg_serial.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 START_RELAY_SETTLE_MS 1000U
|
|
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;
|
|
|
|
/* 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 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 void debug_ck_edges(const gauge_pins_t *g)
|
|
{
|
|
char buf[64];
|
|
uint8_t prev, cur;
|
|
uint16_t edge_cnt = 0;
|
|
uint32_t i;
|
|
|
|
prev = gauge_read_pin(g->ck_p, g->ck_mask);
|
|
|
|
for (i = 0; i < 50000u; i++) { /* 50ms ���� */
|
|
cur = gauge_read_pin(g->ck_p, g->ck_mask);
|
|
if (cur != prev) {
|
|
edge_cnt++;
|
|
prev = cur;
|
|
}
|
|
delay_us(1u);
|
|
}
|
|
|
|
sprintf(buf, "CK_EDGE=%u\r\n", edge_cnt);
|
|
}
|
|
|
|
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 void debug_gauge_levels(const char *tag, const gauge_pins_t *g)
|
|
{
|
|
char buf[96];
|
|
int req, ck, data;
|
|
|
|
if (!g) return;
|
|
|
|
req = ((*(g->req_p)) & g->req_mask) ? 1 : 0;
|
|
ck = ((*(g->ck_p)) & g->ck_mask) ? 1 : 0;
|
|
data = ((*(g->data_p)) & g->data_mask) ? 1 : 0;
|
|
|
|
sprintf(buf, "%s REQ=%d CK=%d DATA=%d\r\n", tag, req, ck, data);
|
|
}
|
|
|
|
static uint8_t gauge_read_aligned_frame(const gauge_pins_t *g, gauge_state_t *s)
|
|
{
|
|
int i;
|
|
int start;
|
|
char buf[96];
|
|
int p;
|
|
|
|
if (!g || !s) return 0u;
|
|
|
|
gauge_req_stop(g);
|
|
delay_ms(10u);
|
|
debug_gauge_levels("BEFORE_START", g);
|
|
|
|
gauge_req_start(g);
|
|
delay_ms(20u);
|
|
debug_gauge_levels("AFTER_START", g);
|
|
|
|
|
|
|
|
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 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_print_value(const char *label, const gauge_state_t *s)
|
|
{
|
|
char buf[48];
|
|
|
|
if (!label || !s) return;
|
|
|
|
out_print(label);
|
|
|
|
if (s->valid) {
|
|
(void)sprintf(buf, "%.*f", s->decimal, s->value);
|
|
} else {
|
|
out_print("ERR");
|
|
}
|
|
}
|
|
|
|
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 print_owi_read_result(const app_owi_result_t *r)
|
|
{
|
|
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");
|
|
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);
|
|
}
|
|
|
|
static void print_connect_sweep_result(uint8_t ch, uint8_t ok)
|
|
{
|
|
char buf[32];
|
|
(void)sprintf(buf, "ch%u: %s\r\n", (unsigned)ch, ok ? "Success" : "Fail");
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
r = app_owi_read_basic(id, (int)read_len);
|
|
|
|
if ((!r.ok || r.timeout || r.read_len < read_len) && is_long_owi_read_len(read_len)) {
|
|
delay_us(OWI_LONG_READ_RETRY_US);
|
|
r = app_owi_read_basic(id, (int)read_len);
|
|
}
|
|
|
|
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 uint8_t tails_match_8(const uint8_t *a, const uint8_t *b)
|
|
{
|
|
if (!a || !b) return 0u;
|
|
return (uint8_t)(memcmp(a, b, 8u) == 0);
|
|
}
|
|
|
|
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 tail1[8];
|
|
uint8_t tail2[8];
|
|
uint8_t tail3[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(tail1)) return 0u;
|
|
if (!read_connected_nvm_tail8(tail2)) return 0u;
|
|
|
|
if (tails_match_8(tail1, tail2)) {
|
|
tail8_to_hex16(tail1, out_hex);
|
|
return 1u;
|
|
}
|
|
|
|
if (!read_connected_nvm_tail8(tail3)) return 0u;
|
|
|
|
if (tails_match_8(tail1, tail3)) {
|
|
tail8_to_hex16(tail1, out_hex);
|
|
return 1u;
|
|
}
|
|
|
|
if (tails_match_8(tail2, tail3)) {
|
|
tail8_to_hex16(tail2, out_hex);
|
|
return 1u;
|
|
}
|
|
|
|
return 0u;
|
|
}
|
|
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;
|
|
|
|
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);
|
|
|
|
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) return 0;
|
|
|
|
/* 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) return 0;
|
|
if (r_read2.data[0] != 0x72u || r_read2.data[1] != 0x72u) return 0;
|
|
|
|
/* 3) write 7C */
|
|
r_write3 = app_owi_write_t_basic(0x28u, &cmd_7c, 1u);
|
|
if (!r_write3.ok || r_write3.timeout) return 0;
|
|
|
|
/* 4) read 3 bytes -> compare with 7C 78 01 */
|
|
r_read3 = app_owi_read_basic(0x28u, 3);
|
|
if (!r_read3.ok || r_read3.timeout || r_read3.read_len < 3u) return 0;
|
|
|
|
if (memcmp(r_read3.data, expected_tail, 3u) != 0) return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
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) {
|
|
print_connect_sweep_result(ch, 1u);
|
|
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<end>\r\n", nvm_hex);
|
|
out_print(out);
|
|
} else {
|
|
out_print("Fail\r\n");
|
|
}
|
|
return 1;
|
|
read_len = 23u;
|
|
} 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");
|
|
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");
|
|
send_end_response();
|
|
return 1;
|
|
}
|
|
|
|
print_owi_read_result(&r_read);
|
|
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);
|
|
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);
|
|
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(15000U);
|
|
|
|
gauge_read(&LEFT_GAUGE, &leftGauge);
|
|
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(START_RELAY_SETTLE_MS);
|
|
do_nvm_read_after_gauge();
|
|
delay_ms(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 */
|
|
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();
|
|
|
|
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)
|
|
{
|
|
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();
|
|
}
|
|
/* 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 */
|
|
|