|
|
|
|
/***********************************************************************************************************************
|
|
|
|
|
* 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 : main + UART protocol handler
|
|
|
|
|
* Creation Date: 2026-01-29
|
|
|
|
|
***********************************************************************************************************************/
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************************************
|
|
|
|
|
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 "dipSwitch.h"
|
|
|
|
|
#include "gatectrl.h"
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <r_cg_port.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"
|
|
|
|
|
/* Start user code for adding. Do not edit comment generated here */
|
|
|
|
|
/* =========================
|
|
|
|
|
* Config
|
|
|
|
|
* ========================= */
|
|
|
|
|
#define CMD_MAX 529
|
|
|
|
|
#define UART_RX_BUF_SIZE 1024
|
|
|
|
|
#define RS485_BRIDGE_FIFO_SZ 2048
|
|
|
|
|
|
|
|
|
|
#define BRIDGE_IDLE_DONE_US 2000000U // ? 3ms ? ?
|
|
|
|
|
#define BRIDGE_TOTAL_WAIT_US 6000000U
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
|
|
|
* UART RX Buffers
|
|
|
|
|
* ========================= */
|
|
|
|
|
volatile uint8_t uart_rx_done = 0;
|
|
|
|
|
volatile uint16_t uart_rx_index = 0; // uint8_t -> uint16_t
|
|
|
|
|
volatile uint8_t uart_rx_buffer[UART_RX_BUF_SIZE] = {0};
|
|
|
|
|
volatile uint16_t uart_rx_length = 0;
|
|
|
|
|
|
|
|
|
|
volatile uint8_t rs485_rx_done = 0;
|
|
|
|
|
volatile uint16_t rs485_rx_index = 0;
|
|
|
|
|
volatile uint8_t rs485_rx_buffer[UART_RX_BUF_SIZE] = {0};
|
|
|
|
|
volatile uint16_t rs485_rx_length = 0;
|
|
|
|
|
|
|
|
|
|
volatile uint32_t g_uart0_err_fef = 0;
|
|
|
|
|
volatile uint32_t g_uart0_err_ovf = 0;
|
|
|
|
|
volatile uint32_t g_uart0_err_pef = 0;
|
|
|
|
|
|
|
|
|
|
/* RS485 bridge flags */
|
|
|
|
|
volatile uint8_t g_rs485_bridge_active = 0;
|
|
|
|
|
volatile uint8_t g_rs485_bridge_done = 0;
|
|
|
|
|
|
|
|
|
|
volatile uint16_t g_rs485_bridge_seq = 0;
|
|
|
|
|
|
|
|
|
|
static volatile uint8_t s_end_st = 0;
|
|
|
|
|
static const char s_end_pat[] = "<end>";
|
|
|
|
|
/* (0~31) */
|
|
|
|
|
uint8_t g_fixed_addr = 0;
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
|
|
|
* Driver globals (Renesas)
|
|
|
|
|
* ========================= */
|
|
|
|
|
extern volatile uint16_t g_uart1_tx_count; /* UART1 TX ?? */
|
|
|
|
|
extern volatile uint16_t g_uart0_tx_count; /* UART0 TX ?? */
|
|
|
|
|
|
|
|
|
|
extern volatile uint8_t g_uart0_tx_done;
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
|
|
|
* RS485 Bridge FIFO
|
|
|
|
|
* ========================= */
|
|
|
|
|
static volatile uint8_t s_rb_fifo[RS485_BRIDGE_FIFO_SZ];
|
|
|
|
|
static volatile uint16_t s_rb_head = 0;
|
|
|
|
|
static volatile uint16_t s_rb_tail = 0;
|
|
|
|
|
|
|
|
|
|
void RS485_Bridge_Push(uint8_t b)
|
|
|
|
|
{
|
|
|
|
|
uint16_t next = (uint16_t)(s_rb_head + 1);
|
|
|
|
|
if (next >= RS485_BRIDGE_FIFO_SZ) next = 0;
|
|
|
|
|
if (next == s_rb_tail) {
|
|
|
|
|
uint16_t t = (uint16_t)(s_rb_tail + 1);
|
|
|
|
|
if (t >= RS485_BRIDGE_FIFO_SZ) t = 0;
|
|
|
|
|
s_rb_tail = t;
|
|
|
|
|
}
|
|
|
|
|
s_rb_fifo[s_rb_head] = b;
|
|
|
|
|
s_rb_head = next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void RS485_Bridge_ResetFifo(void)
|
|
|
|
|
{
|
|
|
|
|
s_rb_head = 0;
|
|
|
|
|
s_rb_tail = 0;
|
|
|
|
|
s_end_st = 0;
|
|
|
|
|
g_rs485_bridge_done = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int RS485_Bridge_ReadLine(char *out, int out_sz, uint32_t timeout_us)
|
|
|
|
|
{
|
|
|
|
|
int n = 0;
|
|
|
|
|
|
|
|
|
|
while (timeout_us--) {
|
|
|
|
|
// FIFO
|
|
|
|
|
while (s_rb_tail != s_rb_head) {
|
|
|
|
|
char c = (char)s_rb_fifo[s_rb_tail];
|
|
|
|
|
s_rb_tail++;
|
|
|
|
|
if (s_rb_tail >= RS485_BRIDGE_FIFO_SZ) s_rb_tail = 0;
|
|
|
|
|
|
|
|
|
|
if (c == '\r') continue;
|
|
|
|
|
|
|
|
|
|
if (n < out_sz - 1) out[n++] = c;
|
|
|
|
|
|
|
|
|
|
if (c == '\n') {
|
|
|
|
|
out[n] = '\0';
|
|
|
|
|
return 1; // line
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
delay_us(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (n > 0) { out[n] = '\0'; }
|
|
|
|
|
return 0; // timeout
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int Is_V_Response_For(char *line, uint8_t addr)
|
|
|
|
|
{
|
|
|
|
|
uint8_t a;
|
|
|
|
|
|
|
|
|
|
if (line[0] != 'V' && line[0] != 'v') return 0;
|
|
|
|
|
if (!isdigit((unsigned char)line[1]) || !isdigit((unsigned char)line[2])) return 0;
|
|
|
|
|
|
|
|
|
|
a = (uint8_t)((line[1]-'0')*10 + (line[2]-'0'));
|
|
|
|
|
return (a == addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
|
|
|
* PC(UART1) Safe TX
|
|
|
|
|
* R_UART1_Send
|
|
|
|
|
* ========================= */
|
|
|
|
|
static uint8_t g_uart1_txbuf[1024];
|
|
|
|
|
|
|
|
|
|
static void UART1_WaitTxIdle(void)
|
|
|
|
|
{
|
|
|
|
|
unsigned long guard = 0;
|
|
|
|
|
while (g_uart1_tx_count != 0U) {
|
|
|
|
|
if (guard++ > 3000000UL) break; /* ? */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void UART1_SendBytes_Safe(const uint8_t *data, uint16_t len)
|
|
|
|
|
{
|
|
|
|
|
if (data == 0 || len == 0) return;
|
|
|
|
|
|
|
|
|
|
UART1_WaitTxIdle();
|
|
|
|
|
|
|
|
|
|
if (len > (uint16_t)sizeof(g_uart1_txbuf))
|
|
|
|
|
len = (uint16_t)sizeof(g_uart1_txbuf);
|
|
|
|
|
|
|
|
|
|
memcpy(g_uart1_txbuf, data, len);
|
|
|
|
|
|
|
|
|
|
R_UART1_Send(g_uart1_txbuf, len);
|
|
|
|
|
|
|
|
|
|
UART1_WaitTxIdle();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void UART1_SendString_Safe(const char *s)
|
|
|
|
|
{
|
|
|
|
|
uint16_t len;
|
|
|
|
|
|
|
|
|
|
if (s == 0) return;
|
|
|
|
|
|
|
|
|
|
UART1_WaitTxIdle(); // ?
|
|
|
|
|
|
|
|
|
|
len = (uint16_t)strlen(s);
|
|
|
|
|
if (len >= (uint16_t)sizeof(g_uart1_txbuf))
|
|
|
|
|
len = (uint16_t)(sizeof(g_uart1_txbuf) - 1);
|
|
|
|
|
|
|
|
|
|
memcpy(g_uart1_txbuf, s, len);
|
|
|
|
|
g_uart1_txbuf[len] = '\0';
|
|
|
|
|
|
|
|
|
|
R_UART1_Send(g_uart1_txbuf, len);
|
|
|
|
|
|
|
|
|
|
UART1_WaitTxIdle(); // ? ?: ? ( ? )
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
|
|
|
* RS485 Bridge Drain -> PC
|
|
|
|
|
* - uart1_send_string(out)
|
|
|
|
|
* - UART1_SendBytes_Safe
|
|
|
|
|
* ========================= */
|
|
|
|
|
static void RS485_Bridge_DrainToPC(void)
|
|
|
|
|
{
|
|
|
|
|
uint16_t n = 0;
|
|
|
|
|
|
|
|
|
|
/* UART1 TX */
|
|
|
|
|
if (g_uart1_tx_count != 0U) return;
|
|
|
|
|
|
|
|
|
|
while (s_rb_tail != s_rb_head && n < 1024U) {
|
|
|
|
|
g_uart1_txbuf[n++] = s_rb_fifo[s_rb_tail];
|
|
|
|
|
s_rb_tail++;
|
|
|
|
|
if (s_rb_tail >= RS485_BRIDGE_FIFO_SZ) s_rb_tail = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (n > 0) {
|
|
|
|
|
R_UART1_Send(g_uart1_txbuf, n);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
|
|
|
* Helpers
|
|
|
|
|
* ========================= */
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
|
|
|
* Prefix mode
|
|
|
|
|
* ========================= */
|
|
|
|
|
typedef enum {
|
|
|
|
|
PREFIX_NONE = 0,
|
|
|
|
|
PREFIX_CAL,
|
|
|
|
|
PREFIX_EOL
|
|
|
|
|
} PrefixMode;
|
|
|
|
|
|
|
|
|
|
static PrefixMode s_prefix_mode = PREFIX_NONE;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
uint8_t active;
|
|
|
|
|
uint8_t scan_started;
|
|
|
|
|
uint8_t current_scan_addr;
|
|
|
|
|
app_job_t job;
|
|
|
|
|
} app_runtime_job_t;
|
|
|
|
|
|
|
|
|
|
static app_runtime_job_t g_app_runtime_job;
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
|
|
|
* parse x-prefix: xNNc_001011:...
|
|
|
|
|
* ========================= */
|
|
|
|
|
static int parse_x_prefix(const char *s, int len,
|
|
|
|
|
uint8_t *addr, uint8_t *ch,
|
|
|
|
|
char *mode, uint8_t *hash_on, uint8_t *anaout_on, uint8_t *check_on, int *payload_pos)
|
|
|
|
|
{
|
|
|
|
|
if (len < 8) return 0;
|
|
|
|
|
if (!(s[0] == 'x' || s[0] == 'X')) return 0;
|
|
|
|
|
|
|
|
|
|
if (!isdigit((unsigned char)s[1]) || !isdigit((unsigned char)s[2])) return -1;
|
|
|
|
|
|
|
|
|
|
if (s[3] == 'c' || s[3] == 'C') *mode = 'C';
|
|
|
|
|
else if (s[3] == 'e' || s[3] == 'E') *mode = 'E';
|
|
|
|
|
else return -1;
|
|
|
|
|
|
|
|
|
|
if (s[4] != '_') return -1;
|
|
|
|
|
if (!isdigit((unsigned char)s[5]) || !isdigit((unsigned char)s[6]) || !isdigit((unsigned char)s[7])) return -1;
|
|
|
|
|
|
|
|
|
|
*addr = (uint8_t)((s[1] - '0') * 10 + (s[2] - '0'));
|
|
|
|
|
*ch = (uint8_t)((s[5] - '0') * 100 + (s[6] - '0') * 10 + (s[7] - '0'));
|
|
|
|
|
|
|
|
|
|
/* prefix only: x01c_001 */
|
|
|
|
|
if (len == 8) {
|
|
|
|
|
*payload_pos = len;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* payload: x01c_001:... */
|
|
|
|
|
if (s[8] == ':') {
|
|
|
|
|
*payload_pos = 9;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* flags: x01c_001011 or x01c_001011:... */
|
|
|
|
|
if (len >= 11 &&
|
|
|
|
|
(s[8] == '0' || s[8] == '1') &&
|
|
|
|
|
(s[9] == '0' || s[9] == '1') &&
|
|
|
|
|
(s[10] == '0' || s[10] == '1'))
|
|
|
|
|
{
|
|
|
|
|
*hash_on = (uint8_t)(s[8] - '0');
|
|
|
|
|
*anaout_on = (uint8_t)(s[9] - '0');
|
|
|
|
|
*check_on = (uint8_t)(s[10] - '0');
|
|
|
|
|
|
|
|
|
|
if (len == 11) { *payload_pos = 11; return 1; }
|
|
|
|
|
if (len >= 12 && s[11] == ':') { *payload_pos = 12; return 1; }
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int bridge_wait_until_end(uint32_t total_us)
|
|
|
|
|
{
|
|
|
|
|
const char *pat = "<end>";
|
|
|
|
|
uint8_t st = 0;
|
|
|
|
|
|
|
|
|
|
while (total_us--) {
|
|
|
|
|
// FIFO -> PC
|
|
|
|
|
while (s_rb_tail != s_rb_head) {
|
|
|
|
|
char c = (char)s_rb_fifo[s_rb_tail];
|
|
|
|
|
s_rb_tail = (s_rb_tail + 1) % RS485_BRIDGE_FIFO_SZ;
|
|
|
|
|
|
|
|
|
|
if (c == pat[st]) {
|
|
|
|
|
st++;
|
|
|
|
|
if (pat[st] == 0) return 1; // found
|
|
|
|
|
} else {
|
|
|
|
|
st = (c == pat[0]) ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
delay_us(1);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
|
|
|
* Print routing
|
|
|
|
|
* ========================= */
|
|
|
|
|
typedef enum {
|
|
|
|
|
CMD_SRC_PC = 0,
|
|
|
|
|
CMD_SRC_RS485 = 1
|
|
|
|
|
} CmdSource;
|
|
|
|
|
|
|
|
|
|
static void OUT_PRINT(CmdSource src, const char *s)
|
|
|
|
|
{
|
|
|
|
|
if (src == CMD_SRC_PC) {
|
|
|
|
|
UART1_SendString_Safe(s);
|
|
|
|
|
} else {
|
|
|
|
|
/* RS485_PRINT ? ?( UART0 TX) */
|
|
|
|
|
RS485_PRINT(s);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void send_end_response(CmdSource src)
|
|
|
|
|
{
|
|
|
|
|
OUT_PRINT(src, "<end>\r\n");
|
|
|
|
|
}
|
|
|
|
|
/* =========================
|
|
|
|
|
* xNNv command
|
|
|
|
|
* ========================= */
|
|
|
|
|
static int parse_x_v_cmd(const char *s, int len, uint8_t *addr)
|
|
|
|
|
{
|
|
|
|
|
if (len != 4) return 0;
|
|
|
|
|
if (!(s[0] == 'x' || s[0] == 'X')) return 0;
|
|
|
|
|
if (!isdigit((unsigned char)s[1]) || !isdigit((unsigned char)s[2])) return 0;
|
|
|
|
|
if (!(s[3] == 'v' || s[3] == 'V')) return 0;
|
|
|
|
|
|
|
|
|
|
*addr = (uint8_t)((s[1] - '0') * 10 + (s[2] - '0'));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
static void send_n_response(uint8_t addr)
|
|
|
|
|
{
|
|
|
|
|
char resp[8];
|
|
|
|
|
resp[0] = 'N';
|
|
|
|
|
resp[1] = (char)('0' + (addr / 10));
|
|
|
|
|
resp[2] = (char)('0' + (addr % 10));
|
|
|
|
|
resp[3] = '\r';
|
|
|
|
|
resp[4] = '\n';
|
|
|
|
|
resp[5] = '\0';
|
|
|
|
|
OUT_PRINT(CMD_SRC_PC, resp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int parse_x_o_cmd(const char *s, int len, uint8_t *addr)
|
|
|
|
|
{
|
|
|
|
|
if (len != 4) return 0;
|
|
|
|
|
if (!(s[0] == 'x' || s[0] == 'X')) return 0;
|
|
|
|
|
if (!isdigit((unsigned char)s[1]) || !isdigit((unsigned char)s[2])) return 0;
|
|
|
|
|
if (!(s[3] == 'o' || s[3] == 'O')) return 0;
|
|
|
|
|
|
|
|
|
|
*addr = (uint8_t)((s[1]-'0')*10 + (s[2]-'0'));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* OUT_PRINT Safe */
|
|
|
|
|
static void send_v_response(CmdSource src, uint8_t addr)
|
|
|
|
|
{
|
|
|
|
|
char resp[8];
|
|
|
|
|
|
|
|
|
|
resp[0] = 'V';
|
|
|
|
|
resp[1] = (char)('0' + (addr / 10));
|
|
|
|
|
resp[2] = (char)('0' + (addr % 10));
|
|
|
|
|
resp[3] = '\r';
|
|
|
|
|
resp[4] = '\n';
|
|
|
|
|
resp[5] = '\0';
|
|
|
|
|
|
|
|
|
|
if (src == CMD_SRC_RS485) {
|
|
|
|
|
delay_us(1200); // 200~500us
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OUT_PRINT(src, resp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void UART0_WaitTxDone_Flag(uint32_t guard_us)
|
|
|
|
|
{
|
|
|
|
|
while (!g_uart0_tx_done && guard_us--) {
|
|
|
|
|
delay_us(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void RS485_FlushJunk(uint16_t loops, uint16_t step_us)
|
|
|
|
|
{
|
|
|
|
|
while (loops--) {
|
|
|
|
|
RS485_Bridge_DrainToPC();
|
|
|
|
|
delay_us(step_us);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void PC_PrintLine_CRLF(const char *line)
|
|
|
|
|
{
|
|
|
|
|
char tmp[320];
|
|
|
|
|
size_t n = strlen(line);
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
// line '\n' , "\r\n"
|
|
|
|
|
if (n > 0 && line[n-1] == '\n') {
|
|
|
|
|
size_t m = 0;
|
|
|
|
|
for (i=0; i<n && m < sizeof(tmp)-3; i++) {
|
|
|
|
|
if (line[i] == '\r') continue;
|
|
|
|
|
if (line[i] == '\n') { tmp[m++] = '\r'; tmp[m++] = '\n'; }
|
|
|
|
|
else tmp[m++] = line[i];
|
|
|
|
|
}
|
|
|
|
|
tmp[m] = 0;
|
|
|
|
|
UART1_SendString_Safe(tmp);
|
|
|
|
|
} else {
|
|
|
|
|
UART1_SendString_Safe(line);
|
|
|
|
|
UART1_SendString_Safe("\r\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
|
|
|
* RS485 scan: xNNv\r\n
|
|
|
|
|
* ========================= */
|
|
|
|
|
static void scan_one_addr_rs485(uint8_t addr)
|
|
|
|
|
{
|
|
|
|
|
char cmdline[8];
|
|
|
|
|
uint8_t try;
|
|
|
|
|
|
|
|
|
|
if (addr == 0) return;
|
|
|
|
|
|
|
|
|
|
cmdline[0] = 'x';
|
|
|
|
|
cmdline[1] = (char)('0' + (addr / 10));
|
|
|
|
|
cmdline[2] = (char)('0' + (addr % 10));
|
|
|
|
|
cmdline[3] = 'v';
|
|
|
|
|
cmdline[4] = '\r';
|
|
|
|
|
cmdline[5] = '\n';
|
|
|
|
|
cmdline[6] = '\0';
|
|
|
|
|
|
|
|
|
|
RS485_FlushJunk(2, 100);
|
|
|
|
|
|
|
|
|
|
for (try = 0; try < 1; try++) { /* ���õ��� �켱 1ȸ�� ���̱� */
|
|
|
|
|
uint32_t total_wait_us;
|
|
|
|
|
char linebuf[320];
|
|
|
|
|
|
|
|
|
|
if (g_rs485_need_recover) {
|
|
|
|
|
rs485_recover();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_rs485_bridge_active = 1;
|
|
|
|
|
g_rs485_bridge_done = 0;
|
|
|
|
|
RS485_Bridge_ResetFifo();
|
|
|
|
|
|
|
|
|
|
rs485_rx_done = 0;
|
|
|
|
|
rs485_rx_index = 0;
|
|
|
|
|
rs485_rx_length = 0;
|
|
|
|
|
R_UART0_Receive((uint8_t*)&rs485_rx_buffer[0], 1);
|
|
|
|
|
|
|
|
|
|
g_uart0_tx_done = 0;
|
|
|
|
|
RS485_PRINT(cmdline);
|
|
|
|
|
|
|
|
|
|
UART0_WaitTxDone_Flag(10000);
|
|
|
|
|
rs485_set_tx(0);
|
|
|
|
|
delay_us(500);
|
|
|
|
|
|
|
|
|
|
total_wait_us = 10000U;
|
|
|
|
|
|
|
|
|
|
while (total_wait_us >= 500U) {
|
|
|
|
|
int got = RS485_Bridge_ReadLine(linebuf, sizeof(linebuf), 500);
|
|
|
|
|
|
|
|
|
|
if (got) {
|
|
|
|
|
/* echo ������ ���� */
|
|
|
|
|
if (linebuf[0] == 'x' || linebuf[0] == 'X') {
|
|
|
|
|
total_wait_us -= 500U;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Is_V_Response_For(linebuf, addr)) {
|
|
|
|
|
PC_PrintLine_CRLF(linebuf);
|
|
|
|
|
g_rs485_bridge_active = 0;
|
|
|
|
|
delay_us(500);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
total_wait_us -= 500U;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_rs485_bridge_active = 0;
|
|
|
|
|
delay_us(500);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
send_n_response(addr);
|
|
|
|
|
|
|
|
|
|
rs485_rx_done = 0;
|
|
|
|
|
rs485_rx_index = 0;
|
|
|
|
|
rs485_rx_length = 0;
|
|
|
|
|
R_UART0_Receive((uint8_t*)&rs485_rx_buffer[0], 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
|
|
|
* Build line from rx buffer
|
|
|
|
|
* ========================= */
|
|
|
|
|
static int build_line_from_rx(const volatile uint8_t *rx_buf, int rx_len,
|
|
|
|
|
char *out, int out_sz)
|
|
|
|
|
{
|
|
|
|
|
int i, idx = 0;
|
|
|
|
|
|
|
|
|
|
if (rx_len < 0) rx_len = 0;
|
|
|
|
|
if (rx_len > out_sz - 1) rx_len = out_sz - 1;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < rx_len && idx < out_sz - 1; i++) {
|
|
|
|
|
char c = (char)rx_buf[i];
|
|
|
|
|
if (c == '\r') continue;
|
|
|
|
|
if (c == '\n') break;
|
|
|
|
|
out[idx++] = c;
|
|
|
|
|
}
|
|
|
|
|
out[idx] = '\0';
|
|
|
|
|
return idx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
|
|
|
* Protocol detect
|
|
|
|
|
* ========================= */
|
|
|
|
|
typedef enum {
|
|
|
|
|
PROTOCOL_I2CT,
|
|
|
|
|
PROTOCOL_OWIT,
|
|
|
|
|
PROTOCOL_I2CW,
|
|
|
|
|
PROTOCOL_I2CR,
|
|
|
|
|
PROTOCOL_OWIW,
|
|
|
|
|
PROTOCOL_OWIR,
|
|
|
|
|
PROTOCOL_UNKNOWN
|
|
|
|
|
} ProtocolType;
|
|
|
|
|
|
|
|
|
|
static ProtocolType detect_protocol(char header1, char header2)
|
|
|
|
|
{
|
|
|
|
|
if (header1 == 'I' && header2 == 'W') return PROTOCOL_I2CW;
|
|
|
|
|
if (header1 == 'I' && header2 == 'R') return PROTOCOL_I2CR;
|
|
|
|
|
if (header1 == 'O' && header2 == 'W') return PROTOCOL_OWIW;
|
|
|
|
|
if (header1 == 'O' && header2 == 'R') return PROTOCOL_OWIR;
|
|
|
|
|
return PROTOCOL_UNKNOWN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void cmd_unknown(const unsigned char *d, unsigned int len)
|
|
|
|
|
{
|
|
|
|
|
(void)d; (void)len;
|
|
|
|
|
OUT_PRINT(CMD_SRC_PC, "Unknown cmd\r\n");
|
|
|
|
|
delay(100000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void print_owi_write_result(CmdSource src, const app_owi_result_t *r)
|
|
|
|
|
{
|
|
|
|
|
char msg[64];
|
|
|
|
|
|
|
|
|
|
if (!r) {
|
|
|
|
|
OUT_PRINT(src, "Err:owi_null\r\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!r->ok || r->timeout) {
|
|
|
|
|
sprintf(msg, "51 !TO(B%u b%u)\r\n",
|
|
|
|
|
(unsigned)r->timeout_byte_index,
|
|
|
|
|
(unsigned)r->timeout_bit_index);
|
|
|
|
|
OUT_PRINT(src, msg);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OUT_PRINT(src, "51\r\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void print_owi_read_result(CmdSource src, const app_owi_result_t *r)
|
|
|
|
|
{
|
|
|
|
|
char out[(2 * OWI_IO_MAX_BYTES) + 64];
|
|
|
|
|
uint16_t p = 0;
|
|
|
|
|
uint16_t i;
|
|
|
|
|
|
|
|
|
|
if (!r) {
|
|
|
|
|
OUT_PRINT(src, "Err:owi_null\r\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (r->read_len == 0) {
|
|
|
|
|
OUT_PRINT(src, "Err:read_len_nonzero\r\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < r->read_len && i < OWI_IO_MAX_BYTES; i++) {
|
|
|
|
|
uint8_t b = r->data[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(src, out);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
uint8_t active;
|
|
|
|
|
uint8_t addr;
|
|
|
|
|
uint8_t channel;
|
|
|
|
|
uint8_t mode;
|
|
|
|
|
uint8_t hash_on;
|
|
|
|
|
uint8_t anaout_on;
|
|
|
|
|
uint8_t check_on;
|
|
|
|
|
uint8_t id;
|
|
|
|
|
|
|
|
|
|
uint8_t first_tx[3];
|
|
|
|
|
uint8_t expected_tail[3];
|
|
|
|
|
} connect_verify_ctx_t;
|
|
|
|
|
|
|
|
|
|
static connect_verify_ctx_t g_connect_verify;
|
|
|
|
|
|
|
|
|
|
static void connect_verify_reset(void)
|
|
|
|
|
{
|
|
|
|
|
memset(&g_connect_verify, 0, sizeof(g_connect_verify));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void print_hex_line(CmdSource src, const uint8_t *data, uint16_t len)
|
|
|
|
|
{
|
|
|
|
|
char out[(2 * OWI_IO_MAX_BYTES) + 64];
|
|
|
|
|
uint16_t p = 0;
|
|
|
|
|
uint16_t i;
|
|
|
|
|
|
|
|
|
|
if (!data || len == 0) {
|
|
|
|
|
OUT_PRINT(src, "\r\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < len && i < OWI_IO_MAX_BYTES; i++) {
|
|
|
|
|
uint8_t b = data[i];
|
|
|
|
|
out[p++] = "0123456789ABCDEF"[b >> 4];
|
|
|
|
|
out[p++] = "0123456789ABCDEF"[b & 0x0F];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out[p++] = '\r';
|
|
|
|
|
out[p++] = '\n';
|
|
|
|
|
out[p] = '\0';
|
|
|
|
|
|
|
|
|
|
OUT_PRINT(src, out);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int execute_connect_verify_sequence(CmdSource src, const app_job_t *job)
|
|
|
|
|
{
|
|
|
|
|
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 = 0x7C;
|
|
|
|
|
uint8_t attempt;
|
|
|
|
|
|
|
|
|
|
if (!job) return 0;
|
|
|
|
|
|
|
|
|
|
/* connect ���� ����
|
|
|
|
|
xNNc_XXX...:owt28006 AABBCC DDEEFF
|
|
|
|
|
- id = 0x28
|
|
|
|
|
- len = 6
|
|
|
|
|
- payload[0..2] = ù write 3����Ʈ
|
|
|
|
|
- payload[3..5] = ���� ���� ���밪 3����Ʈ
|
|
|
|
|
*/
|
|
|
|
|
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->addr != g_fixed_addr) return 0;
|
|
|
|
|
|
|
|
|
|
if (job->channel < 1 || job->channel > 20) {
|
|
|
|
|
OUT_PRINT(src, "Err:ch_range\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy(write1_data, &job->payload[0], 3);
|
|
|
|
|
memcpy(expected_tail, &job->payload[3], 3);
|
|
|
|
|
|
|
|
|
|
for (attempt = 0; attempt < 2; attempt++) {
|
|
|
|
|
|
|
|
|
|
/* ���õ� �� OFF ó�� */
|
|
|
|
|
if (attempt > 0) {
|
|
|
|
|
Cal_Init();
|
|
|
|
|
delay_us(30000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* prefix / gate */
|
|
|
|
|
if (job->mode == 'C') {
|
|
|
|
|
s_prefix_mode = PREFIX_CAL;
|
|
|
|
|
Cal_Init();
|
|
|
|
|
} else {
|
|
|
|
|
s_prefix_mode = PREFIX_EOL;
|
|
|
|
|
Eol_Init();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Gate_SetByNum(job->channel, job->hash_on, job->anaout_on, job->check_on);
|
|
|
|
|
GateCtrl_SelectChannel(job->channel);
|
|
|
|
|
|
|
|
|
|
delay_us(30000);
|
|
|
|
|
|
|
|
|
|
/* 1) OWT 28 003 + first3 */
|
|
|
|
|
r_write1 = app_owi_write_t_basic(0x28u, write1_data, 3);
|
|
|
|
|
if (!r_write1.ok || r_write1.timeout) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 2) OR 28 002 */
|
|
|
|
|
r_read2 = app_owi_read_basic(0x28u, 2);
|
|
|
|
|
if (!r_read2.ok || r_read2.timeout || r_read2.read_len < 2) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 3) OWT 28 001 + 7C */
|
|
|
|
|
r_write3 = app_owi_write_t_basic(0x28u, &cmd_7c, 1);
|
|
|
|
|
if (!r_write3.ok || r_write3.timeout) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 4) OR 28 003 -> ���� Ĩ ���� �б� */
|
|
|
|
|
r_read3 = app_owi_read_basic(0x28u, 3);
|
|
|
|
|
if (!r_read3.ok || r_read3.timeout || r_read3.read_len < 3) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ���� ���� 3����Ʈ�� ���밪 ���� */
|
|
|
|
|
if (memcmp(r_read3.data, expected_tail, 3) == 0) {
|
|
|
|
|
OUT_PRINT(src, "Success\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int execute_direct_read_sequence(CmdSource src, const app_job_t *job)
|
|
|
|
|
{
|
|
|
|
|
app_owi_result_t r_write;
|
|
|
|
|
app_owi_result_t r_read;
|
|
|
|
|
uint8_t read_len = 0;
|
|
|
|
|
|
|
|
|
|
if (!job) return 0;
|
|
|
|
|
|
|
|
|
|
/* �Ϲ� OW ���ϸ� ó�� */
|
|
|
|
|
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->addr != g_fixed_addr) return 0;
|
|
|
|
|
|
|
|
|
|
if (job->channel < 1 || job->channel > 20) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (job->mode == 'C') {
|
|
|
|
|
s_prefix_mode = PREFIX_CAL;
|
|
|
|
|
Cal_Init();
|
|
|
|
|
} else {
|
|
|
|
|
s_prefix_mode = PREFIX_EOL;
|
|
|
|
|
Eol_Init();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Gate_SetByNum(job->channel, job->hash_on, job->anaout_on, job->check_on);
|
|
|
|
|
GateCtrl_SelectChannel(job->channel);
|
|
|
|
|
|
|
|
|
|
/* payload 3����Ʈ �������� read ���� ���� */
|
|
|
|
|
if (job->payload[0] == 0x2E && job->payload[1] == 0x00 && job->payload[2] == 0x1F) {
|
|
|
|
|
read_len = 65; /* outmem */
|
|
|
|
|
}
|
|
|
|
|
else if (job->payload[0] == 0x22 && job->payload[1] == 0x00 && job->payload[2] == 0x3A) {
|
|
|
|
|
read_len = 119; /* shadow */
|
|
|
|
|
}
|
|
|
|
|
else if (job->payload[0] == 0x26 && job->payload[1] == 0x00 && job->payload[2] == 0x3E) {
|
|
|
|
|
read_len = 127; /* nvm */
|
|
|
|
|
}
|
|
|
|
|
else if (job->payload[0] == 0x0B && job->payload[1] == 0x04 && job->payload[2] == 0x06) {
|
|
|
|
|
read_len = 23; /* acquiredata */
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return 0; /* �Ϲ� ow�� ���� ó���� �ѱ� */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 1) GUI���� ���� ow ���� �״��� write */
|
|
|
|
|
r_write = app_owi_write_basic(0x28u, job->payload, 3);
|
|
|
|
|
if (!r_write.ok || r_write.timeout) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 2) �����Ǵ� read ���� */
|
|
|
|
|
r_read = app_owi_read_basic(0x28u, read_len);
|
|
|
|
|
if (!r_read.ok || r_read.timeout || r_read.read_len < read_len) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 3) ���� ���� ���� */
|
|
|
|
|
print_owi_read_result(src, &r_read);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int execute_write_coeff_sequence(CmdSource src, const app_job_t *job)
|
|
|
|
|
{
|
|
|
|
|
app_owi_result_t r_write1;
|
|
|
|
|
app_owi_result_t r_read1;
|
|
|
|
|
app_owi_result_t r_write2;
|
|
|
|
|
app_owi_result_t r_read2;
|
|
|
|
|
|
|
|
|
|
static const uint8_t nvm_read_cmd[3] = { 0x26, 0x00, 0x3E };
|
|
|
|
|
|
|
|
|
|
/* coefficient data:
|
|
|
|
|
payload[0] = 0x23 (write coeff cmd)
|
|
|
|
|
payload[1] = 0x0D (start addr)
|
|
|
|
|
payload[2] = 0x0E (length info -> 15 words)
|
|
|
|
|
payload[3..32] = coefficient 15 words = 30 bytes
|
|
|
|
|
*/
|
|
|
|
|
const uint8_t *coeff_data;
|
|
|
|
|
const uint8_t *nvm_coeff_data;
|
|
|
|
|
|
|
|
|
|
uint16_t coeff_len_bytes = 30u;
|
|
|
|
|
|
|
|
|
|
/* NVM read result format:
|
|
|
|
|
data[0] = 0x26 header
|
|
|
|
|
data[1..126] = 63 words = 126 bytes
|
|
|
|
|
coefficient word range = 0x0D ~ 0x1B (15 words)
|
|
|
|
|
byte start index = 1 + (0x0D * 2) = 27
|
|
|
|
|
*/
|
|
|
|
|
uint16_t nvm_coeff_start = 1u + (0x0Du * 2u);
|
|
|
|
|
|
|
|
|
|
if (!job) return 0;
|
|
|
|
|
|
|
|
|
|
/* write coefficients ���� ���� */
|
|
|
|
|
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->addr != g_fixed_addr) return 0;
|
|
|
|
|
|
|
|
|
|
/* prefix �ĺ� Ȯ�� */
|
|
|
|
|
if (!(job->len >= 3u &&
|
|
|
|
|
job->payload[0] == 0x23u &&
|
|
|
|
|
job->payload[1] == 0x0Du &&
|
|
|
|
|
job->payload[2] == 0x0Eu)) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ���̴� ��Ȯ�� 33����Ʈ���� �� */
|
|
|
|
|
if (job->len != 33u) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (job->channel < 1 || job->channel > 20) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (job->mode == 'C') {
|
|
|
|
|
s_prefix_mode = PREFIX_CAL;
|
|
|
|
|
Cal_Init();
|
|
|
|
|
} else {
|
|
|
|
|
s_prefix_mode = PREFIX_EOL;
|
|
|
|
|
Eol_Init();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Gate_SetByNum(job->channel, job->hash_on, job->anaout_on, job->check_on);
|
|
|
|
|
GateCtrl_SelectChannel(job->channel);
|
|
|
|
|
|
|
|
|
|
coeff_data = &job->payload[3];
|
|
|
|
|
|
|
|
|
|
/* 1) GUI�� ���� coefficient write ��ü ���� */
|
|
|
|
|
r_write1 = app_owi_write_basic(0x28u, job->payload, (uint8_t)job->len);
|
|
|
|
|
if (!r_write1.ok || r_write1.timeout) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 2) or28001 -> 23 Ȯ�� */
|
|
|
|
|
r_read1 = app_owi_read_basic(0x28u, 1);
|
|
|
|
|
if (!r_read1.ok || r_read1.timeout || r_read1.read_len < 1) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (r_read1.data[0] != 0x23u) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 3) NVM read command: ow2800326003e */
|
|
|
|
|
r_write2 = app_owi_write_basic(0x28u, nvm_read_cmd, 3);
|
|
|
|
|
if (!r_write2.ok || r_write2.timeout) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 4) or28127 */
|
|
|
|
|
r_read2 = app_owi_read_basic(0x28u, 127);
|
|
|
|
|
if (!r_read2.ok || r_read2.timeout || r_read2.read_len < 127) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* NVM read ���� ù ����Ʈ�� 0x26 �̾��� ���� */
|
|
|
|
|
if (r_read2.data[0] != 0x26u) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 5) coefficient ���� readback ����
|
|
|
|
|
- coeff_data: payload[3..32] (30 bytes)
|
|
|
|
|
- nvm_coeff_data: r_read2.data[27..56] (30 bytes)
|
|
|
|
|
*/
|
|
|
|
|
nvm_coeff_data = &r_read2.data[nvm_coeff_start];
|
|
|
|
|
|
|
|
|
|
if (memcmp(nvm_coeff_data, coeff_data, coeff_len_bytes) == 0) {
|
|
|
|
|
OUT_PRINT(src, "Success\r\n");
|
|
|
|
|
} else {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int execute_shadow_write_copy_nvm_sequence(CmdSource src, const app_job_t *job)
|
|
|
|
|
{
|
|
|
|
|
app_owi_result_t r_write;
|
|
|
|
|
app_owi_result_t r_read;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const uint8_t cmd_crc_44[3] = { 0x44, 0x00, 0x39 };
|
|
|
|
|
static const uint8_t cmd_15_3c5b[3] = { 0x15, 0x3C, 0x5B };
|
|
|
|
|
static const uint8_t cmd_14[1] = { 0x14 };
|
|
|
|
|
static const uint8_t cmd_1a[1] = { 0x1A };
|
|
|
|
|
static const uint8_t cmd_crc_40[3] = { 0x40, 0x00, 0x39 };
|
|
|
|
|
static const uint8_t cmd_crc_42[3] = { 0x42, 0x00, 0x39 };
|
|
|
|
|
static const uint8_t cmd_15_0000[3] = { 0x15, 0x00, 0x00 };
|
|
|
|
|
static const uint8_t cmd_nvm_read[3] = { 0x26, 0x00, 0x3E };
|
|
|
|
|
|
|
|
|
|
const uint8_t *gui_crc;
|
|
|
|
|
uint16_t poll_count = 0;
|
|
|
|
|
|
|
|
|
|
if (!job) return 0;
|
|
|
|
|
|
|
|
|
|
/* shadow write + shadow to nvm ���� ����
|
|
|
|
|
payload = 230039 + data(116����Ʈ) + crc(2����Ʈ)
|
|
|
|
|
��ü len = 121����Ʈ
|
|
|
|
|
*/
|
|
|
|
|
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->addr != g_fixed_addr) return 0;
|
|
|
|
|
|
|
|
|
|
/* payload ���� ����: 23 00 39 */
|
|
|
|
|
if (!(job->len >= 3u &&
|
|
|
|
|
job->payload[0] == 0x23u &&
|
|
|
|
|
job->payload[1] == 0x00u &&
|
|
|
|
|
job->payload[2] == 0x39u)) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ��ü ���̴� ��Ȯ�� 121����Ʈ */
|
|
|
|
|
if (job->len != 121u) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (job->channel < 1 || job->channel > 20) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (job->mode == 'C') {
|
|
|
|
|
s_prefix_mode = PREFIX_CAL;
|
|
|
|
|
Cal_Init();
|
|
|
|
|
} else {
|
|
|
|
|
s_prefix_mode = PREFIX_EOL;
|
|
|
|
|
Eol_Init();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Gate_SetByNum(job->channel, job->hash_on, job->anaout_on, job->check_on);
|
|
|
|
|
GateCtrl_SelectChannel(job->channel);
|
|
|
|
|
|
|
|
|
|
/* ������ 2����Ʈ�� GUI CRC�� ���� */
|
|
|
|
|
gui_crc = &job->payload[119];
|
|
|
|
|
|
|
|
|
|
/* 1) ow28119230039 + data + crc */
|
|
|
|
|
r_write = app_owi_write_basic(0x28u, job->payload, 119u);
|
|
|
|
|
if (!r_write.ok || r_write.timeout) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 2) or28001 -> 23 */
|
|
|
|
|
r_read = app_owi_read_basic(0x28u, 1);
|
|
|
|
|
if (!r_read.ok || r_read.timeout || r_read.read_len < 1) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (r_read.data[0] != 0x23u) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 3) ow28003440039 */
|
|
|
|
|
r_write = app_owi_write_basic(0x28u, cmd_crc_44, 3);
|
|
|
|
|
if (!r_write.ok || r_write.timeout) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 4) or28003 -> 44 + CRC */
|
|
|
|
|
r_read = app_owi_read_basic(0x28u, 3);
|
|
|
|
|
if (!r_read.ok || r_read.timeout || r_read.read_len < 3) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (r_read.data[0] != 0x44u) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (memcmp(&r_read.data[1], gui_crc, 2) != 0) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 5) ow28003153c5b */
|
|
|
|
|
r_write = app_owi_write_basic(0x28u, cmd_15_3c5b, 3);
|
|
|
|
|
if (!r_write.ok || r_write.timeout) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 6) or28003 -> 150001 */
|
|
|
|
|
r_read = app_owi_read_basic(0x28u, 3);
|
|
|
|
|
if (!r_read.ok || r_read.timeout || r_read.read_len < 3) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (!(r_read.data[0] == 0x15u && r_read.data[1] == 0x00u && r_read.data[2] == 0x01u)) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 7) ow2800114 */
|
|
|
|
|
r_write = app_owi_write_basic(0x28u, cmd_14, 1);
|
|
|
|
|
if (!r_write.ok || r_write.timeout) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 8) or28003 -> 140001 */
|
|
|
|
|
r_read = app_owi_read_basic(0x28u, 3);
|
|
|
|
|
if (!r_read.ok || r_read.timeout || r_read.read_len < 3) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (!(r_read.data[0] == 0x14u && r_read.data[1] == 0x00u && r_read.data[2] == 0x01u)) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 9) ow280011a �� ���� ���� */
|
|
|
|
|
r_write = app_owi_write_basic(0x28u, cmd_1a, 1);
|
|
|
|
|
if (!r_write.ok || r_write.timeout) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (poll_count = 0; poll_count < 50u; poll_count++) {
|
|
|
|
|
char dbg[40];
|
|
|
|
|
|
|
|
|
|
r_read = app_owi_read_basic(0x28u, 3);
|
|
|
|
|
if (!r_read.ok || r_read.timeout || r_read.read_len < 3) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (r_read.data[0] == 0x1Au &&
|
|
|
|
|
r_read.data[1] == 0x00u &&
|
|
|
|
|
r_read.data[2] == 0x00u) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delay_us(5000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (poll_count >= 50u) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 10) ow28003400039 */
|
|
|
|
|
r_write = app_owi_write_basic(0x28u, cmd_crc_40, 3);
|
|
|
|
|
if (!r_write.ok || r_write.timeout) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 11) or28003 -> 40 + CRC */
|
|
|
|
|
r_read = app_owi_read_basic(0x28u, 3);
|
|
|
|
|
if (!r_read.ok || r_read.timeout || r_read.read_len < 3) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (r_read.data[0] != 0x40u) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (memcmp(&r_read.data[1], gui_crc, 2) != 0) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 12) ow28003420039 */
|
|
|
|
|
r_write = app_owi_write_basic(0x28u, cmd_crc_42, 3);
|
|
|
|
|
if (!r_write.ok || r_write.timeout) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 13) or28003 -> 42 + CRC */
|
|
|
|
|
r_read = app_owi_read_basic(0x28u, 3);
|
|
|
|
|
if (!r_read.ok || r_read.timeout || r_read.read_len < 3) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (r_read.data[0] != 0x42u) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (memcmp(&r_read.data[1], gui_crc, 2) != 0) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 14) ow28003150000 */
|
|
|
|
|
r_write = app_owi_write_basic(0x28u, cmd_15_0000, 3);
|
|
|
|
|
if (!r_write.ok || r_write.timeout) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 15) or28003 -> 150000 */
|
|
|
|
|
r_read = app_owi_read_basic(0x28u, 3);
|
|
|
|
|
if (!r_read.ok || r_read.timeout || r_read.read_len < 3) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (!(r_read.data[0] == 0x15u && r_read.data[1] == 0x00u && r_read.data[2] == 0x00u)) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 16) ow2800326003e */
|
|
|
|
|
r_write = app_owi_write_basic(0x28u, cmd_nvm_read, 3);
|
|
|
|
|
if (!r_write.ok || r_write.timeout) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 17) or28127 */
|
|
|
|
|
r_read = app_owi_read_basic(0x28u, 127);
|
|
|
|
|
if (!r_read.ok || r_read.timeout || r_read.read_len < 127) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (r_read.data[0] != 0x26u) {
|
|
|
|
|
OUT_PRINT(src, "Fail\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print_owi_read_result(src, &r_read);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int execute_owi_service_from_job(CmdSource src, const app_job_t *job)
|
|
|
|
|
{
|
|
|
|
|
app_owi_result_t r;
|
|
|
|
|
|
|
|
|
|
if (!job) return 0;
|
|
|
|
|
|
|
|
|
|
// connect
|
|
|
|
|
if (execute_connect_verify_sequence(src, job)) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// nvm, shadow, outmem
|
|
|
|
|
if (execute_direct_read_sequence(src, job)) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// write_coefficient
|
|
|
|
|
if (execute_write_coeff_sequence(src, job)) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// shadow_write to copy nvm
|
|
|
|
|
if (execute_shadow_write_copy_nvm_sequence(src, job)) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (job->addr != g_fixed_addr) return 0;
|
|
|
|
|
if (job->channel < 1 || job->channel > 20) {
|
|
|
|
|
OUT_PRINT(src, "Err:ch_range\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (job->mode == 'C') {
|
|
|
|
|
s_prefix_mode = PREFIX_CAL;
|
|
|
|
|
Cal_Init();
|
|
|
|
|
} else {
|
|
|
|
|
s_prefix_mode = PREFIX_EOL;
|
|
|
|
|
Eol_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(src, &r);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (job->type == APP_JOB_PROTO_OR) {
|
|
|
|
|
r = app_owi_read_basic(job->id, (int)job->len);
|
|
|
|
|
print_owi_read_result(src, &r);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void forward_line_rs485_and_bridge(const char *line)
|
|
|
|
|
{
|
|
|
|
|
static char txbuf[UART_RX_BUF_SIZE + 4];
|
|
|
|
|
uint32_t total_us;
|
|
|
|
|
uint32_t idle_us = 0;
|
|
|
|
|
char linebuf[320];
|
|
|
|
|
int line_len = 0;
|
|
|
|
|
int n;
|
|
|
|
|
uint8_t got_any_line = 0;
|
|
|
|
|
|
|
|
|
|
if (!line) return;
|
|
|
|
|
|
|
|
|
|
g_rs485_bridge_active = 1;
|
|
|
|
|
g_rs485_bridge_done = 0;
|
|
|
|
|
RS485_Bridge_ResetFifo();
|
|
|
|
|
|
|
|
|
|
rs485_rx_done = 0;
|
|
|
|
|
rs485_rx_index = 0;
|
|
|
|
|
rs485_rx_length = 0;
|
|
|
|
|
R_UART0_Receive((uint8_t*)&rs485_rx_buffer[0], 1);
|
|
|
|
|
|
|
|
|
|
n = (int)strlen(line);
|
|
|
|
|
if (n > (int)sizeof(txbuf) - 3) n = (int)sizeof(txbuf) - 3;
|
|
|
|
|
|
|
|
|
|
memcpy(txbuf, line, (size_t)n);
|
|
|
|
|
txbuf[n++] = '\r';
|
|
|
|
|
txbuf[n++] = '\n';
|
|
|
|
|
txbuf[n] = '\0';
|
|
|
|
|
|
|
|
|
|
g_uart0_tx_done = 0;
|
|
|
|
|
RS485_PRINT(txbuf);
|
|
|
|
|
|
|
|
|
|
UART0_WaitTxDone_Flag(10000);
|
|
|
|
|
rs485_set_tx(0);
|
|
|
|
|
delay_us(500);
|
|
|
|
|
|
|
|
|
|
total_us = BRIDGE_TOTAL_WAIT_US;
|
|
|
|
|
line_len = 0;
|
|
|
|
|
linebuf[0] = '\0';
|
|
|
|
|
|
|
|
|
|
while (total_us >= 50U) {
|
|
|
|
|
uint8_t had_byte = 0;
|
|
|
|
|
|
|
|
|
|
/* FIFO���� ����Ʈ�� �ϳ��� ���� ���� */
|
|
|
|
|
while (s_rb_tail != s_rb_head) {
|
|
|
|
|
char c = (char)s_rb_fifo[s_rb_tail];
|
|
|
|
|
s_rb_tail++;
|
|
|
|
|
if (s_rb_tail >= RS485_BRIDGE_FIFO_SZ) s_rb_tail = 0;
|
|
|
|
|
|
|
|
|
|
had_byte = 1;
|
|
|
|
|
|
|
|
|
|
/* CR ���� */
|
|
|
|
|
if (c == '\r') continue;
|
|
|
|
|
|
|
|
|
|
/* ���ۿ� ���� */
|
|
|
|
|
if (line_len < (int)sizeof(linebuf) - 1) {
|
|
|
|
|
linebuf[line_len++] = c;
|
|
|
|
|
linebuf[line_len] = '\0';
|
|
|
|
|
} else {
|
|
|
|
|
/* overflow ��ȣ: ������ �� �� ���� ó�� */
|
|
|
|
|
linebuf[line_len] = '\0';
|
|
|
|
|
if (!(linebuf[0] == 'x' || linebuf[0] == 'X')) {
|
|
|
|
|
PC_PrintLine_CRLF(linebuf);
|
|
|
|
|
got_any_line = 1;
|
|
|
|
|
}
|
|
|
|
|
line_len = 0;
|
|
|
|
|
linebuf[0] = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* LF ���� = �� �� �ϼ� */
|
|
|
|
|
if (c == '\n') {
|
|
|
|
|
if (!(linebuf[0] == 'x' || linebuf[0] == 'X')) {
|
|
|
|
|
PC_PrintLine_CRLF(linebuf);
|
|
|
|
|
got_any_line = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
line_len = 0;
|
|
|
|
|
linebuf[0] = '\0';
|
|
|
|
|
|
|
|
|
|
/* OFF ����ó�� <end>�� ���� ���� */
|
|
|
|
|
if (g_rs485_bridge_done) {
|
|
|
|
|
g_rs485_bridge_active = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (had_byte) {
|
|
|
|
|
idle_us = 0;
|
|
|
|
|
} else if (got_any_line) {
|
|
|
|
|
idle_us += 50U;
|
|
|
|
|
if (idle_us >= BRIDGE_IDLE_DONE_US) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delay_us(50);
|
|
|
|
|
total_us -= 50U;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ���� partial line�� ������ ���������� ���� */
|
|
|
|
|
if (line_len > 0) {
|
|
|
|
|
linebuf[line_len] = '\0';
|
|
|
|
|
if (!(linebuf[0] == 'x' || linebuf[0] == 'X')) {
|
|
|
|
|
PC_PrintLine_CRLF(linebuf);
|
|
|
|
|
got_any_line = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!got_any_line) {
|
|
|
|
|
OUT_PRINT(CMD_SRC_PC, "Err:rs485_no_response\r\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_rs485_bridge_active = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int execute_owi_service_from_line(CmdSource src, const char *line)
|
|
|
|
|
{
|
|
|
|
|
uint8_t addr = 0, ch = 0;
|
|
|
|
|
char mode = 0;
|
|
|
|
|
uint8_t hash_on = 0, anaout_on = 0, check_on = 1;
|
|
|
|
|
int payload_pos = 0;
|
|
|
|
|
int len;
|
|
|
|
|
|
|
|
|
|
ProtocolType proto;
|
|
|
|
|
uint8_t id = 0;
|
|
|
|
|
unsigned int byte_len = 0;
|
|
|
|
|
int pos;
|
|
|
|
|
uint8_t cmd[CMD_MAX];
|
|
|
|
|
unsigned int k;
|
|
|
|
|
app_owi_result_t r;
|
|
|
|
|
|
|
|
|
|
if (!line) return 0;
|
|
|
|
|
|
|
|
|
|
len = (int)strlen(line);
|
|
|
|
|
|
|
|
|
|
/* x-prefix �Ľ� */
|
|
|
|
|
if (parse_x_prefix(line, len,
|
|
|
|
|
&addr, &ch, &mode,
|
|
|
|
|
&hash_on, &anaout_on, &check_on,
|
|
|
|
|
&payload_pos) != 1) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* �ڱ� �ּҰ� �ƴϸ� ���� ���η� �ѱ� */
|
|
|
|
|
if (addr != g_fixed_addr) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ch < 1 || ch > 20) {
|
|
|
|
|
OUT_PRINT(src, "Err:ch_range\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* prefix ���� ����: ���� process_one_line_now()�� �����ϰ� ���� */
|
|
|
|
|
if (mode == 'C') {
|
|
|
|
|
s_prefix_mode = PREFIX_CAL;
|
|
|
|
|
Cal_Init();
|
|
|
|
|
Gate_SetByNum(ch, hash_on, anaout_on, check_on);
|
|
|
|
|
GateCtrl_SelectChannel(ch);
|
|
|
|
|
} else {
|
|
|
|
|
s_prefix_mode = PREFIX_EOL;
|
|
|
|
|
Eol_Init();
|
|
|
|
|
Gate_SetByNum(ch, hash_on, anaout_on, check_on);
|
|
|
|
|
GateCtrl_SelectChannel(ch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (payload_pos >= len) {
|
|
|
|
|
if (mode == 'E') {
|
|
|
|
|
OUT_PRINT(src, "<ACK>XE51\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
} else {
|
|
|
|
|
OUT_PRINT(src, "Err:CAL_need_payload\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pos = payload_pos;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
char h0, h1;
|
|
|
|
|
|
|
|
|
|
h0 = (char)toupper((unsigned char)line[pos]);
|
|
|
|
|
h1 = (char)toupper((unsigned char)line[pos + 1]);
|
|
|
|
|
|
|
|
|
|
proto = detect_protocol(h0, h1);
|
|
|
|
|
if (proto != PROTOCOL_OWIW && proto != PROTOCOL_OWIR) {
|
|
|
|
|
return 0; /* I2C ���� ���� ���� fallback */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pos += 2;
|
|
|
|
|
|
|
|
|
|
if ((line[pos] == 't' || line[pos] == 'T') && proto == PROTOCOL_OWIW) {
|
|
|
|
|
proto = PROTOCOL_OWIT;
|
|
|
|
|
pos++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (line[pos] == '_' || line[pos] == ':') {
|
|
|
|
|
pos++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pos + 1 >= len) {
|
|
|
|
|
OUT_PRINT(src, "Err:id_short\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
id = hex2byte(line[pos], line[pos + 1]);
|
|
|
|
|
pos += 2;
|
|
|
|
|
|
|
|
|
|
if (pos + 2 >= len ||
|
|
|
|
|
!(line[pos] >= '0' && line[pos] <= '9') ||
|
|
|
|
|
!(line[pos+1] >= '0' && line[pos+1] <= '9') ||
|
|
|
|
|
!(line[pos+2] >= '0' && line[pos+2] <= '9')) {
|
|
|
|
|
OUT_PRINT(src, "Err:len_dec\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte_len = (unsigned int)(100 * (line[pos] - '0') +
|
|
|
|
|
10 * (line[pos+1] - '0') +
|
|
|
|
|
(line[pos+2] - '0'));
|
|
|
|
|
pos += 3;
|
|
|
|
|
|
|
|
|
|
if (byte_len > CMD_MAX) {
|
|
|
|
|
OUT_PRINT(src, "Err:len_range\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (proto == PROTOCOL_OWIT || proto == PROTOCOL_OWIW) {
|
|
|
|
|
if (byte_len == 0) {
|
|
|
|
|
OUT_PRINT(src, "Err:payload0\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((int)(pos + (int)byte_len * 2) > len) {
|
|
|
|
|
OUT_PRINT(src, "Err:len_mismatch\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (k = 0; k < byte_len; k++) {
|
|
|
|
|
cmd[k] = hex2byte(line[pos + (int)(2 * k)],
|
|
|
|
|
line[pos + (int)(2 * k + 1)]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (proto == PROTOCOL_OWIT) {
|
|
|
|
|
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(src, &r);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (proto == PROTOCOL_OWIR) {
|
|
|
|
|
if (byte_len == 0) {
|
|
|
|
|
OUT_PRINT(src, "Err:read_len_nonzero\r\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r = app_owi_read_basic(id, (int)byte_len);
|
|
|
|
|
print_owi_read_result(src, &r);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void process_cmd(ProtocolType protocol, uint8_t id,
|
|
|
|
|
const unsigned char *data, unsigned int len)
|
|
|
|
|
{
|
|
|
|
|
switch (protocol) {
|
|
|
|
|
case PROTOCOL_I2CT: I2C_T_Command_Mode_receiveData(data, (uint8_t)len, id); break;
|
|
|
|
|
case PROTOCOL_OWIT: OWI_T_CommandMode(data, (uint8_t)len, id); break;
|
|
|
|
|
case PROTOCOL_I2CW: I2C_Command_Mode_receiveData(data, (uint8_t)len, id); break;
|
|
|
|
|
case PROTOCOL_I2CR: I2C_Command_Mode_Send((uint8_t)len, id); break;
|
|
|
|
|
case PROTOCOL_OWIW: OWI_CommandMode(data, (uint8_t)len, id); break;
|
|
|
|
|
case PROTOCOL_OWIR: OWI_ReadBytesAndPrint(len, id); break;
|
|
|
|
|
default: cmd_unknown(data, len); break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void process_cmd_by_prefix(PrefixMode pm,
|
|
|
|
|
ProtocolType protocol, uint8_t id,
|
|
|
|
|
const unsigned char *data, unsigned int len)
|
|
|
|
|
{
|
|
|
|
|
(void)pm;
|
|
|
|
|
process_cmd(protocol, id, data, len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
|
|
|
* Main line processor
|
|
|
|
|
* ========================= */
|
|
|
|
|
static void process_one_line_now(CmdSource src, const char *input_line)
|
|
|
|
|
{
|
|
|
|
|
char line[UART_RX_BUF_SIZE];
|
|
|
|
|
|
|
|
|
|
uint8_t v_addr = 0;
|
|
|
|
|
int is_v = 0;
|
|
|
|
|
uint8_t a = 0;
|
|
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
int idx = 0;
|
|
|
|
|
int pos = 2;
|
|
|
|
|
|
|
|
|
|
ProtocolType proto;
|
|
|
|
|
uint8_t id;
|
|
|
|
|
unsigned int byte_len;
|
|
|
|
|
uint8_t cmd[CMD_MAX];
|
|
|
|
|
unsigned int k = 0;
|
|
|
|
|
|
|
|
|
|
char orig_line[UART_RX_BUF_SIZE];
|
|
|
|
|
int orig_len = 0;
|
|
|
|
|
|
|
|
|
|
s_prefix_mode = PREFIX_NONE;
|
|
|
|
|
|
|
|
|
|
if (!input_line) return;
|
|
|
|
|
|
|
|
|
|
strncpy(line, input_line, sizeof(line) - 1);
|
|
|
|
|
line[sizeof(line) - 1] = '\0';
|
|
|
|
|
idx = (int)strlen(line);
|
|
|
|
|
if (idx <= 0) return;
|
|
|
|
|
|
|
|
|
|
if (src == CMD_SRC_RS485) {
|
|
|
|
|
if (!(line[0] == 'x' || line[0] == 'X')) return; // V/N/Err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
|
|
|
* 1) xNNv (x-prefix )
|
|
|
|
|
* ========================= */
|
|
|
|
|
is_v = parse_x_v_cmd(line, idx, &v_addr);
|
|
|
|
|
if (is_v) {
|
|
|
|
|
|
|
|
|
|
if (v_addr > 31) { OUT_PRINT(src, "Err:addr_range\r\n"); return; }
|
|
|
|
|
|
|
|
|
|
/* 0(addr=0) + PC x00v => 00~31 */
|
|
|
|
|
if (g_fixed_addr == 0 && src == CMD_SRC_PC && v_addr == 0) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
send_v_response(CMD_SRC_PC, 0);
|
|
|
|
|
|
|
|
|
|
/* 01~31 */
|
|
|
|
|
for (a = 1; a <= 31; a++) {
|
|
|
|
|
scan_one_addr_rs485(a);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (v_addr == g_fixed_addr) {
|
|
|
|
|
send_v_response(src, g_fixed_addr);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
|
|
|
* 1.5) xNNo(OFF)
|
|
|
|
|
* ========================= */
|
|
|
|
|
{
|
|
|
|
|
uint8_t off_addr = 0;
|
|
|
|
|
|
|
|
|
|
if (parse_x_o_cmd(line, idx, &off_addr)) {
|
|
|
|
|
|
|
|
|
|
if (off_addr > 31) {
|
|
|
|
|
OUT_PRINT(src, "Err:addr_range\r\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* �ڱ� �ּҸ� ���� OFF ó�� */
|
|
|
|
|
if (off_addr == g_fixed_addr) {
|
|
|
|
|
Cal_Init();
|
|
|
|
|
OUT_PRINT(src, "<ACK>OFF\r\n");
|
|
|
|
|
send_end_response(src);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ������(addr 0)�� PC���� ���� ���� OFF��
|
|
|
|
|
���� RS485 ������ �Լ��� ���� */
|
|
|
|
|
if (g_fixed_addr == 0 && src == CMD_SRC_PC) {
|
|
|
|
|
forward_line_rs485_and_bridge(line);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* RS485 */
|
|
|
|
|
orig_len = idx;
|
|
|
|
|
memcpy(orig_line, line, (size_t)orig_len);
|
|
|
|
|
orig_line[orig_len] = '\0';
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
|
|
|
* 2) x-prefix
|
|
|
|
|
* ========================= */
|
|
|
|
|
{
|
|
|
|
|
uint8_t addr = 0;
|
|
|
|
|
uint8_t ch = 0;
|
|
|
|
|
char mode = 0;
|
|
|
|
|
int payload_pos = 0;
|
|
|
|
|
|
|
|
|
|
uint8_t hash_on = 0;
|
|
|
|
|
uint8_t anaout_on = 0;
|
|
|
|
|
uint8_t check_on = 1;
|
|
|
|
|
|
|
|
|
|
uint32_t total_us = BRIDGE_TOTAL_WAIT_US;
|
|
|
|
|
uint32_t idle_us = 0;
|
|
|
|
|
uint16_t last_seq = g_rs485_bridge_seq;
|
|
|
|
|
uint8_t got_any = 0;
|
|
|
|
|
|
|
|
|
|
int r = parse_x_prefix(line, idx, &addr, &ch, &mode, &hash_on, &anaout_on, &check_on, &payload_pos);
|
|
|
|
|
|
|
|
|
|
if (r == -1) {
|
|
|
|
|
OUT_PRINT(src, "Err:X_prefix\r\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (r == 1) {
|
|
|
|
|
if (addr > 31) { OUT_PRINT(src, "Err:addr_range\r\n"); return; }
|
|
|
|
|
if (ch < 1 || ch > 20) { OUT_PRINT(src, "Err:ch_range\r\n"); return; }
|
|
|
|
|
|
|
|
|
|
/* addr mismatch */
|
|
|
|
|
if (addr != g_fixed_addr)
|
|
|
|
|
{
|
|
|
|
|
/* 0�� ����(PC ���� ������)�� �״��� RS485�� ������ */
|
|
|
|
|
if (g_fixed_addr == 0 && src == CMD_SRC_PC)
|
|
|
|
|
{
|
|
|
|
|
forward_line_rs485_and_bridge(orig_line);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return; /* addr mismatch */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* addr == g_fixed_addr */
|
|
|
|
|
if (mode == 'C') {
|
|
|
|
|
s_prefix_mode = PREFIX_CAL;
|
|
|
|
|
Cal_Init();
|
|
|
|
|
Gate_SetByNum(ch, hash_on, anaout_on, check_on);
|
|
|
|
|
GateCtrl_SelectChannel(ch);
|
|
|
|
|
} else {
|
|
|
|
|
s_prefix_mode = PREFIX_EOL;
|
|
|
|
|
Eol_Init();
|
|
|
|
|
Gate_SetByNum(ch, hash_on, anaout_on, check_on);
|
|
|
|
|
GateCtrl_SelectChannel(ch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* prefix */
|
|
|
|
|
{
|
|
|
|
|
int rem = idx - payload_pos;
|
|
|
|
|
|
|
|
|
|
if (rem <= 0) {
|
|
|
|
|
if (mode == 'E') {
|
|
|
|
|
OUT_PRINT(src, "<ACK>XE51\r\n");
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
OUT_PRINT(src, "Err:CAL_need_payload\r\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mode == 'E') {
|
|
|
|
|
OUT_PRINT(src, "Err:EOL_no_payload\r\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < rem; i++) line[i] = line[payload_pos + i];
|
|
|
|
|
line[rem] = '\0';
|
|
|
|
|
idx = rem;
|
|
|
|
|
pos = 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (idx < 7) { OUT_PRINT(src, "Err:short\r\n"); return; }
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
char h0 = (char)toupper((unsigned char)line[0]);
|
|
|
|
|
char h1 = (char)toupper((unsigned char)line[1]);
|
|
|
|
|
proto = detect_protocol(h0, h1);
|
|
|
|
|
}
|
|
|
|
|
if (proto == PROTOCOL_UNKNOWN) { OUT_PRINT(src, "Err:ID\r\n"); return; }
|
|
|
|
|
|
|
|
|
|
if (line[pos] == 't' || line[pos] == 'T') {
|
|
|
|
|
if (proto == PROTOCOL_OWIW) proto = PROTOCOL_OWIT;
|
|
|
|
|
else if (proto == PROTOCOL_I2CW) proto = PROTOCOL_I2CT;
|
|
|
|
|
pos++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (line[pos] == '_' || line[pos] == ':') pos++;
|
|
|
|
|
|
|
|
|
|
if (pos + 1 >= idx) { OUT_PRINT(src, "Err:id_short\r\n"); return; }
|
|
|
|
|
id = hex2byte(line[pos], line[pos + 1]);
|
|
|
|
|
pos += 2;
|
|
|
|
|
|
|
|
|
|
if (pos + 2 >= idx ||
|
|
|
|
|
!(line[pos] >= '0' && line[pos] <= '9') ||
|
|
|
|
|
!(line[pos+1] >= '0' && line[pos+1] <= '9') ||
|
|
|
|
|
!(line[pos+2] >= '0' && line[pos+2] <= '9')) {
|
|
|
|
|
OUT_PRINT(src, "Err:len_dec\r\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte_len = (unsigned int)(100*(line[pos]-'0') + 10*(line[pos+1]-'0') + (line[pos+2]-'0'));
|
|
|
|
|
pos += 3;
|
|
|
|
|
|
|
|
|
|
if (byte_len > CMD_MAX) { OUT_PRINT(src, "Err:len_range\r\n"); return; }
|
|
|
|
|
|
|
|
|
|
if (proto == PROTOCOL_OWIT || proto == PROTOCOL_I2CT ||
|
|
|
|
|
proto == PROTOCOL_OWIW || proto == PROTOCOL_I2CW)
|
|
|
|
|
{
|
|
|
|
|
if (byte_len == 0) { OUT_PRINT(src, "Err:payload0\r\n"); return; }
|
|
|
|
|
|
|
|
|
|
if ((int)(pos + (int)byte_len*2) > idx) { OUT_PRINT(src, "Err:len_mismatch\r\n"); return; }
|
|
|
|
|
|
|
|
|
|
for (k = 0; k < byte_len; k++) {
|
|
|
|
|
cmd[k] = hex2byte(line[pos + 2*k], line[pos + 2*k + 1]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pos += (int)byte_len * 2;
|
|
|
|
|
|
|
|
|
|
if (pos != idx) { OUT_PRINT(src, "Err:len_trail\r\n"); return; }
|
|
|
|
|
}
|
|
|
|
|
else if (proto == PROTOCOL_OWIR || proto == PROTOCOL_I2CR)
|
|
|
|
|
{
|
|
|
|
|
if (byte_len == 0) { OUT_PRINT(src, "Err:read_len_nonzero\r\n"); return; }
|
|
|
|
|
if (pos != idx) { OUT_PRINT(src, "Err:read_no_payload\r\n"); return; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
process_cmd_by_prefix(s_prefix_mode, proto, id, cmd, byte_len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void process_one_line(CmdSource src, const volatile uint8_t *rx_buf, uint16_t rx_len)
|
|
|
|
|
{
|
|
|
|
|
char line[UART_RX_BUF_SIZE];
|
|
|
|
|
int idx;
|
|
|
|
|
app_job_t job;
|
|
|
|
|
app_cmd_src_t app_src;
|
|
|
|
|
|
|
|
|
|
idx = build_line_from_rx(rx_buf, (int)rx_len, line, (int)sizeof(line));
|
|
|
|
|
if (idx <= 0) return;
|
|
|
|
|
|
|
|
|
|
/* RS485 xNNv�� ť�� Ÿ�� ���� ���� ���� */
|
|
|
|
|
if (src == CMD_SRC_RS485) {
|
|
|
|
|
uint8_t vaddr = 0;
|
|
|
|
|
|
|
|
|
|
if (parse_x_v_cmd(line, idx, &vaddr)) {
|
|
|
|
|
if (vaddr == g_fixed_addr) {
|
|
|
|
|
send_v_response(CMD_SRC_RS485, g_fixed_addr);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (src == CMD_SRC_RS485) {
|
|
|
|
|
if (!(line[0] == 'x' || line[0] == 'X')) return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
app_src = (src == CMD_SRC_PC) ? APP_CMD_SRC_PC : APP_CMD_SRC_RS485;
|
|
|
|
|
|
|
|
|
|
if (!app_cmd_parse_line(app_src, line, &job)) {
|
|
|
|
|
OUT_PRINT(src, "Err:parse\r\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!app_scheduler_push(&job)) {
|
|
|
|
|
OUT_PRINT(src, "Err:queue_full\r\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void app_runtime_reset(void)
|
|
|
|
|
{
|
|
|
|
|
memset(&g_app_runtime_job, 0, sizeof(g_app_runtime_job));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void app_runtime_try_start(void)
|
|
|
|
|
{
|
|
|
|
|
if (g_app_runtime_job.active) return;
|
|
|
|
|
|
|
|
|
|
if (app_scheduler_pop(&g_app_runtime_job.job)) {
|
|
|
|
|
g_app_runtime_job.active = 1;
|
|
|
|
|
g_app_runtime_job.scan_started = 0;
|
|
|
|
|
g_app_runtime_job.current_scan_addr = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void app_job_tick(void)
|
|
|
|
|
{
|
|
|
|
|
CmdSource src;
|
|
|
|
|
uint8_t scan_addr;
|
|
|
|
|
|
|
|
|
|
app_runtime_try_start();
|
|
|
|
|
if (!g_app_runtime_job.active) return;
|
|
|
|
|
|
|
|
|
|
src = (g_app_runtime_job.job.src == APP_CMD_SRC_PC) ? CMD_SRC_PC : CMD_SRC_RS485;
|
|
|
|
|
|
|
|
|
|
switch (g_app_runtime_job.job.type) {
|
|
|
|
|
case APP_JOB_SCAN_ADDR:
|
|
|
|
|
scan_addr = g_app_runtime_job.job.addr;
|
|
|
|
|
|
|
|
|
|
if (scan_addr > 31) {
|
|
|
|
|
OUT_PRINT(src, "Err:addr_range\r\n");
|
|
|
|
|
app_runtime_reset();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ������ x00v */
|
|
|
|
|
if (g_fixed_addr == 0 && src == CMD_SRC_PC && scan_addr == 0) {
|
|
|
|
|
if (!g_app_runtime_job.scan_started) {
|
|
|
|
|
send_v_response(CMD_SRC_PC, 0);
|
|
|
|
|
g_app_runtime_job.scan_started = 1;
|
|
|
|
|
g_app_runtime_job.current_scan_addr = 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (g_app_runtime_job.current_scan_addr <= 31) {
|
|
|
|
|
scan_one_addr_rs485(g_app_runtime_job.current_scan_addr);
|
|
|
|
|
g_app_runtime_job.current_scan_addr++;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
app_runtime_reset();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* �����̺� xNNv ���� ó�� */
|
|
|
|
|
if (scan_addr == g_fixed_addr) {
|
|
|
|
|
send_v_response(src, g_fixed_addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
app_runtime_reset();
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case APP_JOB_PROTO_OW:
|
|
|
|
|
case APP_JOB_PROTO_OR:
|
|
|
|
|
/* �ڱ� �ּҸ� ���� */
|
|
|
|
|
if (g_app_runtime_job.job.addr == g_fixed_addr) {
|
|
|
|
|
if (!execute_owi_service_from_job(src, &g_app_runtime_job.job)) {
|
|
|
|
|
OUT_PRINT(src, "Err:job_exec\r\n");
|
|
|
|
|
}
|
|
|
|
|
app_runtime_reset();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* �����Ͱ� PC ������ ���� ������ forwarding */
|
|
|
|
|
if (g_fixed_addr == 0 && src == CMD_SRC_PC && g_app_runtime_job.job.addr != 0) {
|
|
|
|
|
forward_line_rs485_and_bridge(g_app_runtime_job.job.line);
|
|
|
|
|
app_runtime_reset();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* �����̺갡 RS485���� ���� ������ ������ ���� */
|
|
|
|
|
if (src == CMD_SRC_RS485) {
|
|
|
|
|
app_runtime_reset();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OUT_PRINT(src, "Err:job_exec\r\n");
|
|
|
|
|
app_runtime_reset();
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case APP_JOB_FORWARD_LINE:
|
|
|
|
|
case APP_JOB_LOCAL_EXEC:
|
|
|
|
|
default:
|
|
|
|
|
process_one_line_now(src, g_app_runtime_job.job.line);
|
|
|
|
|
app_runtime_reset();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
|
|
|
* Main loop handler
|
|
|
|
|
* ========================= */
|
|
|
|
|
void handle_uart_command_line(void)
|
|
|
|
|
{
|
|
|
|
|
while (1)
|
|
|
|
|
{
|
|
|
|
|
if (g_rs485_need_recover) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
g_rs485_bridge_active = 0;
|
|
|
|
|
g_rs485_bridge_done = 0;
|
|
|
|
|
RS485_Bridge_ResetFifo(); // static? ?
|
|
|
|
|
|
|
|
|
|
/* RS485 RX */
|
|
|
|
|
rs485_rx_done = 0;
|
|
|
|
|
rs485_rx_index = 0;
|
|
|
|
|
rs485_rx_length = 0;
|
|
|
|
|
|
|
|
|
|
/* UART0 stop/start + RX arm */
|
|
|
|
|
rs485_recover();
|
|
|
|
|
g_rs485_need_recover = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (g_rs485_bridge_active) {
|
|
|
|
|
RS485_Bridge_DrainToPC();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* PC(UART1) */
|
|
|
|
|
if (uart_rx_done)
|
|
|
|
|
{
|
|
|
|
|
uart_rx_done = 0;
|
|
|
|
|
|
|
|
|
|
process_one_line(CMD_SRC_PC, uart_rx_buffer, uart_rx_length);
|
|
|
|
|
|
|
|
|
|
uart_rx_index = 0;
|
|
|
|
|
uart_rx_length = 0;
|
|
|
|
|
R_UART1_Receive((uint8_t *)&uart_rx_buffer[uart_rx_index], 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* RS485(UART0) */
|
|
|
|
|
if (rs485_rx_done)
|
|
|
|
|
{
|
|
|
|
|
rs485_rx_done = 0;
|
|
|
|
|
|
|
|
|
|
if (!g_rs485_bridge_active) {
|
|
|
|
|
process_one_line(CMD_SRC_RS485, rs485_rx_buffer, rs485_rx_length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rs485_rx_index = 0;
|
|
|
|
|
rs485_rx_length = 0;
|
|
|
|
|
R_UART0_Receive((uint8_t *)&rs485_rx_buffer[rs485_rx_index], 1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
app_job_tick();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =========================
|
|
|
|
|
* Renesas entrypoints
|
|
|
|
|
* ========================= */
|
|
|
|
|
void R_MAIN_UserInit(void);
|
|
|
|
|
|
|
|
|
|
void main(void)
|
|
|
|
|
{
|
|
|
|
|
char b[64];
|
|
|
|
|
|
|
|
|
|
R_MAIN_UserInit();
|
|
|
|
|
|
|
|
|
|
R_UART0_Create(); /* UART0 : RS485 */
|
|
|
|
|
R_UART1_Create(); /* UART1 : PC */
|
|
|
|
|
|
|
|
|
|
R_IICA0_Create(); /* I2C */
|
|
|
|
|
|
|
|
|
|
R_UART0_Start();
|
|
|
|
|
R_UART1_Start();
|
|
|
|
|
|
|
|
|
|
app_scheduler_init();
|
|
|
|
|
app_runtime_reset();
|
|
|
|
|
|
|
|
|
|
sprintf(b, "BOOT addr=%u\r\n", g_fixed_addr);
|
|
|
|
|
|
|
|
|
|
/* ? BOOT �� */
|
|
|
|
|
UART1_SendString_Safe(b);
|
|
|
|
|
RS485_PRINT(b);
|
|
|
|
|
|
|
|
|
|
R_UART1_Receive((uint8_t *)&uart_rx_buffer[uart_rx_index], 1);
|
|
|
|
|
R_UART0_Receive((uint8_t *)&rs485_rx_buffer[rs485_rx_index], 1);
|
|
|
|
|
|
|
|
|
|
handle_uart_command_line();
|
|
|
|
|
|
|
|
|
|
while (1U) { ; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void R_MAIN_UserInit(void)
|
|
|
|
|
{
|
|
|
|
|
/* Start user code. Do not edit comment generated here */
|
|
|
|
|
EI();
|
|
|
|
|
R_PORT_Create();
|
|
|
|
|
|
|
|
|
|
rs485_init();
|
|
|
|
|
|
|
|
|
|
DipSwitch_Init();
|
|
|
|
|
g_fixed_addr = DipSwitch_ReadAddr_0to31();
|
|
|
|
|
/* End user code. Do not edit comment generated here */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* End user code. Do not edit comment generated here */
|