Skip to content

Commit fc5034b

Browse files
committed
Implemented CRC32 and duplicate frame suppression
1 parent e0859b2 commit fc5034b

File tree

1 file changed

+58
-5
lines changed

1 file changed

+58
-5
lines changed

src/dmdreader.c

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616
#include "dmd_interface_spike.pio.h"
1717
#include "dmd_interface_sam.pio.h"
1818

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+
1926
/**
2027
* Glossary
2128
*
@@ -31,6 +38,10 @@
3138
#define LED1_PIN 27
3239
#define LED2_PIN 28
3340

41+
#ifdef SUPRESS_DUPLICATES
42+
#define USE_CRC
43+
#endif
44+
3445
typedef struct buf32_t
3546
{
3647
uint8_t byte0;
@@ -41,14 +52,16 @@ typedef struct buf32_t
4152

4253
// SPI data types and header blocks
4354
// 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
4557

4658
typedef struct __attribute__((__packed__)) block_header_t
4759
{
4860
uint16_t block_type; // block type
4961
uint16_t len; // length of the whole data including header in bytes
5062
} block_header_t;
5163

64+
5265
typedef struct __attribute__((__packed__)) block_pix_header_t
5366
{
5467
uint16_t columns; // number of columns
@@ -57,6 +70,16 @@ typedef struct __attribute__((__packed__)) block_pix_header_t
5770
uint16_t padding;
5871
} block_pix_header_t;
5972

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+
6083
// SPI Defines
6184
#define SPI0 spi0
6285
#define SPI_BASE 16
@@ -88,7 +111,6 @@ typedef struct __attribute__((__packed__)) block_pix_header_t
88111
#define MAX_PLANESPERFRAME 4
89112
#define MAX_MEMORY_OVERHEAD 4 // reserve additional memory in framebuf for line oversampling
90113

91-
92114
uint16_t lcd_width;
93115
uint16_t lcd_height;
94116
uint16_t lcd_bitsperpixel;
@@ -111,8 +133,11 @@ uint8_t *lastplane = planebuf2;
111133

112134
// processed frames (merged planes)
113135
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;
115139
uint8_t* lastframe = framebuf1;
140+
uint32_t* lastcrc;
116141

117142
uint32_t stat_frames_received=0;
118143
uint32_t stat_spi_skipped=0;
@@ -250,17 +275,28 @@ void spi_notify_onoff(int count) {
250275
*
251276
* @param pixbuf a frame to send
252277
*/
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)
254279
{
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
255286
block_header_t h = {
256287
.block_type = SPI_BLOCK_PIX};
257288
block_pix_header_t ph = {};
289+
#endif
258290

259291
// round length to 4-byte blocks
260292
h.len = (((lcd_bytes + 3) / 4) * 4) + sizeof(h) + sizeof(ph);
261293
ph.columns = lcd_width;
262294
ph.rows = lcd_height;
263295
ph.bitsperpixel = lcd_bitsperpixel;
296+
#ifdef USE_CRC
297+
ph.crc32 = crc32;
298+
#endif
299+
264300

265301
if (skip_when_busy) {
266302
if (spi_busy()) return false;
@@ -358,17 +394,22 @@ void spi_dma_handler() {
358394
void dmd_dma_handler() {
359395

360396
uint8_t *target;
397+
uint32_t *targetcrc;
361398
uint32_t *planebuf;
362399

363400
// Switch between buffers
364401
if (lastplane == planebuf1) {
365402
target = planebuf1;
366403
lastplane = planebuf2;
367404
lastframe = framebuf2;
405+
lastcrc = &crc2;
406+
targetcrc = &crc1;
368407
} else {
369408
target = planebuf2;
370409
lastplane = planebuf1;
371410
lastframe = framebuf1;
411+
lastcrc = &crc1;
412+
targetcrc = &crc2;
372413
}
373414

374415
// Clear the interrupt request
@@ -455,6 +496,9 @@ void dmd_dma_handler() {
455496
dst += lcd_wordsperline; // destination skips only one line
456497
}
457498
}
499+
#ifdef USE_CRC
500+
*lastcrc = crc32(0,(const uint8_t*) framebuf, lcd_bytes);
501+
#endif
458502

459503
frame_received=true;
460504
}
@@ -644,6 +688,7 @@ bool init()
644688

645689
int main()
646690
{
691+
uint32_t crc_previous_frame = 0;
647692
if (!init()) {
648693
printf("Error during initialisation, aborting...\n");
649694
return 0;
@@ -655,7 +700,15 @@ int main()
655700
frame_received=false;
656701

657702
// 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+
659712
}
660713

661714
return 0;

0 commit comments

Comments
 (0)