Commit | Line | Data |
---|---|---|
5fc23db2 JM |
1 | #include <stdint.h> |
2 | #include <stdbool.h> | |
3 | ||
4 | #include "user.h" | |
5 | ||
6 | #include "ws2811.h" | |
7 | ||
8 | /* this holds the G R B bytes for the entire string */ | |
9 | unsigned char rgbdata[RGB_COUNT]; | |
10 | ||
11 | ||
12 | /* These values are placed in common memory so that they can be accessed | |
13 | * quickly without a bank switch by the routines below, THIS IS IMPORTANT, | |
14 | * it will not run properly without it */ | |
15 | volatile uint8_t rgb_sample @ 0x7B; | |
16 | volatile uint8_t rgb_byte @ 0x7C; | |
17 | volatile uint8_t rgb_bit @ 0x7D; | |
18 | ||
19 | // send the whole pile of data | |
20 | static void ws2811_send(void) | |
21 | { | |
22 | #asm | |
23 | // copy the led colour array location into FSR0 for fast access | |
24 | MOVLW HIGH _rgbdata | |
25 | MOVWF FSR0H | |
26 | MOVLW LOW _rgbdata | |
27 | MOVWF FSR0L | |
28 | ||
29 | // load next byte from array into working reg | |
30 | ws2811_nextbyte: | |
31 | MOVIW FSR0++ | |
32 | MOVWF _rgb_sample | |
33 | MOVLW 8 // reset bit count | |
34 | MOVWF _rgb_bit | |
35 | ||
36 | ws2811_sendbit: | |
37 | // you assume its a zero then test if its one | |
38 | // MOVLW 0xC0 ;11000000B | |
39 | MOVLW 0x80 ;10000000B | |
40 | ||
41 | RLF _rgb_sample,f | |
42 | BTFSC STATUS,0 // CARRY | |
43 | //asm("MOVLW 0xF8 "); // 11111000B | |
44 | MOVLW 0xF0 // 11110000B | |
45 | ||
46 | BANKSEL (SSP1BUF) | |
47 | MOVWF BANKMASK(SSP1BUF) | |
48 | ||
49 | // any more bits | |
50 | DECFSZ _rgb_bit,f | |
51 | BRA ws2811_delay | |
52 | ||
53 | // any more bytes | |
54 | DECFSZ _rgb_byte,f | |
55 | BRA ws2811_nextbyte | |
56 | BRA ws2811_end | |
57 | ||
58 | ws2811_delay: | |
59 | NOP | |
60 | NOP | |
61 | NOP | |
62 | BRA ws2811_sendbit | |
63 | ||
64 | ws2811_end: | |
65 | ||
66 | ||
67 | #endasm | |
68 | ||
69 | // all done | |
70 | } | |
71 | ||
72 | #if _XTAL_FREQ != 32000000L | |
73 | #error "This code requires 32MHz system clock or above" | |
74 | #endif | |
75 | ||
76 | void ws2811_init(void) | |
77 | { | |
78 | // SPI is on RA0 | |
79 | TRISAbits.TRISA0 = 0; // SDO is RA0 | |
80 | ANSELAbits.ANSA0 = 0; // not analog | |
81 | ||
82 | // SCK (SPI Clock) is RA1 | |
83 | // SDI (SPI In) is RA2 | |
84 | APFCONbits.SDOSEL = 0; // use RA0 not RA4 for output | |
85 | ||
86 | // at 8MHz Tclk 0 = 2 bits, 1 = 6 bits. | |
87 | // write to SSP1BUF | |
88 | SSP1CON1bits.SSPM = 0b0000; // SPI Master Fosc/4 | |
89 | SSP1CON1bits.SSPEN = 1; // enable MSSP | |
90 | } | |
91 | ||
92 | void ws2811_transmit(void) | |
93 | { | |
94 | rgb_byte = RGB_COUNT; | |
95 | ws2811_send(); // send the first bit | |
96 | } |