mirror of
				https://github.com/hyperion-project/hyperion.ng.git
				synced 2025-03-01 10:33:28 +00:00 
			
		
		
		
	Assembler version 1: use roll and bit clear instructions
Former-commit-id: 4f27d34dd63c635a65ee33f2c368978d5b162974
This commit is contained in:
		| @@ -260,6 +260,31 @@ LedDeviceWS2812b::LedDeviceWS2812b() : | |||||||
| 	printf("WS2812b init finished \n"); | 	printf("WS2812b init finished \n"); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifdef WS2812_ASM_OPTI | ||||||
|  |  | ||||||
|  | // rotate register, used to move the 1 around :-) | ||||||
|  | static inline __attribute__((always_inline)) | ||||||
|  | uint32_t arm_ror_imm(uint32_t v, uint32_t sh) { | ||||||
|  |   uint32_t d; | ||||||
|  |   asm ("ROR %[Rd], %[Rm], %[Is]" : [Rd] "=r" (d) : [Rm] "r" (v), [Is] "i" (sh)); | ||||||
|  |   return d; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline __attribute__((always_inline)) | ||||||
|  | uint32_t arm_ror(uint32_t v, uint32_t sh) { | ||||||
|  |   uint32_t d; | ||||||
|  |   asm ("ROR %[Rd], %[Rm], %[Rs]" : [Rd] "=r" (d) : [Rm] "r" (v), [Rs] "r" (sh)); | ||||||
|  |   return d; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static inline __attribute__((always_inline)) | ||||||
|  | uint32_t arm_Bit_Clear_imm(uint32_t v, uint32_t v2) { | ||||||
|  |   uint32_t d; | ||||||
|  |   asm ("BIC %[Rd], %[Rm], %[Rs]" : [Rd] "=r" (d) : [Rm] "r" (v), [Rs] "r" (v2)); | ||||||
|  |   return d; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues) | int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues) | ||||||
| { | { | ||||||
| @@ -295,6 +320,9 @@ int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues) | |||||||
| 		//mLedCount = (NUM_DATA_WORDS - 1) / 2.25; | 		//mLedCount = (NUM_DATA_WORDS - 1) / 2.25; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | #ifdef WS2812_ASM_OPTI | ||||||
|  | 	unsigned int startbitPattern = 0x40000000; // = 0100 0000  0000 0000  0000 0000  0000 0000 pattern | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| 	for(size_t i=0; i<mLedCount; i++) { | 	for(size_t i=0; i<mLedCount; i++) { | ||||||
| @@ -306,10 +334,26 @@ int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues) | |||||||
|  |  | ||||||
| 		// Iterate through color bits to get wire bits | 		// Iterate through color bits to get wire bits | ||||||
| 		for(int j=23; j>=0; j--) { | 		for(int j=23; j>=0; j--) { | ||||||
| 			unsigned char colorBit = (colorBits & (1 << j)) ? 1 : 0; // Holds current bit out of colorBits to be processed | #ifdef WS2812_ASM_OPTI | ||||||
|  | 			// Fetch word the bit is in | ||||||
|  | 				unsigned int wordOffset = (int)(wireBit / 32); | ||||||
|  | 				wireBit +=3; | ||||||
|  |  | ||||||
|  | //				printBinary(startbitPattern, 32); | ||||||
|  | //				printf(" %d\n", j); | ||||||
|  | 				if (colorBits & (1 << j)) { | ||||||
|  | 						PWMWaveform[wordOffset] |= startbitPattern; | ||||||
|  | 				} else { | ||||||
|  | 						PWMWaveform[wordOffset] = arm_Bit_Clear_imm(PWMWaveform[wordOffset], startbitPattern); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				startbitPattern = arm_ror_imm(startbitPattern, 3); | ||||||
|  |  | ||||||
|  | #else | ||||||
|  | 			unsigned char colorBit = (colorBits & (1 << j)) ? 1 : 0; // Holds current bit out of colorBits to be processed | ||||||
| 			setPWMBit(wireBit, colorBit); | 			setPWMBit(wireBit, colorBit); | ||||||
| 			wireBit +=3; | 			wireBit +=3; | ||||||
|  | #endif | ||||||
| 			/* old code for better understanding | 			/* old code for better understanding | ||||||
| 			switch(colorBit) { | 			switch(colorBit) { | ||||||
| 				case 1: | 				case 1: | ||||||
| @@ -328,6 +372,11 @@ int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | #ifdef WS2812_ASM_OPTI | ||||||
|  | 	// calculate the bits manually since it is not needed with asm | ||||||
|  | 	//wireBit += mLedCount * 24 *3; | ||||||
|  | 	//printf(" %d\n", wireBit); | ||||||
|  | #endif | ||||||
| 	//remove one to undo optimization | 	//remove one to undo optimization | ||||||
| 	wireBit --; | 	wireBit --; | ||||||
|  |  | ||||||
| @@ -344,6 +393,8 @@ int LedDeviceWS2812b::write(const std::vector<ColorRgb> &ledValues) | |||||||
| 		wireBit += 3; | 		wireBit += 3; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | //	printBinary(PWMWaveform[(int)(oldwireBitValue / 32) -1 ], 32); | ||||||
|  | //		printf(" post\n"); | ||||||
| //	printBinary(PWMWaveform[(int)(oldwireBitValue / 32)], 32); | //	printBinary(PWMWaveform[(int)(oldwireBitValue / 32)], 32); | ||||||
| //		printf(" post\n"); | //		printf(" post\n"); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -102,6 +102,7 @@ | |||||||
| #include <leddevice/LedDevice.h> | #include <leddevice/LedDevice.h> | ||||||
|  |  | ||||||
| #define BENCHMARK | #define BENCHMARK | ||||||
|  | #define WS2812_ASM_OPTI | ||||||
|  |  | ||||||
| // The page map contains pointers to memory that we will allocate below. It uses two pointers | // The page map contains pointers to memory that we will allocate below. It uses two pointers | ||||||
| // per address. This is because the software (this program) deals only in virtual addresses, | // per address. This is because the software (this program) deals only in virtual addresses, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user