update SPI bridge to latest jd-c
This commit is contained in:
Родитель
ad5b0e7e02
Коммит
4b0c3fbf55
228
src/bridge.c
228
src/bridge.c
|
@ -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
|
Загрузка…
Ссылка в новой задаче