make rbuf len configurable, signal overflow to host

This commit is contained in:
Steve Markgraf 2025-02-12 23:22:59 +01:00
parent 1bdf43ae94
commit c5cf8c1178
7 changed files with 44 additions and 33 deletions

View file

@ -49,7 +49,7 @@
#define DMACH_PIO_PONG 1 #define DMACH_PIO_PONG 1
static bool pio_dma_pong = false; static bool pio_dma_pong = false;
uint16_t ringbuffer[RBUF_TOTAL_LEN]; uint16_t ringbuffer[RBUF_DEFAULT_TOTAL_LEN];
int ringbuf_head = 2; int ringbuf_head = 2;
void __scratch_y("") pio_dma_irq_handler() void __scratch_y("") pio_dma_irq_handler()
@ -59,7 +59,7 @@ void __scratch_y("") pio_dma_irq_handler()
dma_hw->intr = 1u << ch_num; dma_hw->intr = 1u << ch_num;
pio_dma_pong = !pio_dma_pong; pio_dma_pong = !pio_dma_pong;
ringbuf_head = (ringbuf_head + 1) % RBUF_SLICES; ringbuf_head = (ringbuf_head + 1) % RBUF_DEFAULT_SLICES;
ch->write_addr = (uintptr_t)&ringbuffer[ringbuf_head * RBUF_SLICE_LEN]; ch->write_addr = (uintptr_t)&ringbuffer[ringbuf_head * RBUF_SLICE_LEN];
ch->transfer_count = RBUF_MAX_DATA_LEN; ch->transfer_count = RBUF_MAX_DATA_LEN;
@ -130,7 +130,7 @@ int main()
stdio_init_all(); stdio_init_all();
hsdaoh_init(GPIO_DRIVE_STRENGTH_4MA, GPIO_SLEW_RATE_SLOW); hsdaoh_init(GPIO_DRIVE_STRENGTH_4MA, GPIO_SLEW_RATE_SLOW);
hsdaoh_add_stream(0, 1, (SYS_CLK/8) * 1000, RBUF_MAX_DATA_LEN, ringbuffer); hsdaoh_add_stream(0, 1, (SYS_CLK/8) * 1000, RBUF_MAX_DATA_LEN, RBUF_DEFAULT_SLICES, ringbuffer);
hsdaoh_start(); hsdaoh_start();
init_pio_input(); init_pio_input();

View file

@ -67,7 +67,7 @@
#define DMACH_PIO_PONG 1 #define DMACH_PIO_PONG 1
static bool pio_dma_pong = false; static bool pio_dma_pong = false;
uint16_t ringbuffer[RBUF_TOTAL_LEN]; uint16_t ringbuffer[RBUF_DEFAULT_TOTAL_LEN];
int ringbuf_head = 2; int ringbuf_head = 2;
void __scratch_y("") pio_dma_irq_handler() void __scratch_y("") pio_dma_irq_handler()
@ -77,7 +77,7 @@ void __scratch_y("") pio_dma_irq_handler()
dma_hw->intr = 1u << ch_num; dma_hw->intr = 1u << ch_num;
pio_dma_pong = !pio_dma_pong; pio_dma_pong = !pio_dma_pong;
ringbuf_head = (ringbuf_head + 1) % RBUF_SLICES; ringbuf_head = (ringbuf_head + 1) % RBUF_DEFAULT_SLICES;
ch->write_addr = (uintptr_t)&ringbuffer[ringbuf_head * RBUF_SLICE_LEN]; ch->write_addr = (uintptr_t)&ringbuffer[ringbuf_head * RBUF_SLICE_LEN];
ch->transfer_count = ADC_DATA_LEN/2; ch->transfer_count = ADC_DATA_LEN/2;
@ -143,7 +143,7 @@ void init_pio_input(void)
#define DMACH_AUDIO_PIO_PONG 3 #define DMACH_AUDIO_PIO_PONG 3
static bool audio_pio_dma_pong = false; static bool audio_pio_dma_pong = false;
uint16_t audio_ringbuffer[RBUF_TOTAL_LEN]; uint16_t audio_ringbuffer[RBUF_DEFAULT_TOTAL_LEN];
int audio_ringbuf_head = 2; int audio_ringbuf_head = 2;
void __scratch_y("") audio_pio_dma_irq_handler() void __scratch_y("") audio_pio_dma_irq_handler()
@ -153,7 +153,7 @@ void __scratch_y("") audio_pio_dma_irq_handler()
dma_hw->intr = 1u << ch_num; dma_hw->intr = 1u << ch_num;
audio_pio_dma_pong = !audio_pio_dma_pong; audio_pio_dma_pong = !audio_pio_dma_pong;
audio_ringbuf_head = (audio_ringbuf_head + 1) % RBUF_SLICES; audio_ringbuf_head = (audio_ringbuf_head + 1) % RBUF_DEFAULT_SLICES;
ch->write_addr = (uintptr_t)&audio_ringbuffer[audio_ringbuf_head * RBUF_SLICE_LEN]; ch->write_addr = (uintptr_t)&audio_ringbuffer[audio_ringbuf_head * RBUF_SLICE_LEN];
ch->transfer_count = AUDIO_DATA_LEN/2; ch->transfer_count = AUDIO_DATA_LEN/2;
@ -231,7 +231,6 @@ int main()
); );
pll_init(pll_usb, 1, 1536 * MHZ, 4, 2); pll_init(pll_usb, 1, 1536 * MHZ, 4, 2);
// pll_init(pll_usb, 1, (983 * MHZ) + (40 * KHZ), 4, 2);
/* set USB clock to clk_usb/4 */ /* set USB clock to clk_usb/4 */
hw_write_masked(&clocks_hw->clk[clk_usb].div, 4 << CLOCKS_CLK_USB_DIV_INT_LSB, CLOCKS_CLK_USB_DIV_INT_BITS); hw_write_masked(&clocks_hw->clk[clk_usb].div, 4 << CLOCKS_CLK_USB_DIV_INT_LSB, CLOCKS_CLK_USB_DIV_INT_BITS);
@ -242,8 +241,8 @@ int main()
stdio_init_all(); stdio_init_all();
hsdaoh_init(GPIO_DRIVE_STRENGTH_4MA, GPIO_SLEW_RATE_SLOW); hsdaoh_init(GPIO_DRIVE_STRENGTH_4MA, GPIO_SLEW_RATE_SLOW);
hsdaoh_add_stream(0, 1, (SYS_CLK/8) * 1000, ADC_DATA_LEN, ringbuffer); hsdaoh_add_stream(0, 1, (SYS_CLK/8) * 1000, ADC_DATA_LEN, RBUF_DEFAULT_SLICES, ringbuffer);
hsdaoh_add_stream(1, 1, 75000, AUDIO_DATA_LEN, audio_ringbuffer); hsdaoh_add_stream(1, 1, 75000, AUDIO_DATA_LEN, RBUF_DEFAULT_SLICES, audio_ringbuffer);
hsdaoh_start(); hsdaoh_start();
init_pio_input(); init_pio_input();
init_audio_pio_input(); init_audio_pio_input();

View file

@ -66,7 +66,7 @@
#define DMACH_PIO_PONG 1 #define DMACH_PIO_PONG 1
static bool pio_dma_pong = false; static bool pio_dma_pong = false;
uint16_t ringbuffer[RBUF_TOTAL_LEN]; uint16_t ringbuffer[RBUF_DEFAULT_TOTAL_LEN];
int ringbuf_head = 2; int ringbuf_head = 2;
void __scratch_y("") pio_dma_irq_handler() void __scratch_y("") pio_dma_irq_handler()
@ -76,7 +76,7 @@ void __scratch_y("") pio_dma_irq_handler()
dma_hw->intr = 1u << ch_num; dma_hw->intr = 1u << ch_num;
pio_dma_pong = !pio_dma_pong; pio_dma_pong = !pio_dma_pong;
ringbuf_head = (ringbuf_head + 1) % RBUF_SLICES; ringbuf_head = (ringbuf_head + 1) % RBUF_DEFAULT_SLICES;
ch->write_addr = (uintptr_t)&ringbuffer[ringbuf_head * RBUF_SLICE_LEN]; ch->write_addr = (uintptr_t)&ringbuffer[ringbuf_head * RBUF_SLICE_LEN];
ch->transfer_count = ADC_DATA_LEN; ch->transfer_count = ADC_DATA_LEN;
@ -137,7 +137,7 @@ void init_pio_input(void)
#define DMACH_AUDIO_PIO_PONG 3 #define DMACH_AUDIO_PIO_PONG 3
static bool audio_pio_dma_pong = false; static bool audio_pio_dma_pong = false;
uint16_t audio_ringbuffer[RBUF_TOTAL_LEN]; uint16_t audio_ringbuffer[RBUF_DEFAULT_TOTAL_LEN];
int audio_ringbuf_head = 2; int audio_ringbuf_head = 2;
void __scratch_y("") audio_pio_dma_irq_handler() void __scratch_y("") audio_pio_dma_irq_handler()
@ -147,7 +147,7 @@ void __scratch_y("") audio_pio_dma_irq_handler()
dma_hw->intr = 1u << ch_num; dma_hw->intr = 1u << ch_num;
audio_pio_dma_pong = !audio_pio_dma_pong; audio_pio_dma_pong = !audio_pio_dma_pong;
audio_ringbuf_head = (audio_ringbuf_head + 1) % RBUF_SLICES; audio_ringbuf_head = (audio_ringbuf_head + 1) % RBUF_DEFAULT_SLICES;
ch->write_addr = (uintptr_t)&audio_ringbuffer[audio_ringbuf_head * RBUF_SLICE_LEN]; ch->write_addr = (uintptr_t)&audio_ringbuffer[audio_ringbuf_head * RBUF_SLICE_LEN];
ch->transfer_count = AUDIO_DATA_LEN/2; ch->transfer_count = AUDIO_DATA_LEN/2;
@ -220,7 +220,6 @@ int main()
); );
pll_init(pll_usb, 1, 1536 * MHZ, 4, 2); pll_init(pll_usb, 1, 1536 * MHZ, 4, 2);
// pll_init(pll_usb, 1, (983 * MHZ) + (40 * KHZ), 4, 2);
/* set USB clock to clk_usb/4 */ /* set USB clock to clk_usb/4 */
hw_write_masked(&clocks_hw->clk[clk_usb].div, 4 << CLOCKS_CLK_USB_DIV_INT_LSB, CLOCKS_CLK_USB_DIV_INT_BITS); hw_write_masked(&clocks_hw->clk[clk_usb].div, 4 << CLOCKS_CLK_USB_DIV_INT_LSB, CLOCKS_CLK_USB_DIV_INT_BITS);
@ -231,8 +230,8 @@ int main()
stdio_init_all(); stdio_init_all();
hsdaoh_init(GPIO_DRIVE_STRENGTH_4MA, GPIO_SLEW_RATE_SLOW); hsdaoh_init(GPIO_DRIVE_STRENGTH_4MA, GPIO_SLEW_RATE_SLOW);
hsdaoh_add_stream(0, 1, (SYS_CLK/4) * 1000, ADC_DATA_LEN, ringbuffer); hsdaoh_add_stream(0, 1, (SYS_CLK/4) * 1000, ADC_DATA_LEN, RBUF_DEFAULT_SLICES, ringbuffer);
hsdaoh_add_stream(1, 1, 75000, AUDIO_DATA_LEN, audio_ringbuffer); hsdaoh_add_stream(1, 1, 75000, AUDIO_DATA_LEN, RBUF_DEFAULT_SLICES, audio_ringbuffer);
hsdaoh_start(); hsdaoh_start();
init_pio_input(); init_pio_input();
init_audio_pio_input(); init_audio_pio_input();

View file

@ -54,7 +54,7 @@
#define DMACH_ADC_PONG 1 #define DMACH_ADC_PONG 1
static bool dma_adc_pong = false; static bool dma_adc_pong = false;
uint16_t ringbuffer[RBUF_TOTAL_LEN]; uint16_t ringbuffer[RBUF_DEFAULT_TOTAL_LEN];
int ringbuf_head = 2; int ringbuf_head = 2;
void __scratch_y("") adc_dma_irq_handler() void __scratch_y("") adc_dma_irq_handler()
@ -64,7 +64,7 @@ void __scratch_y("") adc_dma_irq_handler()
dma_hw->intr = 1u << ch_num; dma_hw->intr = 1u << ch_num;
dma_adc_pong = !dma_adc_pong; dma_adc_pong = !dma_adc_pong;
ringbuf_head = (ringbuf_head + 1) % RBUF_SLICES; ringbuf_head = (ringbuf_head + 1) % RBUF_DEFAULT_SLICES;
ch->write_addr = (uintptr_t)&ringbuffer[ringbuf_head * RBUF_SLICE_LEN]; ch->write_addr = (uintptr_t)&ringbuffer[ringbuf_head * RBUF_SLICE_LEN];
ch->transfer_count = RBUF_MAX_DATA_LEN; ch->transfer_count = RBUF_MAX_DATA_LEN;
@ -153,7 +153,7 @@ int main()
stdio_init_all(); stdio_init_all();
hsdaoh_init(GPIO_DRIVE_STRENGTH_4MA, GPIO_SLEW_RATE_SLOW); hsdaoh_init(GPIO_DRIVE_STRENGTH_4MA, GPIO_SLEW_RATE_SLOW);
hsdaoh_add_stream(0, 1, (SYS_CLK/8) * 1000, RBUF_MAX_DATA_LEN, ringbuffer); hsdaoh_add_stream(0, 1, (SYS_CLK/8) * 1000, RBUF_MAX_DATA_LEN, RBUF_DEFAULT_SLICES, ringbuffer);
hsdaoh_start(); hsdaoh_start();
init_adc_input(); init_adc_input();

View file

@ -53,7 +53,7 @@
#define DMACH_PIO_PONG 1 #define DMACH_PIO_PONG 1
static bool pio_dma_pong = false; static bool pio_dma_pong = false;
uint16_t ringbuffer[RBUF_TOTAL_LEN]; uint16_t ringbuffer[RBUF_DEFAULT_TOTAL_LEN];
int ringbuf_head = 2; int ringbuf_head = 2;
void __scratch_y("") pio_dma_irq_handler() void __scratch_y("") pio_dma_irq_handler()
@ -63,7 +63,7 @@ void __scratch_y("") pio_dma_irq_handler()
dma_hw->intr = 1u << ch_num; dma_hw->intr = 1u << ch_num;
pio_dma_pong = !pio_dma_pong; pio_dma_pong = !pio_dma_pong;
ringbuf_head = (ringbuf_head + 1) % RBUF_SLICES; ringbuf_head = (ringbuf_head + 1) % RBUF_DEFAULT_SLICES;
ch->write_addr = (uintptr_t)&ringbuffer[ringbuf_head * RBUF_SLICE_LEN]; ch->write_addr = (uintptr_t)&ringbuffer[ringbuf_head * RBUF_SLICE_LEN];
ch->transfer_count = RBUF_MAX_DATA_LEN; ch->transfer_count = RBUF_MAX_DATA_LEN;
@ -136,7 +136,7 @@ int main()
stdio_init_all(); stdio_init_all();
hsdaoh_init(GPIO_DRIVE_STRENGTH_4MA, GPIO_SLEW_RATE_SLOW); hsdaoh_init(GPIO_DRIVE_STRENGTH_4MA, GPIO_SLEW_RATE_SLOW);
hsdaoh_add_stream(0, 1, (SYS_CLK/8) * 1000, RBUF_MAX_DATA_LEN, ringbuffer); hsdaoh_add_stream(0, 1, (SYS_CLK/8) * 1000, RBUF_MAX_DATA_LEN, RBUF_DEFAULT_SLICES, ringbuffer);
hsdaoh_start(); hsdaoh_start();
init_pio_input(); init_pio_input();

View file

@ -75,10 +75,12 @@ typedef struct
uint16_t *rbuf; uint16_t *rbuf;
uint tail; uint tail;
uint head; uint head;
uint rbuf_slices;
uint16_t format; uint16_t format;
uint32_t srate; uint32_t srate;
uint16_t len; uint16_t len;
uint64_t data_cnt; uint64_t data_cnt;
bool overflow;
} stream_t; } stream_t;
stream_t streams[MAX_STREAMS]; stream_t streams[MAX_STREAMS];
@ -157,7 +159,10 @@ void init_info_packet(void)
void hsdaoh_update_head(int stream_id, int head) void hsdaoh_update_head(int stream_id, int head)
{ {
streams[stream_id].head = head; if (streams[stream_id].tail == head)
streams[stream_id].overflow = true;
else
streams[stream_id].head = head;
} }
#define DMACH_HSTX_START 13 #define DMACH_HSTX_START 13
@ -234,11 +239,18 @@ void __scratch_x("") hstx_dma_irq_handler()
if (!stream->active) if (!stream->active)
continue; continue;
int next_tail = (stream->tail + 1) % RBUF_SLICES; int next_tail = (stream->tail + 1) % stream->rbuf_slices;
if (stream->head != next_tail) { if (stream->head != next_tail) {
next_line = &stream->rbuf[stream->tail * RBUF_SLICE_LEN]; next_line = &stream->rbuf[stream->tail * RBUF_SLICE_LEN];
stream->tail = next_tail; stream->tail = next_tail;
next_line[RBUF_SLICE_LEN - 1] = stream->len; stream->data_cnt += stream->len;
if (stream->overflow) {
/* signal that there has been an overflow */
next_line[RBUF_SLICE_LEN - 1] = 0x0fff;
stream->overflow = false;
} else
next_line[RBUF_SLICE_LEN - 1] = stream->len;
next_line[RBUF_SLICE_LEN - 3] = i; // stream ID next_line[RBUF_SLICE_LEN - 3] = i; // stream ID
break; break;
} }
@ -284,7 +296,7 @@ void hsdaoh_start(void)
dma_channel_start(DMACH_HSTX_START); dma_channel_start(DMACH_HSTX_START);
} }
int hsdaoh_add_stream(uint16_t stream_id, uint16_t format, uint32_t samplerate, uint length, uint16_t *ringbuf) int hsdaoh_add_stream(uint16_t stream_id, uint16_t format, uint32_t samplerate, uint length, uint slices, uint16_t *ringbuf)
{ {
if (stream_id >= MAX_STREAMS) if (stream_id >= MAX_STREAMS)
return -1; return -1;
@ -294,7 +306,8 @@ int hsdaoh_add_stream(uint16_t stream_id, uint16_t format, uint32_t samplerate,
stream->format = format; stream->format = format;
stream->srate = samplerate; stream->srate = samplerate;
stream->len = length; stream->len = length;
stream->tail = RBUF_SLICES-1; stream->rbuf_slices = slices;
stream->tail = slices-1;
stream->head = 0; stream->head = 0;
stream->data_cnt = 0; stream->data_cnt = 0;
stream->active = true; stream->active = true;
@ -378,7 +391,7 @@ void hsdaoh_init(int dstrength, int slewrate)
} }
/* All channels are set up identically, to transfer a whole scanline and /* All channels are set up identically, to transfer a whole scanline and
* then chain to the net channel. Each time a channel finishes, we * then chain to the next channel. Each time a channel finishes, we
* reconfigure the one that just finished, meanwhile another channel * reconfigure the one that just finished, meanwhile another channel
* is already making progress. */ * is already making progress. */
for (int i = 0; i < DMACH_HSTX_COUNT; i++) { for (int i = 0; i < DMACH_HSTX_COUNT; i++) {

View file

@ -23,12 +23,12 @@
// stream ID, CRC word and length/metadata word, so 3 reserved words // stream ID, CRC word and length/metadata word, so 3 reserved words
#define NUM_RESERVED_WORDS 3 #define NUM_RESERVED_WORDS 3
#define RBUF_SLICES 16 #define RBUF_DEFAULT_SLICES 16
#define RBUF_SLICE_LEN MODE_H_ACTIVE_PIXELS #define RBUF_SLICE_LEN MODE_H_ACTIVE_PIXELS
#define RBUF_MAX_DATA_LEN (RBUF_SLICE_LEN - NUM_RESERVED_WORDS) #define RBUF_MAX_DATA_LEN (RBUF_SLICE_LEN - NUM_RESERVED_WORDS)
#define RBUF_TOTAL_LEN (RBUF_SLICE_LEN * RBUF_SLICES) #define RBUF_DEFAULT_TOTAL_LEN (RBUF_SLICE_LEN * RBUF_DEFAULT_SLICES)
#define MAX_STREAMS 8 #define MAX_STREAMS 4
enum crc_config { enum crc_config {
CRC_NONE, /* No CRC, just 16 bit idle counter */ CRC_NONE, /* No CRC, just 16 bit idle counter */
@ -51,6 +51,6 @@ typedef struct
void hsdaoh_start(void); void hsdaoh_start(void);
void hsdaoh_init(int dstrength, int slewrate); void hsdaoh_init(int dstrength, int slewrate);
void hsdaoh_update_head(int stream_id, int head); void hsdaoh_update_head(int stream_id, int head);
int hsdaoh_add_stream(uint16_t stream_id, uint16_t format, uint32_t samplerate, uint length, uint16_t *ringbuf); int hsdaoh_add_stream(uint16_t stream_id, uint16_t format, uint32_t samplerate, uint length, uint slices, uint16_t *ringbuf);
#endif #endif