|
|
|
|
#include "app_owi_service.h"
|
|
|
|
|
#include "owi.h"
|
|
|
|
|
#include "delay.h"
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
static app_owi_result_t app_owi_from_raw(const owi_io_result_t *io)
|
|
|
|
|
{
|
|
|
|
|
app_owi_result_t r;
|
|
|
|
|
uint16_t i;
|
|
|
|
|
|
|
|
|
|
memset(&r, 0, sizeof(r));
|
|
|
|
|
|
|
|
|
|
if (!io) {
|
|
|
|
|
r.ok = 0;
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r.ok = io->ok;
|
|
|
|
|
r.timeout = io->timeout;
|
|
|
|
|
r.read_len = io->read_len;
|
|
|
|
|
r.timeout_byte_index = io->timeout_byte_index;
|
|
|
|
|
r.timeout_bit_index = io->timeout_bit_index;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < io->read_len && i < OWI_IO_MAX_BYTES; i++) {
|
|
|
|
|
r.data[i] = io->data[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint8_t is_long_owi_read(int length)
|
|
|
|
|
{
|
|
|
|
|
return (length == 119 || length == 127) ? 1u : 0u;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint8_t looks_bad_tail(const owi_io_result_t *io)
|
|
|
|
|
{
|
|
|
|
|
uint16_t i;
|
|
|
|
|
uint8_t zero_run = 0;
|
|
|
|
|
uint8_t ff_run = 0;
|
|
|
|
|
|
|
|
|
|
if (!io) return 1u;
|
|
|
|
|
if (io->read_len < 24u) return 1u;
|
|
|
|
|
|
|
|
|
|
for (i = (uint16_t)(io->read_len - 24u); i < io->read_len; i++) {
|
|
|
|
|
uint8_t b = io->data[i];
|
|
|
|
|
|
|
|
|
|
if (b == 0x00u) zero_run++;
|
|
|
|
|
else zero_run = 0;
|
|
|
|
|
|
|
|
|
|
if (b == 0xFFu) ff_run++;
|
|
|
|
|
else ff_run = 0;
|
|
|
|
|
|
|
|
|
|
/* tail ?? 8??? ?? ?? 00/FF? ??? */
|
|
|
|
|
if (zero_run >= 8u || ff_run >= 8u) {
|
|
|
|
|
return 1u;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0u;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ? ? ?? 4???? ?? 00 ?? ?? FF? ????? ?? */
|
|
|
|
|
static uint8_t looks_bad_last_bytes(const owi_io_result_t *io)
|
|
|
|
|
{
|
|
|
|
|
uint16_t start;
|
|
|
|
|
uint8_t i;
|
|
|
|
|
uint8_t all_zero = 1u;
|
|
|
|
|
uint8_t all_ff = 1u;
|
|
|
|
|
|
|
|
|
|
if (!io) return 1u;
|
|
|
|
|
if (io->read_len < 6u) return 1u;
|
|
|
|
|
|
|
|
|
|
start = (uint16_t)(io->read_len - 6u);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < 6u; i++) {
|
|
|
|
|
uint8_t b = io->data[start + i];
|
|
|
|
|
|
|
|
|
|
if (b != 0x00u) all_zero = 0u;
|
|
|
|
|
if (b != 0xFFu) all_ff = 0u;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (uint8_t)(all_zero || all_ff);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint8_t needs_retry_for_long_read(const owi_io_result_t *io, int length)
|
|
|
|
|
{
|
|
|
|
|
if (!is_long_owi_read(length)) return 0u;
|
|
|
|
|
if (!io) return 1u;
|
|
|
|
|
|
|
|
|
|
if (!io->ok) return 1u;
|
|
|
|
|
if (io->timeout) return 1u;
|
|
|
|
|
if (io->read_len < (uint16_t)length) return 1u;
|
|
|
|
|
if (looks_bad_tail(io)) return 1u;
|
|
|
|
|
if (looks_bad_last_bytes(io)) return 1u;
|
|
|
|
|
|
|
|
|
|
return 0u;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
app_owi_result_t app_owi_read_basic(uint8_t id, int length)
|
|
|
|
|
{
|
|
|
|
|
owi_io_result_t io;
|
|
|
|
|
|
|
|
|
|
OWI_ReadBytesRaw(length, id, &io);
|
|
|
|
|
|
|
|
|
|
if (needs_retry_for_long_read(&io, length)) {
|
|
|
|
|
delay_us(3000u);
|
|
|
|
|
OWI_ReadBytesRaw(length, id, &io);
|
|
|
|
|
|
|
|
|
|
/* ??? ??? ???? ?? ?? */
|
|
|
|
|
if (needs_retry_for_long_read(&io, length)) {
|
|
|
|
|
io.ok = 0u;
|
|
|
|
|
io.timeout = 1u;
|
|
|
|
|
io.timeout_byte_index = 0xFFFEu;
|
|
|
|
|
io.timeout_bit_index = 0xFEu;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return app_owi_from_raw(&io);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
app_owi_result_t app_owi_write_basic(uint8_t id, const uint8_t *tx_data, uint8_t tx_len)
|
|
|
|
|
{
|
|
|
|
|
owi_io_result_t io;
|
|
|
|
|
OWI_CommandModeRaw(tx_data, tx_len, id, &io);
|
|
|
|
|
return app_owi_from_raw(&io);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
app_owi_result_t app_owi_write_t_basic(uint8_t id, const uint8_t *tx_data, uint8_t tx_len)
|
|
|
|
|
{
|
|
|
|
|
owi_io_result_t io;
|
|
|
|
|
OWI_T_CommandModeRaw(tx_data, tx_len, id, &io);
|
|
|
|
|
return app_owi_from_raw(&io);
|
|
|
|
|
}
|