#include #include #include "user.h" #include "ws2811.h" /* this holds the G R B bytes for the entire string */ unsigned char rgbdata[RGB_COUNT]; /* These values are placed in common memory so that they can be accessed * quickly without a bank switch by the routines below, THIS IS IMPORTANT, * it will not run properly without it */ volatile uint8_t rgb_sample @ 0x7B; volatile uint8_t rgb_byte @ 0x7C; volatile uint8_t rgb_bit @ 0x7D; // send the whole pile of data static void ws2811_send(void) { #asm // copy the led colour array location into FSR0 for fast access MOVLW HIGH _rgbdata MOVWF FSR0H MOVLW LOW _rgbdata MOVWF FSR0L // load next byte from array into working reg ws2811_nextbyte: MOVIW FSR0++ MOVWF _rgb_sample MOVLW 8 // reset bit count MOVWF _rgb_bit ws2811_sendbit: // you assume its a zero then test if its one // MOVLW 0xC0 ;11000000B MOVLW 0x80 ;10000000B RLF _rgb_sample,f BTFSC STATUS,0 // CARRY //asm("MOVLW 0xF8 "); // 11111000B MOVLW 0xF0 // 11110000B BANKSEL (SSP1BUF) MOVWF BANKMASK(SSP1BUF) // any more bits DECFSZ _rgb_bit,f BRA ws2811_delay // any more bytes DECFSZ _rgb_byte,f BRA ws2811_nextbyte BRA ws2811_end ws2811_delay: NOP NOP NOP BRA ws2811_sendbit ws2811_end: #endasm // all done } #if _XTAL_FREQ != 32000000L #error "This code requires 32MHz system clock or above" #endif void ws2811_init(void) { // SPI is on RA0 TRISAbits.TRISA0 = 0; // SDO is RA0 ANSELAbits.ANSA0 = 0; // not analog // SCK (SPI Clock) is RA1 // SDI (SPI In) is RA2 APFCONbits.SDOSEL = 0; // use RA0 not RA4 for output // at 8MHz Tclk 0 = 2 bits, 1 = 6 bits. // write to SSP1BUF SSP1CON1bits.SSPM = 0b0000; // SPI Master Fosc/4 SSP1CON1bits.SSPEN = 1; // enable MSSP } void ws2811_transmit(void) { rgb_byte = RGB_COUNT; ws2811_send(); // send the first bit }