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.

1105 lines
32 KiB

3 months ago
/***********************************************************************************************************************
3 months ago
* 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.
3 months ago
***********************************************************************************************************************/
/***********************************************************************************************************************
* 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
***********************************************************************************************************************/
3 months ago
/***********************************************************************************************************************
Includes
***********************************************************************************************************************/
3 months ago
#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>
/* End user code. Do not edit comment generated here */
#include "r_cg_userdefine.h"
3 months ago
/* Start user code for adding. Do not edit comment generated here */
3 months ago
/* =========================
* Config
* ========================= */
#define CMD_MAX 529
2 months ago
#define UART_RX_BUF_SIZE 1024
3 months ago
#define RS485_BRIDGE_FIFO_SZ 2048
#define BRIDGE_IDLE_DONE_US 5000U // ������ ����Ʈ ���� 3ms �����ϸ� ������ �Ǵ�
#define BRIDGE_TOTAL_WAIT_US 600000U
3 months ago
/* =========================
* UART RX Buffers
* ========================= */
2 months ago
volatile uint8_t uart_rx_done = 0;
volatile uint16_t uart_rx_index = 0; // �� uint8_t -> uint16_t
3 months ago
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;
3 months ago
volatile uint8_t rs485_rx_buffer[UART_RX_BUF_SIZE] = {0};
volatile uint16_t rs485_rx_length = 0;
3 months ago
volatile uint32_t g_uart0_err_fef = 0;
volatile uint32_t g_uart0_err_ovf = 0;
volatile uint32_t g_uart0_err_pef = 0;
3 months ago
/* RS485 bridge flags */
volatile uint8_t g_rs485_bridge_active = 0;
volatile uint8_t g_rs485_bridge_done = 0;
3 months ago
volatile uint16_t g_rs485_bridge_seq = 0;
static volatile uint8_t s_end_st = 0;
static const char s_end_pat[] = "<end>";
3 months ago
/* (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 ���� ī��Ʈ */
3 months ago
extern volatile uint8_t g_uart0_tx_done;
3 months ago
/* =========================
* RS485 Bridge FIFO
* ========================= */
static volatile uint8_t s_rb_fifo[RS485_BRIDGE_FIFO_SZ];
3 months ago
static volatile uint16_t s_rb_head = 0;
static volatile uint16_t s_rb_tail = 0;
3 months ago
void RS485_Bridge_Push(uint8_t b)
{
3 months ago
uint16_t next = (uint16_t)(s_rb_head + 1);
3 months ago
if (next >= RS485_BRIDGE_FIFO_SZ) next = 0;
if (next == s_rb_tail) {
3 months ago
uint16_t t = (uint16_t)(s_rb_tail + 1);
3 months ago
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;
3 months ago
s_end_st = 0;
g_rs485_bridge_done = 0;
3 months ago
}
3 months ago
static int RS485_Bridge_ReadLine(char *out, int out_sz, uint32_t timeout_us)
{
int n = 0;
while (timeout_us--) {
// FIFO�� �����Ͱ� ������ 1����Ʈ�� ������ line ����
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;
// line ��: "V02\n" �Ǵ� "V02\r\n" (CR�� ������ ���ŵ�)
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);
}
3 months ago
/* =========================
* ? PC(UART1) Safe TX (߿)
* -
* - ׻ ۷ R_UART1_Send
* ========================= */
static uint8_t g_uart1_txbuf[1024];
3 months ago
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;
2 months ago
UART1_WaitTxIdle(); // ? ������ �� ����
3 months ago
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);
2 months ago
UART1_WaitTxIdle(); // ? �� �߰�: ������ �� �ڿ��� ���� (���� ����� ����)
3 months ago
}
/* =========================
* RS485 Bridge Drain -> PC
* - uart1_send_string(out) 1Ʈ ڿ ۽
* - UART1_SendBytes_Safe Ʈ̶ "�����ϰ�"
* ========================= */
static void RS485_Bridge_DrainToPC(void)
{
uint16_t n = 0;
/* UART1�� TX���̸� ���� �������� */
if (g_uart1_tx_count != 0U) return;
/* FIFO -> �ӽ� ���ۿ� �ִ� 64����Ʈ���� ���Ƽ� �� ���� ���� */
while (s_rb_tail != s_rb_head && n < 1024U) {
3 months ago
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;
/* =========================
* 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;
}
3 months ago
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;
// PC�� �ٷ� ����(���۸��� ����ó�� ���Ƽ� ������ OK)
// ���⼭�� �ܼ�ȭ�� ���� 1����Ʈ�� �������� ���� ���� 256���Ƽ� ������ �Լ� ���� ����
// ���� ��Ī
if (c == pat[st]) {
st++;
if (pat[st] == 0) return 1; // found
} else {
st = (c == pat[0]) ? 1 : 0;
}
}
delay_us(1);
}
return 0;
}
3 months ago
/* =========================
* Print routing
* ========================= */
typedef enum {
CMD_SRC_PC = 0,
CMD_SRC_RS485 = 1
} CmdSource;
/* ? PC ������ ������ Safe�� */
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(void)
{
OUT_PRINT(CMD_SRC_PC, "<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);
}
2 months ago
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;
}
3 months ago
/* ? ���⼭�� 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) {
3 months ago
delay_us(600); // 200~500us ���� (ȯ�� ���� ����)
3 months ago
}
OUT_PRINT(src, resp);
}
3 months ago
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)
{
// ��ĵ ���� ����, ������ �ִ� CR/LF/����� PC�� ���� FIFO�� ����
while (loops--) {
RS485_Bridge_DrainToPC();
delay_us(step_us);
}
}
static void PC_PrintLine_CRLF(const char *line)
{
char tmp[40];
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");
}
}
3 months ago
/* =========================
* RS485 scan: xNNv\r\n
* ========================= */
2 months ago
/* =========================
* RS485 scan: xNNv\r\n (pattern-based, no line needed)
* ========================= */
3 months ago
static void scan_one_addr_rs485(uint8_t addr)
{
char cmdline[8];
2 months ago
uint8_t try;
3 months ago
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';
2 months ago
/* ? try Ƚ�� ���̱�: �ӵ� �ٽ� */
2 months ago
for (try = 0; try < 3; try++)
{
3 months ago
{
2 months ago
/* --- bridge �غ� --- */
3 months ago
g_rs485_bridge_active = 1;
g_rs485_bridge_done = 0;
RS485_Bridge_ResetFifo();
3 months ago
2 months ago
/* RX arm (�긴�� ������ �׻� buffer[0]�� 1����Ʈ �޴� �������� ��) */
3 months ago
rs485_rx_done = 0;
rs485_rx_index = 0;
rs485_rx_length = 0;
R_UART0_Receive((uint8_t*)&rs485_rx_buffer[0], 1);
3 months ago
2 months ago
/* ---- �۽� ---- */
3 months ago
g_uart0_tx_done = 0;
RS485_PRINT(cmdline);
3 months ago
2 months ago
/* TX �Ϸ� ���� (�ʹ� ���� ���� ����) */
UART0_WaitTxDone_Flag(2500); // 2.5ms ����
rs485_set_tx(0); // Ȥ�� ���� ���� RX
delay_us(80); // turnaround (ȯ�� ���� 50~150us)
3 months ago
2 months ago
/* ---- ���� ���� (ª��) ---- */
3 months ago
{
2 months ago
uint32_t total_wait_us = 2500; // ? 2.5ms�� ���κ� ����
3 months ago
char linebuf[32];
while (total_wait_us > 0) {
2 months ago
/* 0.5ms�� ���� ���� */
int got = RS485_Bridge_ReadLine(linebuf, sizeof(linebuf), 500);
3 months ago
if (got) {
if (Is_V_Response_For(linebuf, addr)) {
2 months ago
PC_PrintLine_CRLF(linebuf);
3 months ago
g_rs485_bridge_active = 0;
2 months ago
return;
3 months ago
}
2 months ago
/* �ٸ� ����(������/����)�� ���� */
3 months ago
}
2 months ago
total_wait_us -= 500;
3 months ago
}
3 months ago
}
3 months ago
g_rs485_bridge_active = 0;
3 months ago
}
2 months ago
// ���� ������ ����/�����̸� ���� �� ���õ�
if (g_rs485_need_recover) {
rs485_recover();
}
delay_us(500);
}
2 months ago
/* ���� �� Nxx */
3 months ago
send_n_response(addr);
2 months ago
/* ������ ���� RX ��arm */
3 months ago
rs485_rx_done = 0;
rs485_rx_index = 0;
3 months ago
rs485_rx_length = 0;
R_UART0_Receive((uint8_t*)&rs485_rx_buffer[0], 1);
}
2 months ago
3 months ago
/* =========================
* 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 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(CmdSource src, const volatile uint8_t *rx_buf, uint16_t rx_len)
{
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;
2 months ago
3 months ago
char msg[64];
3 months ago
s_prefix_mode = PREFIX_NONE;
idx = build_line_from_rx(rx_buf, (int)rx_len, line, (int)sizeof(line));
if (idx <= 0) return;
2 months ago
3 months ago
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; }
2 months ago
/* ����0(addr=0) + PC���� x00v => 00~31 ��ĵ */
3 months ago
if (g_fixed_addr == 0 && src == CMD_SRC_PC && v_addr == 0) {
/* �ڱ� �ڽ�(00) ���� */
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;
}
2 months ago
/* =========================
* 1.5) xNNo ó (OFF) ? : 0 ٸ ּҸ RS485 ߰
* ========================= */
{
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; }
/* 1) �� �ּҸ� ���� OFF */
if (off_addr == g_fixed_addr) {
Cal_Init(); // ����ü OFF(�⺻ ����)��
OUT_PRINT(src, "<ACK>OFF\r\n");
send_end_response(); // GUI�� ��Ƽ�����̸� <end> ����
return;
}
/* 2) ����0(addr=0) + PC���� ������ x01o~ �� RS485�� �긴�� */
if (g_fixed_addr == 0 && src == CMD_SRC_PC) {
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);
/* ---- RS485�� ���� �۽� ---- */
{
static char txbuf[UART_RX_BUF_SIZE + 4];
int n = idx; // 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';
/* UART0 TX busy�� ���� ���� �� �۽� */
{
unsigned long g = 0;
while (g_uart0_tx_count != 0U) {
if (g++ > 3000000UL) break;
}
}
RS485_PRINT(txbuf);
}
/* ---- ���� �巹��: ������ 1���̶��� ���� 3ms idle�̸� ���� ---- */
{
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;
while (total_us >= 50U) {
RS485_Bridge_DrainToPC();
delay_us(50);
total_us -= 50U;
if (g_rs485_bridge_done) break; // <end>�� ����
if (g_rs485_bridge_seq != last_seq) {
last_seq = g_rs485_bridge_seq;
got_any = 1;
idle_us = 0;
} else if (got_any) {
idle_us += 50U;
if (idle_us >= BRIDGE_IDLE_DONE_US) break; // 3ms idle
}
}
RS485_Bridge_DrainToPC();
g_rs485_bridge_active = 0;
if (total_us < 50U) {
2 months ago
rs485_recover();
2 months ago
OUT_PRINT(CMD_SRC_PC, "Err:rs485_timeout\r\n");
sprintf(msg, "Err:rs485_timeout fef=%lu ovf=%lu pef=%lu\r\n",
g_uart0_err_fef, g_uart0_err_ovf, g_uart0_err_pef);
OUT_PRINT(CMD_SRC_PC, msg);
}
}
}
return; // �����̺��� mismatch�� �׳� ����
2 months ago
}
}
3 months ago
/* 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;
2 months ago
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;
3 months ago
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 */
2 months ago
if (addr != g_fixed_addr)
{
/* ����0(addr=0) + PC������ RS485 �߰� */
if (g_fixed_addr == 0 && src == CMD_SRC_PC)
{
uint32_t total_us;
uint32_t idle_us;
uint16_t last_seq;
uint8_t got_any;
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);
/* ---- RS485�� ���� �۽� ---- */
{
static char txbuf[UART_RX_BUF_SIZE + 4];
int n = orig_len;
if (n > (int)sizeof(txbuf) - 3) n = (int)sizeof(txbuf) - 3;
memcpy(txbuf, orig_line, (size_t)n);
txbuf[n++] = '\r';
txbuf[n++] = '\n';
txbuf[n] = '\0';
/* UART0 TX busy�� ���� ���� �� �۽� */
{
unsigned long g = 0;
while (g_uart0_tx_count != 0U) {
if (g++ > 3000000UL) break;
}
}
RS485_PRINT(txbuf);
}
/* ---- ���� �巹�� ---- */
total_us = BRIDGE_TOTAL_WAIT_US;
idle_us = 0;
last_seq = g_rs485_bridge_seq;
got_any = 0;
while (total_us >= 50U) {
RS485_Bridge_DrainToPC();
delay_us(50);
total_us -= 50U;
if (g_rs485_bridge_done) break;
if (g_rs485_bridge_seq != last_seq) {
last_seq = g_rs485_bridge_seq;
got_any = 1;
idle_us = 0;
} else if (got_any) {
idle_us += 50U;
if (idle_us >= BRIDGE_IDLE_DONE_US) break;
}
}
RS485_Bridge_DrainToPC();
g_rs485_bridge_active = 0;
if (total_us < 50U) {
2 months ago
rs485_recover();
2 months ago
OUT_PRINT(CMD_SRC_PC, "Err:rs485_timeout\r\n");
sprintf(msg, "Err:rs485_timeout fef=%lu ovf=%lu pef=%lu\r\n",
g_uart0_err_fef, g_uart0_err_ovf, g_uart0_err_pef);
OUT_PRINT(CMD_SRC_PC, msg);
}
}
return; /* �����̺��� addr mismatch ���� */
}
3 months ago
/* 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�� �� ���� / payload ó�� */
{
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;
}
}
}
/* =========================
* 3) Ϲ Ŀǵ Ľ
* ========================= */
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);
}
2 months ago
3 months ago
/* =========================
* Main loop handler
* ========================= */
void handle_uart_command_line(void)
{
while (1)
{
2 months ago
if (g_rs485_need_recover) {
/* 1) �긴�� ���� ���� */
g_rs485_bridge_active = 0;
g_rs485_bridge_done = 0;
RS485_Bridge_ResetFifo(); // ���� ���� �� static�̶� ȣ�� ����
/* 2) RS485 RX ���� ���� */
rs485_rx_done = 0;
rs485_rx_index = 0;
rs485_rx_length = 0;
/* 3) UART0 stop/start + RX ��arm */
rs485_recover();
g_rs485_need_recover = 0;
}
3 months ago
/* �긴�� ���̸� RS485->PC ���� �巹�� */
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
{
}
}
}
/* =========================
* 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();
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)
{
3 months ago
/* Start user code. Do not edit comment generated here */
3 months ago
EI();
R_PORT_Create();
rs485_init();
DipSwitch_Init();
g_fixed_addr = DipSwitch_ReadAddr_0to31();
3 months ago
/* End user code. Do not edit comment generated here */
3 months ago
}
3 months ago
/* End user code. Do not edit comment generated here */