update SPI bridge to latest jd-c

This commit is contained in:
Michal Moskal 2022-06-20 16:33:55 -07:00
Родитель ad5b0e7e02
Коммит 4b0c3fbf55
2 изменённых файлов: 10 добавлений и 316 удалений

Просмотреть файл

@ -1,228 +0,0 @@
#include "lib.h"
// SPI-Jacdac bridge (not used)
#ifdef BRIDGEQ
struct srv_state {
SRV_COMMON;
uint8_t enabled;
uint8_t pin_cs, pin_txrq;
uint8_t rx_size, shift, skip_one;
jd_queue_t rx_q;
uint32_t next_send;
jd_frame_t spi_rx;
};
REG_DEFINITION( //
bridge_regs, //
REG_SRV_COMMON, //
REG_U8(JD_REG_INTENSITY), //
)
void jd_send_low(jd_frame_t *f);
static srv_t *_state;
static void spi_done_handler(void) {
srv_t *state = _state;
unsigned frmsz = JD_FRAME_SIZE(&state->spi_rx);
if (state->spi_rx.size == 0xFE) {
// m:b didn't manage to read the packet; try again
state->rx_size = 0;
pin_set(state->pin_cs, 1);
pwr_leave_tim();
state->next_send = now;
tim_max_sleep = 100;
return;
}
if (frmsz > state->rx_size && state->spi_rx.size != 0xFF) {
// we didn't read enough
uint8_t *d = (uint8_t *)&state->spi_rx + state->rx_size;
unsigned left = frmsz - state->rx_size;
state->rx_size = frmsz;
dspi_xfer(NULL, d, left, spi_done_handler);
} else {
state->rx_size = 0;
pin_set(state->pin_cs, 1);
pwr_leave_tim();
if (state->shift)
jd_queue_shift(state->rx_q);
if (4 <= state->spi_rx.size && state->spi_rx.size <= 240) {
if (state->spi_rx.flags & JD_FRAME_FLAG_LOOPBACK) {
jd_packet_t *pkt = (jd_packet_t *)&state->spi_rx;
if (pkt->service_index == 0)
switch (pkt->service_command) {
case 0xf0:
ns_set(pkt->device_identifier, (const char *)pkt->data);
break;
case 0xf1:
ns_clear();
break;
}
}
} else {
jd_send_low(&state->spi_rx);
// also process packets ourselves - m:b might be talking to us
jd_services_process_frame(&state->spi_rx);
}
}
state->next_send = now + 99;
tim_max_sleep = 100;
}
static void xchg(srv_t *state) {
if (state->rx_size)
return;
if (in_future(state->next_send)) {
tim_max_sleep = 100;
return;
}
if (state->skip_one) {
state->skip_one = 0;
return;
}
// tim_max_sleep = 0; // TODO work on power consumption
jd_frame_t *fwd = jd_queue_front(state->rx_q);
int size = 32;
if (fwd && JD_FRAME_SIZE(fwd) > size)
size = JD_FRAME_SIZE(fwd);
state->rx_size = size;
state->shift = !!fwd;
pin_set(state->pin_cs, 0);
pwr_enter_tim();
*(uint32_t *)&state->spi_rx = 0;
dspi_xfer(fwd, &state->spi_rx, size, spi_done_handler);
}
void bridge_forward_frame(jd_frame_t *frame) {
if (frame != &_state->spi_rx) {
// for announce packets
jd_packet_t *pkt = (jd_packet_t *)frame;
if (pkt->service_command == JD_SERVICE_INDEX_CONTROL &&
pkt->service_index == JD_CONTROL_CMD_SERVICES &&
!(frame->flags & JD_FRAME_FLAG_COMMAND)) {
// we check if we have name for the source device
const char *name = ns_get(pkt->device_identifier);
if (name) {
unsigned namelen = strlen(name);
unsigned len = (namelen + 4 + 3) & ~3;
// and if it will fit in frame
if (frame->size + len < JD_SERIAL_PAYLOAD_SIZE + 4) {
// we shift everything forward
uint32_t *src = (uint32_t *)(frame->data + frame->size - 4);
uint32_t *dst = src + (len >> 2);
while (src >= (uint32_t *)frame->data)
*dst-- = *src--;
// and add the name at the beginning
pkt->service_command = JD_GET(JD_REG_CTRL_SELF_NAME);
pkt->service_size = namelen;
memcpy(pkt->data, name, namelen);
frame->size += len;
}
}
}
jd_queue_push(_state->rx_q, frame);
}
}
void bridge_process(srv_t *state) {
if (jd_queue_front(state->rx_q) || (!in_future(state->next_send) && pin_get(state->pin_txrq) == 0))
xchg(state);
}
void bridge_handle_packet(srv_t *state, jd_packet_t *pkt) {
service_handle_register_final(state, pkt, bridge_regs);
}
SRV_DEF(bridge, JD_SERVICE_CLASS_BRIDGE);
void bridge_init(uint8_t pin_cs, uint8_t pin_txrq) {
SRV_ALLOC(bridge);
ns_init();
dspi_init(false, 0 , 0);
state->pin_cs = pin_cs;
pin_set(pin_cs, 1);
pin_setup_output(pin_cs);
state->pin_txrq = pin_txrq;
pin_setup_input(pin_txrq, PIN_PULL_UP);
state->rx_q = jd_queue_alloc(512);
_state = state;
}
// alternative tx_Q impl.
static jd_queue_t tx_q;
static bool isSending;
int jd_tx_is_idle() {
return !isSending && jd_queue_front(tx_q) == NULL;
}
void jd_tx_init(void) {
tx_q = jd_queue_alloc(512);
}
void jd_send_low(jd_frame_t *f) {
jd_compute_crc(f);
jd_queue_push(tx_q, f);
jd_packet_ready();
}
int jd_send(unsigned service_num, unsigned service_cmd, const void *data, unsigned service_size) {
if (service_size > 32)
jd_panic();
uint32_t buf[(service_size + 16 + 3) / 4];
jd_frame_t *f = (jd_frame_t *)buf;
jd_reset_frame(f);
void *trg = jd_push_in_frame(f, service_num, service_cmd, service_size);
memcpy(trg, data, service_size);
f->device_identifier = jd_device_id();
jd_send_low(f);
if (_state) {
jd_queue_push(_state->rx_q, f); // also forward packets we generate ourselves
_state->skip_one = 1;
}
return 0;
}
void jd_send_event_ext(srv_t *srv, uint32_t eventid, uint32_t arg) {
srv_common_t *state = (srv_common_t *)srv;
if (eventid >> 16)
jd_panic();
uint32_t data[] = {eventid, arg};
jd_send(state->service_index, JD_CMD_EVENT, data, 8);
}
// bridge between phys and queue imp, phys calls this to get the next frame.
jd_frame_t *jd_tx_get_frame(void) {
jd_frame_t *f = jd_queue_front(tx_q);
if (f)
isSending = true;
return f;
}
// bridge between phys and queue imp, marks as sent.
void jd_tx_frame_sent(jd_frame_t *pkt) {
isSending = false;
jd_queue_shift(tx_q);
if (jd_queue_front(tx_q))
jd_packet_ready(); // there's more to do
}
void jd_tx_flush() {
// do nothing
}
#endif

Просмотреть файл

@ -2,19 +2,16 @@
// SPI-Jacdac bridge for RPi
#ifdef BRIDGESPI
#ifdef PIN_BR_TX_READY
#if !JD_BRIDGE || !JD_SEND_FRAME
#error "JD_BRIDGE reqd"
#endif
#define XFER_SIZE 256
#define TXQ_SIZE 1024
#define RXQ_SIZE 1024
static jd_queue_t tx_q;
#if JD_RAW_FRAME
uint8_t rawFrameSending;
jd_frame_t *rawFrame;
#endif
#define JD_SERVICE_CLASS_BRIDGE 0x1fe5b46f
struct srv_state {
@ -39,8 +36,6 @@ REG_DEFINITION( //
REG_U8(JD_REG_INTENSITY), //
)
void jd_send_low(jd_frame_t *f);
static srv_t *_state;
static inline bool is_host_frame(jd_frame_t *f) {
@ -52,7 +47,7 @@ static void spi_done_handler(void) {
srv_t *state = _state;
if (jd_should_sample(&state->connected_blink, 2 * 512 * 1024)) {
jd_status_set_ch(2, 150);
// jd_status_set_ch(2, 150);
state->connected_blink_end = tim_get_micros() + 50 * 1024;
}
@ -60,9 +55,7 @@ static void spi_done_handler(void) {
while (frame->size && (uint8_t *)frame < &_state->spi_host[XFER_SIZE]) {
unsigned frmsz = JD_FRAME_SIZE(frame);
jd_send_low(frame);
// also process packets ourselves - RPi might be talking to us
jd_services_process_frame(frame);
jd_send_frame_raw(frame);
frame = (jd_frame_t *)((uint8_t *)frame + ((frmsz + 3) & ~3));
}
@ -104,7 +97,7 @@ static void setup_xfer(srv_t *state) {
state->spi_host[2] = 0xff;
spis_xfer(state->spi_bridge, state->spi_host, XFER_SIZE, spi_done_handler);
pin_set(PIN_BR_TX_READY, jd_queue_will_fit(tx_q, sizeof(XFER_SIZE)));
pin_set(PIN_BR_TX_READY, jd_tx_will_fit(XFER_SIZE));
pin_set(PIN_BR_RX_READY, has_rx);
target_enable_irq();
}
@ -112,7 +105,7 @@ static void setup_xfer(srv_t *state) {
// called when physical layer received a frame
void bridge_forward_frame(jd_frame_t *frame) {
if (is_host_frame(frame))
return; // ignore stuff we sent ourselves
jd_panic(); // loop?
srv_t *state = _state;
@ -139,7 +132,7 @@ void bridge_forward_frame(jd_frame_t *frame) {
void bridge_process(srv_t *state) {
if (state->connected_blink_end && in_past(state->connected_blink_end)) {
state->connected_blink_end = 0;
jd_status_set_ch(2, 0);
// jd_status_set_ch(2, 0);
}
}
@ -171,75 +164,4 @@ void bridge_init(void) {
setup_xfer(state);
}
// alternative tx_Q impl.
static bool isSending;
int jd_tx_is_idle() {
return !isSending && jd_queue_front(tx_q) == NULL;
}
void jd_tx_init(void) {
tx_q = jd_queue_alloc(TXQ_SIZE);
}
void jd_send_low(jd_frame_t *f) {
jd_compute_crc(f);
jd_queue_push(tx_q, f);
jd_packet_ready();
}
int jd_send(unsigned service_num, unsigned service_cmd, const void *data, unsigned service_size) {
if (service_size > 64)
jd_panic();
uint32_t buf[(service_size + 16 + 3) / 4];
jd_frame_t *f = (jd_frame_t *)buf;
jd_reset_frame(f);
void *trg = jd_push_in_frame(f, service_num, service_cmd, service_size);
memcpy(trg, data, service_size);
f->device_identifier = jd_device_id();
jd_send_low(f);
if (_state) {
bridge_forward_frame(f); // also forward packets we generate ourselves
}
return 0;
}
// bridge between phys and queue imp, phys calls this to get the next frame.
jd_frame_t *jd_tx_get_frame(void) {
#if JD_RAW_FRAME
if (rawFrame) {
jd_frame_t *r = rawFrame;
rawFrame = NULL;
rawFrameSending = true;
return r;
}
#endif
jd_frame_t *f = jd_queue_front(tx_q);
if (f)
isSending = true;
return f;
}
// bridge between phys and queue imp, marks as sent.
void jd_tx_frame_sent(jd_frame_t *pkt) {
#if JD_RAW_FRAME
if (rawFrameSending) {
rawFrameSending = false;
return;
}
#endif
isSending = false;
jd_queue_shift(tx_q);
if (jd_queue_front(tx_q))
jd_packet_ready(); // there's more to do
}
void jd_tx_flush() {
// do nothing
}
#endif