16
16
#include "dmd_interface_spike.pio.h"
17
17
#include "dmd_interface_sam.pio.h"
18
18
19
+ // should CRC32 checksum be caculated and sent with each frame
20
+ #define USE_CRC
21
+
22
+ // supress duplicate frames (implies USE_CRC)
23
+ #define SUPRESS_DUPLICATES
24
+
25
+
19
26
/**
20
27
* Glossary
21
28
*
31
38
#define LED1_PIN 27
32
39
#define LED2_PIN 28
33
40
41
+ #ifdef SUPRESS_DUPLICATES
42
+ #define USE_CRC
43
+ #endif
44
+
34
45
typedef struct buf32_t
35
46
{
36
47
uint8_t byte0 ;
@@ -41,14 +52,16 @@ typedef struct buf32_t
41
52
42
53
// SPI data types and header blocks
43
54
// header block length should always be a multiple of 32bit
44
- #define SPI_BLOCK_PIX 0xcc33
55
+ #define SPI_BLOCK_PIX 0xcc33 // DMD frame
56
+ #define SPI_BLOCK_PIX_CRC 0x44ee // DMD frame with CRC32 checksum
45
57
46
58
typedef struct __attribute__((__packed__ )) block_header_t
47
59
{
48
60
uint16_t block_type ; // block type
49
61
uint16_t len ; // length of the whole data including header in bytes
50
62
} block_header_t ;
51
63
64
+
52
65
typedef struct __attribute__((__packed__ )) block_pix_header_t
53
66
{
54
67
uint16_t columns ; // number of columns
@@ -57,6 +70,16 @@ typedef struct __attribute__((__packed__)) block_pix_header_t
57
70
uint16_t padding ;
58
71
} block_pix_header_t ;
59
72
73
+ typedef struct __attribute__((__packed__ )) block_pix_crc_header_t
74
+ {
75
+ uint16_t columns ; // number of columns
76
+ uint16_t rows ; // number of rows
77
+ uint16_t bitsperpixel ; // bits per pixel
78
+ uint16_t padding ;
79
+ uint32_t crc32 ; // crc32 of the pixel data
80
+ } block_pix_crc_header_t ;
81
+
82
+
60
83
// SPI Defines
61
84
#define SPI0 spi0
62
85
#define SPI_BASE 16
@@ -88,7 +111,6 @@ typedef struct __attribute__((__packed__)) block_pix_header_t
88
111
#define MAX_PLANESPERFRAME 4
89
112
#define MAX_MEMORY_OVERHEAD 4 // reserve additional memory in framebuf for line oversampling
90
113
91
-
92
114
uint16_t lcd_width ;
93
115
uint16_t lcd_height ;
94
116
uint16_t lcd_bitsperpixel ;
@@ -111,8 +133,11 @@ uint8_t *lastplane = planebuf2;
111
133
112
134
// processed frames (merged planes)
113
135
uint8_t framebuf1 [MAX_WIDTH * MAX_HEIGHT * MAX_BITSPERPIXEL / 8 * MAX_MEMORY_OVERHEAD ];
114
- uint8_t framebuf2 [MAX_WIDTH * MAX_HEIGHT * MAX_BITSPERPIXEL / 8 * MAX_MEMORY_OVERHEAD ] ;
136
+ uint8_t framebuf2 [MAX_WIDTH * MAX_HEIGHT * MAX_BITSPERPIXEL / 8 * MAX_MEMORY_OVERHEAD ];
137
+ uint32_t crc1 ;
138
+ uint32_t crc2 ;
115
139
uint8_t * lastframe = framebuf1 ;
140
+ uint32_t * lastcrc ;
116
141
117
142
uint32_t stat_frames_received = 0 ;
118
143
uint32_t stat_spi_skipped = 0 ;
@@ -250,17 +275,28 @@ void spi_notify_onoff(int count) {
250
275
*
251
276
* @param pixbuf a frame to send
252
277
*/
253
- bool spi_send_pix (uint8_t * pixbuf , bool skip_when_busy )
278
+ bool spi_send_pix (uint8_t * pixbuf , uint32_t crc32 , bool skip_when_busy )
254
279
{
280
+
281
+ #ifdef USE_CRC
282
+ block_header_t h = {
283
+ .block_type = SPI_BLOCK_PIX_CRC };
284
+ block_pix_crc_header_t ph = {};
285
+ #else
255
286
block_header_t h = {
256
287
.block_type = SPI_BLOCK_PIX };
257
288
block_pix_header_t ph = {};
289
+ #endif
258
290
259
291
// round length to 4-byte blocks
260
292
h .len = (((lcd_bytes + 3 ) / 4 ) * 4 ) + sizeof (h ) + sizeof (ph );
261
293
ph .columns = lcd_width ;
262
294
ph .rows = lcd_height ;
263
295
ph .bitsperpixel = lcd_bitsperpixel ;
296
+ #ifdef USE_CRC
297
+ ph .crc32 = crc32 ;
298
+ #endif
299
+
264
300
265
301
if (skip_when_busy ) {
266
302
if (spi_busy ()) return false;
@@ -358,17 +394,22 @@ void spi_dma_handler() {
358
394
void dmd_dma_handler () {
359
395
360
396
uint8_t * target ;
397
+ uint32_t * targetcrc ;
361
398
uint32_t * planebuf ;
362
399
363
400
// Switch between buffers
364
401
if (lastplane == planebuf1 ) {
365
402
target = planebuf1 ;
366
403
lastplane = planebuf2 ;
367
404
lastframe = framebuf2 ;
405
+ lastcrc = & crc2 ;
406
+ targetcrc = & crc1 ;
368
407
} else {
369
408
target = planebuf2 ;
370
409
lastplane = planebuf1 ;
371
410
lastframe = framebuf1 ;
411
+ lastcrc = & crc1 ;
412
+ targetcrc = & crc2 ;
372
413
}
373
414
374
415
// Clear the interrupt request
@@ -455,6 +496,9 @@ void dmd_dma_handler() {
455
496
dst += lcd_wordsperline ; // destination skips only one line
456
497
}
457
498
}
499
+ #ifdef USE_CRC
500
+ * lastcrc = crc32 (0 ,(const uint8_t * ) framebuf , lcd_bytes );
501
+ #endif
458
502
459
503
frame_received = true;
460
504
}
@@ -644,6 +688,7 @@ bool init()
644
688
645
689
int main ()
646
690
{
691
+ uint32_t crc_previous_frame = 0 ;
647
692
if (!init ()) {
648
693
printf ("Error during initialisation, aborting...\n" );
649
694
return 0 ;
@@ -655,7 +700,15 @@ int main()
655
700
frame_received = false;
656
701
657
702
// do something
658
- spi_send_pix (lastframe ,true);
703
+ #ifdef SUPRESS_DUPLICATES
704
+ if (* lastcrc != crc_previous_frame ) {
705
+ spi_send_pix (lastframe , * lastcrc , true);
706
+ crc_previous_frame = * lastcrc ;
707
+ }
708
+ #else
709
+ spi_send_pix (lastframe , * lastcrc , true);
710
+ #endif
711
+
659
712
}
660
713
661
714
return 0 ;
0 commit comments