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.
870 lines
21 KiB
870 lines
21 KiB
#include "owi.h"
|
|
#include "delay.h"
|
|
#include "r_cg_timer.h"
|
|
#include "r_cg_wdt.h"
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include "uart.h"
|
|
#include "r_cg_wdt.h"
|
|
|
|
#ifndef OWI_STRONG_DRIVE_HIGH_US
|
|
#define OWI_STRONG_DRIVE_HIGH_US 5u
|
|
#endif
|
|
|
|
#ifndef OWI_USE_TAU1_CAPTURE
|
|
#define OWI_USE_TAU1_CAPTURE 1u
|
|
#endif
|
|
|
|
/* Renesas CG: count-clock period is half the selected 0.063 us minimum.
|
|
Therefore TI15 capture runs at approximately 32 timer ticks per us. */
|
|
#define OWI_TAU1_TICKS_PER_US 32UL
|
|
#define OWI_CAPTURE_QUEUE_WAIT_US (bit_period_us * 4u)
|
|
#define OWI_CAPTURE_SYNC_BITS 16u
|
|
|
|
/* 내부 상태 */
|
|
static uint32_t bit_period_us = OWI_BIT_PERIOD_US;
|
|
static uint8_t g_owi_timeout_latched = 0;
|
|
#if OWI_USE_TAU1_CAPTURE
|
|
static uint32_t g_owi_capture_threshold_ticks = 0UL;
|
|
static uint8_t g_owi_capture_pending_bits[OWI_CAPTURE_SYNC_BITS];
|
|
static uint8_t g_owi_capture_pending_index = 0U;
|
|
static uint8_t g_owi_capture_pending_count = 0U;
|
|
#endif
|
|
|
|
static uint16_t g_owi_last_timeout_byte_index = 0xFFFFu;
|
|
static uint8_t g_owi_last_timeout_bit_index = 0xFFu;
|
|
|
|
static uint16_t g_owi_current_read_byte_index = 0u;
|
|
static uint8_t g_owi_current_read_bit_index = 0u;
|
|
|
|
/* =========================================================
|
|
* GPIO helpers (P70 / HW Open-Drain)
|
|
* - LOW : 출력 모드 + 0
|
|
* - HIGH : 입력(Hi-Z)로 release
|
|
* ========================================================= */
|
|
void GPIO_Clear(void)
|
|
{
|
|
OWI_PORT_POM |= (uint8_t)OWI_PIN_MASK;
|
|
OWI_PORT_P &= (uint8_t)~OWI_PIN_MASK;
|
|
OWI_PORT_PM &= (uint8_t)~OWI_PIN_MASK;
|
|
}
|
|
|
|
void GPIO_Input(void)
|
|
{
|
|
OWI_PORT_POM |= (uint8_t)OWI_PIN_MASK;
|
|
OWI_PORT_P |= (uint8_t)OWI_PIN_MASK;
|
|
OWI_PORT_PM |= (uint8_t)OWI_PIN_MASK;
|
|
}
|
|
|
|
int GPIO_Read(void)
|
|
{
|
|
return (OWI_PORT_P & (uint8_t)OWI_PIN_MASK) ? 1 : 0;
|
|
}
|
|
|
|
static void OWI_Release(void)
|
|
{
|
|
OWI_PORT_POM |= (uint8_t)OWI_PIN_MASK;
|
|
OWI_PORT_P |= (uint8_t)OWI_PIN_MASK;
|
|
OWI_PORT_PM |= (uint8_t)OWI_PIN_MASK;
|
|
}
|
|
|
|
static void GPIO_StrongDriveHighKick(uint32_t kick_us)
|
|
{
|
|
OWI_Release();
|
|
|
|
if (!GPIO_Read()) {
|
|
return;
|
|
}
|
|
|
|
OWI_PORT_POM &= (uint8_t)~OWI_PIN_MASK;
|
|
OWI_PORT_P |= (uint8_t)OWI_PIN_MASK;
|
|
OWI_PORT_PM &= (uint8_t)~OWI_PIN_MASK;
|
|
|
|
delay_us(kick_us);
|
|
|
|
OWI_PORT_POM |= (uint8_t)OWI_PIN_MASK;
|
|
OWI_Release();
|
|
}
|
|
|
|
void GPIO_ForceHighKick(void)
|
|
{
|
|
GPIO_StrongDriveHighKick(OWI_STRONG_DRIVE_HIGH_US);
|
|
}
|
|
|
|
static void OWI_DriveLow(void)
|
|
{
|
|
OWI_PORT_POM |= (uint8_t)OWI_PIN_MASK;
|
|
OWI_PORT_P &= (uint8_t)~OWI_PIN_MASK;
|
|
OWI_PORT_PM &= (uint8_t)~OWI_PIN_MASK;
|
|
}
|
|
|
|
/* =========================================================
|
|
* Diagnostics
|
|
* ========================================================= */
|
|
uint8_t OWI_HasTimeout(void)
|
|
{
|
|
return g_owi_timeout_latched;
|
|
}
|
|
|
|
void OWI_ClearTimeout(void)
|
|
{
|
|
g_owi_timeout_latched = 0;
|
|
g_owi_last_timeout_byte_index = 0xFFFFu;
|
|
g_owi_last_timeout_bit_index = 0xFFu;
|
|
}
|
|
|
|
uint16_t OWI_GetLastTimeoutByteIndex(void)
|
|
{
|
|
return g_owi_last_timeout_byte_index;
|
|
}
|
|
|
|
uint8_t OWI_GetLastTimeoutBitIndex(void)
|
|
{
|
|
return g_owi_last_timeout_bit_index;
|
|
}
|
|
|
|
/* =========================================================
|
|
* OWI Init
|
|
* ========================================================= */
|
|
void OWI_Init(uint32_t bit_time_us)
|
|
{
|
|
bit_period_us = bit_time_us;
|
|
(void)bit_period_us;
|
|
|
|
/* R_PORT_Create() can overwrite the TI15 setup after system init.
|
|
Re-enable the P70 digital input path before every OWI transaction. */
|
|
PMC7 &= (uint8_t)~OWI_PIN_MASK;
|
|
PIM7 &= (uint8_t)~OWI_PIN_MASK;
|
|
OWI_PORT_POM |= (uint8_t)OWI_PIN_MASK;
|
|
OWI_PORT_PU &= (uint8_t)~OWI_PIN_MASK;
|
|
|
|
OWI_ClearTimeout();
|
|
GPIO_Input();
|
|
}
|
|
|
|
/* =========================================================
|
|
* Start/Stop/Secure
|
|
* ========================================================= */
|
|
void OWI_Start(void)
|
|
{
|
|
GPIO_Clear();
|
|
delay_us(TSTART_HOLD);
|
|
|
|
GPIO_Input();
|
|
delay_us(TBIT);
|
|
}
|
|
|
|
void OWI_Stop(void)
|
|
{
|
|
GPIO_Input();
|
|
delay_us(TSTOP_LOW);
|
|
delay_us(TIDLE);
|
|
}
|
|
|
|
static void OWI_StopWrite(void)
|
|
{
|
|
OWI_Release();
|
|
delay_us(TSTOP_LOW);
|
|
delay_us(TIDLE);
|
|
}
|
|
|
|
static void OWI_StopRead(void)
|
|
{
|
|
OWI_DriveLow();
|
|
delay_us(TSTOP_LOW);
|
|
OWI_Release();
|
|
delay_us(TIDLE);
|
|
}
|
|
|
|
static uint8_t OWI_WaitForFallingEdge(uint16_t byte_index, uint8_t bit_index)
|
|
{
|
|
int timeout = (int)(bit_period_us * 4u);
|
|
|
|
while (GPIO_Read() && timeout-- > 0) {
|
|
delay_us(1u);
|
|
}
|
|
|
|
if (timeout <= 0) {
|
|
if (!g_owi_timeout_latched) {
|
|
g_owi_timeout_latched = 1;
|
|
g_owi_last_timeout_byte_index = byte_index;
|
|
g_owi_last_timeout_bit_index = bit_index;
|
|
}
|
|
return 0u;
|
|
}
|
|
|
|
return 1u;
|
|
}
|
|
|
|
static uint8_t OWI_ReadByte_StreamSynced(uint16_t byte_index)
|
|
{
|
|
uint8_t data = 0;
|
|
int b;
|
|
|
|
for (b = 7; b >= 0; b--) {
|
|
uint8_t bit_index = (uint8_t)(7 - b);
|
|
uint8_t bit;
|
|
|
|
g_owi_current_read_byte_index = byte_index;
|
|
g_owi_current_read_bit_index = bit_index;
|
|
|
|
/* 슬롯 시작 후 중앙 샘플 */
|
|
delay_us(bit_period_us / 2u);
|
|
bit = GPIO_Read() ? 1u : 0u;
|
|
data |= (uint8_t)(bit << b);
|
|
|
|
/* 남은 반 슬롯 대기 */
|
|
delay_us(bit_period_us / 2u);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
#if OWI_USE_TAU1_CAPTURE
|
|
static void OWI_CapturePrepare(void)
|
|
{
|
|
/* P70 remains a normal open-drain GPIO at boot. Configure TI15 only
|
|
immediately before a captured receive transaction. */
|
|
R_TAU1_Create();
|
|
R_TAU1_Channel5_Stop();
|
|
/* Slow RC rising edges on P70 benefit from the TI15 digital noise filter.
|
|
Give capture precedence over UART interrupts while receiving a frame. */
|
|
NFEN2 |= _20_TAU_CH5_NOISE_ON;
|
|
TMPR115 = 0U;
|
|
TMPR015 = 0U;
|
|
GPIO_Input();
|
|
}
|
|
|
|
static void OWI_CaptureBegin(void)
|
|
{
|
|
GPIO_Input();
|
|
g_owi_capture_threshold_ticks = 0UL;
|
|
g_owi_capture_pending_index = 0U;
|
|
g_owi_capture_pending_count = 0U;
|
|
R_TAU1_Channel5_CaptureReset();
|
|
R_TAU1_Channel5_Start();
|
|
}
|
|
|
|
static void OWI_CaptureEnd(void)
|
|
{
|
|
R_TAU1_Channel5_Stop();
|
|
GPIO_Input();
|
|
}
|
|
|
|
static uint8_t OWI_CaptureWaitLowWidth(uint16_t byte_index,
|
|
uint8_t bit_index,
|
|
uint32_t * const low_ticks)
|
|
{
|
|
uint32_t timeout_us = OWI_CAPTURE_QUEUE_WAIT_US;
|
|
|
|
while (timeout_us-- > 0UL)
|
|
{
|
|
if (R_TAU1_Channel5_GetLowWidthTicks(low_ticks))
|
|
{
|
|
return 1U;
|
|
}
|
|
|
|
if (R_TAU1_Channel5_CaptureOverflowed())
|
|
{
|
|
break;
|
|
}
|
|
|
|
/* This delay is only a timeout yield; pulse timing is captured by TAU1. */
|
|
delay_us(1U);
|
|
}
|
|
|
|
if (!g_owi_timeout_latched)
|
|
{
|
|
g_owi_timeout_latched = 1U;
|
|
g_owi_last_timeout_byte_index = byte_index;
|
|
g_owi_last_timeout_bit_index = bit_index;
|
|
}
|
|
|
|
return 0U;
|
|
}
|
|
|
|
static uint32_t OWI_CaptureFindThreshold(const uint32_t *widths,
|
|
uint8_t width_count)
|
|
{
|
|
uint32_t sorted[OWI_CAPTURE_SYNC_BITS];
|
|
uint32_t max_gap = 0UL;
|
|
uint32_t threshold =
|
|
((uint32_t)bit_period_us * OWI_TAU1_TICKS_PER_US) / 2UL;
|
|
uint32_t gap;
|
|
uint32_t temp;
|
|
uint8_t i;
|
|
uint8_t j;
|
|
|
|
for (i = 0U; i < width_count; i++) {
|
|
sorted[i] = widths[i];
|
|
}
|
|
|
|
for (i = 0U; i < (uint8_t)(width_count - 1U); i++) {
|
|
for (j = (uint8_t)(i + 1U); j < width_count; j++) {
|
|
if (sorted[j] < sorted[i]) {
|
|
temp = sorted[i];
|
|
sorted[i] = sorted[j];
|
|
sorted[j] = temp;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* The 0x26 header contains both short and long LOW pulses. The largest
|
|
gap separates the two measured clusters without assuming timer scale. */
|
|
for (i = 0U; i < (uint8_t)(width_count - 1U); i++) {
|
|
gap = sorted[i + 1U] - sorted[i];
|
|
if (gap > max_gap) {
|
|
max_gap = gap;
|
|
threshold = sorted[i] + (gap / 2UL);
|
|
}
|
|
}
|
|
|
|
return threshold;
|
|
}
|
|
|
|
static uint8_t OWI_CaptureExpectedHeaderBit(uint8_t header_bit_index)
|
|
{
|
|
return (uint8_t)((0x26U >> (7U - header_bit_index)) & 0x01U);
|
|
}
|
|
|
|
static uint8_t OWI_CaptureFindHeaderEnd(const uint8_t *bits,
|
|
uint8_t bit_count,
|
|
uint8_t * const header_end)
|
|
{
|
|
uint8_t start;
|
|
uint8_t i;
|
|
uint8_t missed;
|
|
uint8_t matched;
|
|
|
|
if (header_end == 0) {
|
|
return 0U;
|
|
}
|
|
|
|
/* Normal case and recovery from one or more leading noise edges. */
|
|
for (start = 0U; start <= (uint8_t)(bit_count - 8U); start++) {
|
|
matched = 1U;
|
|
for (i = 0U; i < 8U; i++) {
|
|
if (bits[start + i] != OWI_CaptureExpectedHeaderBit(i)) {
|
|
matched = 0U;
|
|
break;
|
|
}
|
|
}
|
|
if (matched) {
|
|
*header_end = (uint8_t)(start + 8U);
|
|
return 1U;
|
|
}
|
|
}
|
|
|
|
/* If capture was armed during the first LOW, recover using the known
|
|
suffix of the 0x26 header. At most two leading bits are reconstructed. */
|
|
for (missed = 1U; missed <= 2U; missed++) {
|
|
matched = 1U;
|
|
for (i = 0U; i < (uint8_t)(8U - missed); i++) {
|
|
if (bits[i] != OWI_CaptureExpectedHeaderBit((uint8_t)(i + missed))) {
|
|
matched = 0U;
|
|
break;
|
|
}
|
|
}
|
|
if (matched) {
|
|
*header_end = (uint8_t)(8U - missed);
|
|
return 1U;
|
|
}
|
|
}
|
|
|
|
return 0U;
|
|
}
|
|
|
|
static uint8_t OWI_CaptureGetDecodedBit(uint16_t byte_index,
|
|
uint8_t bit_index,
|
|
uint8_t * const decoded_bit)
|
|
{
|
|
uint32_t low_ticks;
|
|
|
|
if (decoded_bit == 0) {
|
|
return 0U;
|
|
}
|
|
|
|
if (g_owi_capture_pending_index < g_owi_capture_pending_count) {
|
|
*decoded_bit = g_owi_capture_pending_bits[g_owi_capture_pending_index++];
|
|
return 1U;
|
|
}
|
|
|
|
if (!OWI_CaptureWaitLowWidth(byte_index, bit_index, &low_ticks)) {
|
|
return 0U;
|
|
}
|
|
|
|
*decoded_bit = (low_ticks < g_owi_capture_threshold_ticks) ? 1U : 0U;
|
|
return 1U;
|
|
}
|
|
|
|
static uint8_t OWI_ReadByte_Captured(uint16_t byte_index)
|
|
{
|
|
uint8_t data = 0U;
|
|
int b;
|
|
uint32_t sync_widths[OWI_CAPTURE_SYNC_BITS];
|
|
|
|
if (byte_index == 0U)
|
|
{
|
|
uint8_t sync_bits[OWI_CAPTURE_SYNC_BITS];
|
|
uint8_t header_end;
|
|
uint8_t i;
|
|
|
|
for (i = 0U; i < OWI_CAPTURE_SYNC_BITS; i++)
|
|
{
|
|
g_owi_current_read_byte_index = 0U;
|
|
g_owi_current_read_bit_index = i;
|
|
|
|
if (!OWI_CaptureWaitLowWidth(0U, i, &sync_widths[i]))
|
|
{
|
|
return 0U;
|
|
}
|
|
}
|
|
|
|
g_owi_capture_threshold_ticks =
|
|
OWI_CaptureFindThreshold(sync_widths, OWI_CAPTURE_SYNC_BITS);
|
|
|
|
for (i = 0U; i < OWI_CAPTURE_SYNC_BITS; i++) {
|
|
sync_bits[i] =
|
|
(sync_widths[i] < g_owi_capture_threshold_ticks) ? 1U : 0U;
|
|
}
|
|
|
|
if (!OWI_CaptureFindHeaderEnd(sync_bits,
|
|
OWI_CAPTURE_SYNC_BITS,
|
|
&header_end)) {
|
|
if (!g_owi_timeout_latched) {
|
|
g_owi_timeout_latched = 1U;
|
|
g_owi_last_timeout_byte_index = 0U;
|
|
g_owi_last_timeout_bit_index = 0U;
|
|
}
|
|
return 0U;
|
|
}
|
|
|
|
g_owi_capture_pending_index = 0U;
|
|
g_owi_capture_pending_count =
|
|
(uint8_t)(OWI_CAPTURE_SYNC_BITS - header_end);
|
|
for (i = 0U; i < g_owi_capture_pending_count; i++) {
|
|
g_owi_capture_pending_bits[i] = sync_bits[header_end + i];
|
|
}
|
|
|
|
return 0x26U;
|
|
}
|
|
|
|
for (b = 7; b >= 0; b--)
|
|
{
|
|
uint8_t bit_index = (uint8_t)(7 - b);
|
|
uint8_t bit;
|
|
|
|
g_owi_current_read_byte_index = byte_index;
|
|
g_owi_current_read_bit_index = bit_index;
|
|
|
|
if (!OWI_CaptureGetDecodedBit(byte_index, bit_index, &bit))
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (bit)
|
|
{
|
|
data |= (uint8_t)(1U << b);
|
|
}
|
|
}
|
|
|
|
return data;
|
|
}
|
|
#endif
|
|
|
|
void OWI_SecureStop(void)
|
|
{
|
|
int i;
|
|
|
|
GPIO_Clear();
|
|
delay_us(SECURE_HIGH);
|
|
|
|
for (i = 0; i < (int)SECURE_TOGGLE_COUNT; i++) {
|
|
GPIO_Input();
|
|
delay_us(SECURE_TOGGLE_HIGH);
|
|
|
|
GPIO_Clear();
|
|
delay_us(SECURE_TOGGLE_LOW);
|
|
}
|
|
|
|
GPIO_Input();
|
|
delay_us(SECURE_HIGH);
|
|
|
|
GPIO_Clear();
|
|
delay_us(TSTART_HOLD);
|
|
GPIO_Input();
|
|
}
|
|
|
|
/* =========================================================
|
|
* Bit/Byte IO
|
|
* ========================================================= */
|
|
void OWI_WriteBit(int bit)
|
|
{
|
|
uint32_t t_low = bit ? (uint32_t)TLOW_1 : (uint32_t)TLOW_0;
|
|
uint32_t t_high = (uint32_t)TBIT - t_low;
|
|
|
|
/* HIGH 구간 */
|
|
OWI_Release();
|
|
delay_us(t_high);
|
|
|
|
/* LOW 구간 */
|
|
OWI_DriveLow();
|
|
delay_us(t_low);
|
|
|
|
/* 다음 슬롯 시작 전 반드시 release */
|
|
OWI_Release();
|
|
}
|
|
|
|
void OWI_WriteByte(uint8_t data)
|
|
{
|
|
int i;
|
|
for (i = 7; i >= 0; i--) {
|
|
OWI_WriteBit((data >> i) & 0x01u);
|
|
}
|
|
GPIO_Input();
|
|
}
|
|
|
|
uint8_t OWI_ReadBit(void)
|
|
{
|
|
int timeout;
|
|
int low_width = 0;
|
|
|
|
/* 1) 라인이 HIGH가 될 때까지 정리 */
|
|
timeout = (int)(bit_period_us * 2u);
|
|
while (!GPIO_Read() && timeout-- > 0) {
|
|
delay_us(1u);
|
|
}
|
|
|
|
if (timeout <= 0) {
|
|
if (!g_owi_timeout_latched) {
|
|
g_owi_timeout_latched = 1;
|
|
g_owi_last_timeout_byte_index = g_owi_current_read_byte_index;
|
|
g_owi_last_timeout_bit_index = g_owi_current_read_bit_index;
|
|
}
|
|
return 0u;
|
|
}
|
|
|
|
/* 2) 다음 LOW 시작 대기 */
|
|
timeout = (int)(bit_period_us * 2u);
|
|
while (GPIO_Read() && timeout-- > 0) {
|
|
delay_us(1u);
|
|
}
|
|
|
|
if (timeout <= 0) {
|
|
if (!g_owi_timeout_latched) {
|
|
g_owi_timeout_latched = 1;
|
|
g_owi_last_timeout_byte_index = g_owi_current_read_byte_index;
|
|
g_owi_last_timeout_bit_index = g_owi_current_read_bit_index;
|
|
}
|
|
return 0u;
|
|
}
|
|
|
|
/* 3) LOW가 유지되는 시간을 직접 측정 */
|
|
while (!GPIO_Read() && low_width < (int)(bit_period_us * 2u)) {
|
|
delay_us(1u);
|
|
low_width++;
|
|
}
|
|
|
|
/* 4) LOW 폭 기준으로 판정
|
|
- 짧으면 1
|
|
- 길면 0
|
|
threshold ~= TBIT/2
|
|
*/
|
|
return (low_width < (int)(bit_period_us / 2u)) ? 1u : 0u;
|
|
}
|
|
|
|
uint8_t OWI_ReadByte(void)
|
|
{
|
|
uint8_t data = 0;
|
|
int i;
|
|
|
|
for (i = 7; i >= 0; i--) {
|
|
g_owi_current_read_bit_index = (uint8_t)(7 - i);
|
|
data |= (uint8_t)(OWI_ReadBit() << i);
|
|
if (OWI_HasTimeout()) {
|
|
break;
|
|
}
|
|
}
|
|
return data;
|
|
}
|
|
|
|
/* =========================================================
|
|
* Debug Print
|
|
* ========================================================= */
|
|
void OWI_T_ReadBytesAndPrint(int length)
|
|
{
|
|
uint8_t buf[129];
|
|
int i;
|
|
char uart_buf[8];
|
|
char tmp_buf[8];
|
|
uint8_t va0, va1;
|
|
|
|
if (length > 129) length = 129;
|
|
if (length <= 0) return;
|
|
|
|
OWI_ClearTimeout();
|
|
|
|
for (i = 0; i < length; i++) {
|
|
R_WDT_Restart();
|
|
g_owi_current_read_byte_index = (uint16_t)i;
|
|
buf[i] = OWI_ReadByte();
|
|
if (OWI_HasTimeout()) {
|
|
i++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
sprintf(uart_buf, "%02X ", buf[0]);
|
|
strcpy(tmp_buf, uart_buf);
|
|
HOST_PRINT(tmp_buf);
|
|
|
|
for (i = 1; i < length; i += 2) {
|
|
va0 = buf[i];
|
|
va1 = (uint8_t)((i + 1 < length) ? buf[i + 1] : 0u);
|
|
|
|
delay_us(200);
|
|
sprintf(uart_buf, "%02X%02X ", va0, va1);
|
|
strcpy(tmp_buf, uart_buf);
|
|
HOST_PRINT(tmp_buf);
|
|
delay_us(200);
|
|
}
|
|
}
|
|
|
|
/* =========================================================
|
|
* Raw helpers
|
|
* ========================================================= */
|
|
static void owi_result_init(owi_io_result_t *r)
|
|
{
|
|
if (!r) return;
|
|
memset(r, 0, sizeof(*r));
|
|
r->ok = 1;
|
|
r->timeout_byte_index = 0xFFFFu;
|
|
r->timeout_bit_index = 0xFFu;
|
|
}
|
|
|
|
static void owi_result_latch_timeout(owi_io_result_t *r)
|
|
{
|
|
if (!r) return;
|
|
|
|
if (OWI_HasTimeout()) {
|
|
r->ok = 0;
|
|
r->timeout = 1;
|
|
r->timeout_byte_index = OWI_GetLastTimeoutByteIndex();
|
|
r->timeout_bit_index = OWI_GetLastTimeoutBitIndex();
|
|
}
|
|
}
|
|
|
|
void OWI_T_CommandModeRaw(const uint8_t *tx_data, uint8_t tx_len, uint8_t id, owi_io_result_t *r)
|
|
{
|
|
int i;
|
|
|
|
owi_result_init(r);
|
|
|
|
//delay_us(200);
|
|
OWI_Init(OWI_BIT_PERIOD_US);
|
|
OWI_ClearTimeout();
|
|
|
|
R_WDT_Restart();
|
|
OWI_SecureStop();
|
|
R_WDT_Restart();
|
|
OWI_WriteByte((uint8_t)(id << 1));
|
|
R_WDT_Restart();
|
|
|
|
for (i = 0; i < (int)tx_len; i++) {
|
|
R_WDT_Restart();
|
|
OWI_WriteByte(tx_data[i]);
|
|
R_WDT_Restart();
|
|
}
|
|
|
|
OWI_Stop();
|
|
R_WDT_Restart();
|
|
owi_result_latch_timeout(r);
|
|
}
|
|
|
|
void OWI_CommandModeRaw(const uint8_t *tx_data, uint8_t tx_len, uint8_t id, owi_io_result_t *r)
|
|
{
|
|
int i;
|
|
|
|
owi_result_init(r);
|
|
OWI_Init(OWI_BIT_PERIOD_US);
|
|
OWI_ClearTimeout();
|
|
|
|
R_WDT_Restart();
|
|
OWI_SecureStop();
|
|
R_WDT_Restart();
|
|
OWI_WriteByte((uint8_t)(id << 1));
|
|
R_WDT_Restart();
|
|
|
|
for (i = 0; i < (int)tx_len; i++) {
|
|
R_WDT_Restart();
|
|
OWI_WriteByte(tx_data[i]);
|
|
R_WDT_Restart();
|
|
}
|
|
|
|
OWI_Stop();
|
|
R_WDT_Restart();
|
|
owi_result_latch_timeout(r);
|
|
}
|
|
|
|
void OWI_ReadBytesRaw(int length, uint8_t id, owi_io_result_t *r)
|
|
{
|
|
int i;
|
|
int max_len;
|
|
uint8_t is_long_read;
|
|
uint8_t use_capture = 0u;
|
|
|
|
if (!r) return;
|
|
|
|
owi_result_init(r);
|
|
OWI_Init(OWI_BIT_PERIOD_US);
|
|
|
|
if (length <= 0) {
|
|
r->ok = 0;
|
|
return;
|
|
}
|
|
|
|
max_len = (int)OWI_IO_MAX_BYTES;
|
|
if (length > max_len) {
|
|
length = max_len;
|
|
}
|
|
|
|
r->read_len = (uint16_t)length;
|
|
OWI_ClearTimeout();
|
|
|
|
#if OWI_USE_TAU1_CAPTURE
|
|
/* Keep short connection/handshake reads on the proven GPIO path. */
|
|
use_capture = (length == 127) ? 1u : 0u;
|
|
#endif
|
|
/* GPIO fallback also resynchronizes the requested 127-byte path. */
|
|
is_long_read = (length == 119 || length == 127) ? 1u : 0u;
|
|
|
|
R_WDT_Restart();
|
|
#if OWI_USE_TAU1_CAPTURE
|
|
if (use_capture) {
|
|
OWI_CapturePrepare();
|
|
}
|
|
#endif
|
|
OWI_SecureStop();
|
|
OWI_WriteByte((uint8_t)((id << 1) | 1u));
|
|
|
|
#if OWI_USE_TAU1_CAPTURE
|
|
if (use_capture) {
|
|
/* Each rising edge captures the preceding LOW width in hardware. */
|
|
OWI_CaptureBegin();
|
|
|
|
for (i = 0; i < length; i++)
|
|
{
|
|
R_WDT_Restart();
|
|
r->data[i] = OWI_ReadByte_Captured((uint16_t)i);
|
|
|
|
if (OWI_HasTimeout())
|
|
{
|
|
owi_result_latch_timeout(r);
|
|
break;
|
|
}
|
|
}
|
|
|
|
OWI_CaptureEnd();
|
|
} else
|
|
#endif
|
|
{
|
|
/*
|
|
* For 129 bytes, wait for the first edge immediately after the read ID.
|
|
* The old 100us delay could enter an already-started first pulse.
|
|
* Preserve the established delay for every other read length.
|
|
*/
|
|
if (length != 129) {
|
|
delay_us(100u);
|
|
}
|
|
|
|
R_WDT_Restart();
|
|
if (!OWI_WaitForFallingEdge(0u, 0u)) {
|
|
owi_result_latch_timeout(r);
|
|
OWI_StopRead();
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < length; i++) {
|
|
R_WDT_Restart();
|
|
|
|
/* Preserve the existing byte-69 checkpoint for 119-byte reads only. */
|
|
if (is_long_read && i == (length - 50)) {
|
|
R_WDT_Restart();
|
|
if (!OWI_WaitForFallingEdge((uint16_t)i, 0u)) {
|
|
owi_result_latch_timeout(r);
|
|
break;
|
|
}
|
|
}
|
|
|
|
r->data[i] = OWI_ReadByte_StreamSynced((uint16_t)i);
|
|
|
|
if (OWI_HasTimeout()) {
|
|
owi_result_latch_timeout(r);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
OWI_StopRead();
|
|
}
|
|
|
|
void OWI_disable(void)
|
|
{
|
|
HOST_PRINT("51\r\n");
|
|
}
|
|
|
|
void OWI_T_CommandMode(const uint8_t *tx_data, uint8_t tx_len, uint8_t id)
|
|
{
|
|
owi_io_result_t r;
|
|
(void)r;
|
|
|
|
OWI_T_CommandModeRaw(tx_data, tx_len, id, &r);
|
|
HOST_PRINT("51\r\n");
|
|
}
|
|
|
|
void OWI_CommandMode(const uint8_t *tx_data, uint8_t tx_len, uint8_t id)
|
|
{
|
|
owi_io_result_t r;
|
|
(void)r;
|
|
|
|
OWI_CommandModeRaw(tx_data, tx_len, id, &r);
|
|
HOST_PRINT("51\r\n");
|
|
}
|
|
|
|
void OWI_ReadBytesAndPrint(int length, uint8_t id)
|
|
{
|
|
owi_io_result_t r;
|
|
char out[(2 * OWI_IO_MAX_BYTES) + 40];
|
|
int i;
|
|
uint16_t p = 0;
|
|
|
|
if (length <= 0) {
|
|
HOST_PRINT("Err:read_len_nonzero\r\n");
|
|
return;
|
|
}
|
|
|
|
OWI_ReadBytesRaw(length, id, &r);
|
|
|
|
if (r.read_len == 0) {
|
|
HOST_PRINT("Err:read_len_nonzero\r\n");
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < (int)r.read_len; 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';
|
|
|
|
HOST_PRINT(out);
|
|
}
|
|
|