Skip to content
This repository was archived by the owner on May 6, 2021. It is now read-only.

Commit 4f27d34

Browse files
committed
Assembler version 1: use roll and bit clear instructions
1 parent 08dc5ee commit 4f27d34

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

libsrc/leddevice/LedDeviceWS2812b.cpp

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,31 @@ LedDeviceWS2812b::LedDeviceWS2812b() :
260260
printf("WS2812b init finished \n");
261261
}
262262

263+
#ifdef WS2812_ASM_OPTI
264+
265+
// rotate register, used to move the 1 around :-)
266+
static inline __attribute__((always_inline))
267+
uint32_t arm_ror_imm(uint32_t v, uint32_t sh) {
268+
uint32_t d;
269+
asm ("ROR %[Rd], %[Rm], %[Is]" : [Rd] "=r" (d) : [Rm] "r" (v), [Is] "i" (sh));
270+
return d;
271+
}
272+
273+
static inline __attribute__((always_inline))
274+
uint32_t arm_ror(uint32_t v, uint32_t sh) {
275+
uint32_t d;
276+
asm ("ROR %[Rd], %[Rm], %[Rs]" : [Rd] "=r" (d) : [Rm] "r" (v), [Rs] "r" (sh));
277+
return d;
278+
}
279+
280+
281+
static inline __attribute__((always_inline))
282+
uint32_t arm_Bit_Clear_imm(uint32_t v, uint32_t v2) {
283+
uint32_t d;
284+
asm ("BIC %[Rd], %[Rm], %[Rs]" : [Rd] "=r" (d) : [Rm] "r" (v), [Rs] "r" (v2));
285+
return d;
286+
}
287+
#endif
263288

264289
int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues)
265290
{
@@ -295,6 +320,9 @@ int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues)
295320
//mLedCount = (NUM_DATA_WORDS - 1) / 2.25;
296321
}
297322

323+
#ifdef WS2812_ASM_OPTI
324+
unsigned int startbitPattern = 0x40000000; // = 0100 0000 0000 0000 0000 0000 0000 0000 pattern
325+
#endif
298326

299327

300328
for(size_t i=0; i<mLedCount; i++) {
@@ -306,10 +334,26 @@ int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues)
306334

307335
// Iterate through color bits to get wire bits
308336
for(int j=23; j>=0; j--) {
337+
#ifdef WS2812_ASM_OPTI
338+
// Fetch word the bit is in
339+
unsigned int wordOffset = (int)(wireBit / 32);
340+
wireBit +=3;
341+
342+
// printBinary(startbitPattern, 32);
343+
// printf(" %d\n", j);
344+
if (colorBits & (1 << j)) {
345+
PWMWaveform[wordOffset] |= startbitPattern;
346+
} else {
347+
PWMWaveform[wordOffset] = arm_Bit_Clear_imm(PWMWaveform[wordOffset], startbitPattern);
348+
}
349+
350+
startbitPattern = arm_ror_imm(startbitPattern, 3);
351+
352+
#else
309353
unsigned char colorBit = (colorBits & (1 << j)) ? 1 : 0; // Holds current bit out of colorBits to be processed
310-
311354
setPWMBit(wireBit, colorBit);
312355
wireBit +=3;
356+
#endif
313357
/* old code for better understanding
314358
switch(colorBit) {
315359
case 1:
@@ -328,6 +372,11 @@ int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues)
328372
}
329373
}
330374

375+
#ifdef WS2812_ASM_OPTI
376+
// calculate the bits manually since it is not needed with asm
377+
//wireBit += mLedCount * 24 *3;
378+
//printf(" %d\n", wireBit);
379+
#endif
331380
//remove one to undo optimization
332381
wireBit --;
333382

@@ -344,6 +393,8 @@ int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues)
344393
wireBit += 3;
345394
}
346395

396+
// printBinary(PWMWaveform[(int)(oldwireBitValue / 32) -1 ], 32);
397+
// printf(" post\n");
347398
// printBinary(PWMWaveform[(int)(oldwireBitValue / 32)], 32);
348399
// printf(" post\n");
349400

libsrc/leddevice/LedDeviceWS2812b.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
#include <leddevice/LedDevice.h>
103103

104104
#define BENCHMARK
105+
#define WS2812_ASM_OPTI
105106

106107
// The page map contains pointers to memory that we will allocate below. It uses two pointers
107108
// per address. This is because the software (this program) deals only in virtual addresses,

0 commit comments

Comments
 (0)