Skip to content

Commit 211e0aa

Browse files
MichaelBellGadgetoid
authored andcommitted
DV Display: Fix unaligned read across page boundary
1 parent b8116fc commit 211e0aa

File tree

3 files changed

+30
-9
lines changed

3 files changed

+30
-9
lines changed

drivers/aps6404/aps6404.cpp

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,9 @@ namespace pimoroni {
192192
void APS6404::read(uint32_t addr, uint32_t* read_buf, uint32_t len_in_words) {
193193
start_read(read_buf, len_in_words);
194194

195-
uint32_t first_page_len = (PAGE_SIZE - (addr & (PAGE_SIZE - 1))) >> 2;
195+
uint32_t first_page_len = (PAGE_SIZE - (addr & (PAGE_SIZE - 1)));
196196

197-
if (first_page_len >= len_in_words) {
197+
if (first_page_len >= len_in_words << 2) {
198198
pio_sm_put_blocking(pio, pio_sm, (len_in_words * 8) - 4);
199199
pio_sm_put_blocking(pio, pio_sm, 0xeb000000u | addr);
200200
pio_sm_put_blocking(pio, pio_sm, pio_offset + sram_offset_do_read);
@@ -261,19 +261,33 @@ namespace pimoroni {
261261
}
262262

263263
uint32_t* APS6404::add_read_to_cmd_buffer(uint32_t* cmd_buf, uint32_t addr, uint32_t len_in_words) {
264-
uint32_t len = (PAGE_SIZE - (addr & (PAGE_SIZE - 1))) >> 2;
264+
int32_t len_remaining = len_in_words << 2;
265+
uint32_t len = std::min((PAGE_SIZE - (addr & (PAGE_SIZE - 1))), (uint32_t)len_remaining);
266+
bool clear_isr = false;
265267

266268
while (true) {
267-
*cmd_buf++ = (len * 8) - 4;
269+
if (len < 2) {
270+
// This is guaranteed to leave at least one byte in the ISR,
271+
// which we then clear with an additional command
272+
len = 2;
273+
clear_isr = true;
274+
}
275+
*cmd_buf++ = (len * 2) - 4;
268276
*cmd_buf++ = 0xeb000000u | addr;
269277
*cmd_buf++ = pio_offset + sram_offset_do_read;
270-
len_in_words -= len;
271-
addr += len << 2;
278+
len_remaining -= len;
279+
addr += len;
272280

273-
if (len_in_words == 0) break;
281+
if (len_remaining <= 0) break;
274282

275-
len = len_in_words;
276-
if (len > (PAGE_SIZE >> 2)) len = PAGE_SIZE >> 2;
283+
len = len_remaining;
284+
if (len > PAGE_SIZE) len = PAGE_SIZE;
285+
}
286+
287+
if (clear_isr) {
288+
*cmd_buf++ = 0;
289+
*cmd_buf++ = 0xeb000000u | addr;
290+
*cmd_buf++ = pio_offset + sram_offset_do_clear;
277291
}
278292

279293
return cmd_buf;

drivers/aps6404/aps6404.pio

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ PUBLIC do_write:
3434
jmp y--, do_write side 0b10
3535
set pindirs, 0 side 0b00
3636
out null, 32 side 0b01
37+
PUBLIC do_clear:
38+
mov isr, null side 0b01
3739
jmp top side 0b01
3840

3941
; Read command
@@ -76,6 +78,8 @@ PUBLIC do_write:
7678
jmp y--, do_write side 0b10
7779
set pindirs, 0 side 0b00
7880
out null, 32 side 0b01
81+
PUBLIC do_clear:
82+
mov isr, null side 0b01
7983
jmp top side 0b01
8084

8185
; Read command
@@ -121,6 +125,8 @@ PUBLIC do_write:
121125
jmp y--, do_write [1] side 0b10
122126
set pindirs, 0 side 0b00
123127
out null, 32 side 0b01
128+
PUBLIC do_clear:
129+
mov isr, null side 0b01
124130
jmp top side 0b01
125131

126132
; Read command

drivers/dv_display/dv_display.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ namespace pimoroni {
378378
ram.write(point_to_address_palette(p), &val, 1);
379379
--l;
380380
offset++;
381+
ram.wait_for_finish_blocking();
381382
}
382383
if (l > 0) {
383384
ram.write(point_to_address_palette(p) + offset, (uint32_t*)data, l);

0 commit comments

Comments
 (0)