rcbench
Servo and ESC test bench: panel, IOmcu and shared C
Loading...
Searching...
No Matches
hitec_wire.c File Reference

Hitec servo programming protocols: frames, transactions and the reply decoders. More...

#include "hitec_wire.h"
#include <string.h>

Functions

uint32_t hitec_bit_rate (uint8_t family)
 Bit rate of family in bit/s; 0 for a family this module does not have.
uint32_t hitec_bits_ns (uint8_t family, uint32_t bits)
 bits bit times of family in ns, rounded to nearest; 0 for an unknown family.
uint8_t hitec_c_sum (uint8_t cmd, uint8_t p1, uint8_t p2)
 The byte that makes cmd p1 p2 sum sum to 0 modulo 256.
void hitec_c_frame (uint8_t cmd, uint8_t p1, uint8_t p2, uint8_t out[HITEC_C_FRAME_LEN])
 The 4 bytes of a classic command.
bool hitec_c_frame_ok (const uint8_t frame[HITEC_C_FRAME_LEN])
 True when the 4 bytes at frame sum to 0 modulo 256.
uint8_t hitec_d_sum (const uint8_t *bytes, size_t n)
 The low byte of the sum of the n bytes at bytes.
void hitec_d_read_frame (uint8_t id, uint8_t addr, uint8_t out[HITEC_D_READ_LEN])
 96 id addr 00 sum.
void hitec_d_write_frame (uint8_t id, uint8_t addr, uint16_t value, uint8_t out[HITEC_D_WRITE_LEN])
 96 id addr 02 lo hi sum, value little endian.
bool hitec_xfer_valid (const hitec_xfer_t *x)
 True when x is a transaction a driver runs: every field in its range, LISTEN with a window, LEVEL with a time.
static void send_xfer (uint8_t family, const uint8_t *bytes, uint8_t n, hitec_xfer_t *out)
 Set up a SEND transaction with the given bytes and no receive window.
void hitec_c_xfer (uint8_t cmd, uint8_t p1, uint8_t p2, hitec_xfer_t *out)
 A command and its 2-byte reply: 4 bytes, HITEC_C_GAP_BITS between them, HITEC_C_WINDOW_US, 2 bytes.
void hitec_d_read_xfer (uint8_t id, uint8_t addr, hitec_xfer_t *out)
 A read and its answer: lead, 5 bytes back to back, HITEC_D_WINDOW_US, HITEC_D_READ_RX bytes.
void hitec_d_write_xfer (uint8_t id, uint8_t addr, uint16_t value, hitec_xfer_t *out)
 A write: lead, 7 bytes back to back, nothing received.
bool hitec_listen_xfer (uint8_t family, uint32_t window_us, uint8_t max_rx, bool answer, uint8_t answer_byte, hitec_xfer_t *out)
 A LISTEN of window_us for up to max_rx bytes; with answer set the first byte is answered with answer_byte.
bool hitec_level_xfer (uint8_t family, uint8_t level, uint32_t time_us, hitec_xfer_t *out)
 A LEVEL of level for time_us.
bool hitec_c_expect_of (uint8_t cmd, hitec_c_expect_t *out)
 The reply cmd has.
static hitec_rx_t common_checks (const hitec_capture_t *cap, hitec_reply_t *out)
 The checks every decoder starts with.
static uint32_t half_bits_ns (uint8_t family, uint32_t half)
 half half bit times of family in ns, rounded to nearest.
static bool gaps_ok (const hitec_capture_t *cap, unsigned n)
 Bytes 1 to n - 1 each start 9.5 to 15 bit times after the one before.
static bool framing_ok (const hitec_capture_t *cap, unsigned n)
 Check that the first n bytes of a capture have no bad stop bit.
hitec_rx_t hitec_c_decode (const hitec_capture_t *cap, hitec_c_expect_t expect, hitec_reply_t *out)
 Decode a classic reply.
hitec_rx_t hitec_d_decode (const hitec_capture_t *cap, uint8_t addr, hitec_reply_t *out)
 Decode a D series answer to a read of addr.
hitec_rx_t hitec_listen_decode (const hitec_capture_t *cap, uint8_t want, hitec_reply_t *out)
 Decode a listen for the byte want, as the classic entry's +: abort, overflow, a byte at all, its stop bit, its value, no byte after it. delay_ns is the first byte's time from the start of the listen.
uint32_t hitec_elapsed_us (uint32_t now, uint32_t since)
 Microseconds from since to now on a clock that wraps at 2^32.
bool hitec_due (uint32_t now, uint32_t since, uint32_t span_us)
 True when span_us or more have passed from since to now, also across the wrap of the clock.

Detailed Description

Hitec servo programming protocols: frames, transactions and the reply decoders.

See include/hitec_wire.h.

SPDX-License-Identifier: MIT

Function Documentation

◆ common_checks()

hitec_rx_t common_checks ( const hitec_capture_t * cap,
hitec_reply_t * out )
static

The checks every decoder starts with.

HITEC_RX_OK when the capture holds at least one byte to look at.

◆ hitec_bit_rate()

uint32_t hitec_bit_rate ( uint8_t family)

Bit rate of family in bit/s; 0 for a family this module does not have.

Parameters
familyhitec_family_t value.
Returns
Bit rate in bit/s, or 0 for an unknown family.

◆ hitec_bits_ns()

uint32_t hitec_bits_ns ( uint8_t family,
uint32_t bits )

bits bit times of family in ns, rounded to nearest; 0 for an unknown family.

Parameters
familyhitec_family_t value.
bitsNumber of bit times.
Returns
Duration in ns, rounded to nearest, or 0 for an unknown family.

◆ hitec_c_decode()

hitec_rx_t hitec_c_decode ( const hitec_capture_t * cap,
hitec_c_expect_t expect,
hitec_reply_t * out )

Decode a classic reply.

Checks in this order: the arguments, abort, overflow, a byte at all, the first byte's time (HITEC_C_REPLY_MIN_NS to HITEC_C_REPLY_MAX_NS), - alone, 2 bytes, both stop bits, the second byte's time, the + bytes. out is filled in every case as far as the checks went.

Parameters
capCapture to decode.
expectReply shape to check against.
outReceives the decoded reply.
Returns
HITEC_RX_OK, or the code of the first failed check.

◆ hitec_c_expect_of()

bool hitec_c_expect_of ( uint8_t cmd,
hitec_c_expect_t * out )

The reply cmd has.

False for a command byte this module does not know.

Parameters
cmdCommand byte.
outReceives the expected reply shape; may be NULL.
Returns
false for a command byte this module does not know.

◆ hitec_c_frame()

void hitec_c_frame ( uint8_t cmd,
uint8_t p1,
uint8_t p2,
uint8_t out[HITEC_C_FRAME_LEN] )

The 4 bytes of a classic command.

Parameters
cmdCommand byte.
p1First parameter byte.
p2Second parameter byte.
outReceives the four bytes of the frame.

◆ hitec_c_frame_ok()

bool hitec_c_frame_ok ( const uint8_t frame[HITEC_C_FRAME_LEN])

True when the 4 bytes at frame sum to 0 modulo 256.

Parameters
frameThe four bytes to check.
Returns
true when they sum to 0 modulo 256.

◆ hitec_c_sum()

uint8_t hitec_c_sum ( uint8_t cmd,
uint8_t p1,
uint8_t p2 )

The byte that makes cmd p1 p2 sum sum to 0 modulo 256.

Parameters
cmdCommand byte.
p1First parameter byte.
p2Second parameter byte.
Returns
The check byte that makes the four bytes sum to 0 modulo 256.

◆ hitec_c_xfer()

void hitec_c_xfer ( uint8_t cmd,
uint8_t p1,
uint8_t p2,
hitec_xfer_t * out )

A command and its 2-byte reply: 4 bytes, HITEC_C_GAP_BITS between them, HITEC_C_WINDOW_US, 2 bytes.

Parameters
cmdCommand byte.
p1First parameter byte.
p2Second parameter byte.
outReceives the transaction.

◆ hitec_d_decode()

hitec_rx_t hitec_d_decode ( const hitec_capture_t * cap,
uint8_t addr,
hitec_reply_t * out )

Decode a D series answer to a read of addr.

Checks in this order: the arguments, abort, overflow, a byte at all, the first byte's time (HITEC_D_ANSWER_MIN_NS to HITEC_D_ANSWER_MAX_NS), 7 bytes, their stop bits, their times, the header and length byte, the address, the sum. Bytes after the seventh are not checked: the D485HW sends 0x00 after every answer, and the release of the line reads as a byte with a bad stop bit. The ID byte is reported and not checked.

Parameters
capCapture to decode.
addrRegister address the read asked for.
outReceives the decoded reply.
Returns
HITEC_RX_OK, or the code of the first failed check.

◆ hitec_d_read_frame()

void hitec_d_read_frame ( uint8_t id,
uint8_t addr,
uint8_t out[HITEC_D_READ_LEN] )

96 id addr 00 sum.

Parameters
idServo ID.
addrRegister address.
outReceives the five bytes of the request.

◆ hitec_d_read_xfer()

void hitec_d_read_xfer ( uint8_t id,
uint8_t addr,
hitec_xfer_t * out )

A read and its answer: lead, 5 bytes back to back, HITEC_D_WINDOW_US, HITEC_D_READ_RX bytes.

Parameters
idServo ID.
addrRegister address.
outReceives the transaction.

◆ hitec_d_sum()

uint8_t hitec_d_sum ( const uint8_t * bytes,
size_t n )

The low byte of the sum of the n bytes at bytes.

Parameters
bytesBytes to sum.
nNumber of bytes.
Returns
The low byte of the sum.

◆ hitec_d_write_frame()

void hitec_d_write_frame ( uint8_t id,
uint8_t addr,
uint16_t value,
uint8_t out[HITEC_D_WRITE_LEN] )

96 id addr 02 lo hi sum, value little endian.

Parameters
idServo ID.
addrRegister address.
valueData word, sent little endian.
outReceives the seven bytes of the request.

◆ hitec_d_write_xfer()

void hitec_d_write_xfer ( uint8_t id,
uint8_t addr,
uint16_t value,
hitec_xfer_t * out )

A write: lead, 7 bytes back to back, nothing received.

Parameters
idServo ID.
addrRegister address.
valueData word, sent little endian.
outReceives the transaction.

◆ hitec_due()

bool hitec_due ( uint32_t now,
uint32_t since,
uint32_t span_us )

True when span_us or more have passed from since to now, also across the wrap of the clock.

A span is shorter than 2^31us.

Parameters
nowCurrent time, in us.
sinceEarlier time, in us.
span_usSpan to test, in us.
Returns
true when span_us or more have passed, also across the wrap of the clock.

◆ hitec_elapsed_us()

uint32_t hitec_elapsed_us ( uint32_t now,
uint32_t since )

Microseconds from since to now on a clock that wraps at 2^32.

Parameters
nowCurrent time, in us.
sinceEarlier time, in us.
Returns
Microseconds from since to now, on a clock that wraps at 2^32.

◆ hitec_level_xfer()

bool hitec_level_xfer ( uint8_t family,
uint8_t level,
uint32_t time_us,
hitec_xfer_t * out )

A LEVEL of level for time_us.

False, and out untouched, when the result would not be valid.

Parameters
familyhitec_family_t value.
levelLine level to hold, 0 or 1.
time_usHold time, in us.
outReceives the transaction; NULL returns false.
Returns
false when the result would not be valid.

◆ hitec_listen_decode()

hitec_rx_t hitec_listen_decode ( const hitec_capture_t * cap,
uint8_t want,
hitec_reply_t * out )

Decode a listen for the byte want, as the classic entry's +: abort, overflow, a byte at all, its stop bit, its value, no byte after it. delay_ns is the first byte's time from the start of the listen.

A listen for more bytes reads them from the capture.

Parameters
capCapture to decode.
wantByte expected as the first received byte.
outReceives the decoded reply.
Returns
HITEC_RX_OK, or the code of the first failed check.

◆ hitec_listen_xfer()

bool hitec_listen_xfer ( uint8_t family,
uint32_t window_us,
uint8_t max_rx,
bool answer,
uint8_t answer_byte,
hitec_xfer_t * out )

A LISTEN of window_us for up to max_rx bytes; with answer set the first byte is answered with answer_byte.

False, and out untouched, when the result would not be valid.

Parameters
familyhitec_family_t value.
window_usWaiting time for a start bit, in us.
max_rxBytes to receive.
answertrue to answer the first received byte.
answer_byteByte sent as the answer.
outReceives the transaction; NULL returns false.
Returns
false when the result would not be valid.

◆ hitec_xfer_valid()

bool hitec_xfer_valid ( const hitec_xfer_t * x)

True when x is a transaction a driver runs: every field in its range, LISTEN with a window, LEVEL with a time.

Whether the drive can make the level is the driver's check.

Parameters
xTransaction to check; NULL returns false.
Returns
true when x is a transaction a driver runs.