CircuitGizmos

Electronic Products for Creative Minds

  • Home
  • Gizmo Store/Products
  • Documentation/Datasheets
  • Projects/Libraries
  • GizmoBlog
  • Services/Contact
    • Design
    • Contact Gizmo!
  • Your Gizmo Cart
    • Your Account
You are here: Home / Projects / MicroBoard MicroMite Projects / Neopixel: WS2812 RGB LED

Neopixel: WS2812 RGB LED

2015-02-10_190713_P1050013

This code is a bit of example code for WS2812 RGB LEDs.

Project by Peter Mather.

I was able to properly test the code for sending out the pulse sequences. The attached code contains a simple example that fades in and out the colours and rotates them around the ring – I wish I had some artistic flair but that will have to do as an example!

The code should be able to handle any number of WS2812 LEDs in the string – power supply and cost will be the limiting factors. The Cfunction code is included as comments.

The WS2812.init routine sets the CPU speed to 48, the Cfunction will only operate correctly at this speed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
OPTION DEFAULT NONE
OPTION EXPLICIT
'
' Function and subroutine calls
'
' WS2812.pulses: number of LEDs, PIC port numer (0=A..2=C), Pin number within the port, array of colour codes, buffer array used by the CFunction
' sub WS2812.pulses(numleds as integer, portnum as integer, pinnum as integer, colours() as integer, buffer() as integer)
'
' WS2812.getcolour: Get the green, red, and blue components for a specific LED from the colour array
' sub WS2812.getcolour(led as integer, greenness as integer, redness as integer, blueness as integer)
'
' WS2812.setcolour: Load the colour array for a specific LED from the green, red, and blue components
' sub WS2812.setcolour(led as integer, greenness as integer, redness as integer, blueness as integer)
'
' WS2812.INIT: set the pin to use for output to the LEDs and the number of LEDs in the string and sets up the required global variables and CPU speed
' SUB WS2812.INIT(LED_PIN as integer,NUMLEDS as INTEGER)
'
' WS2812.getpin: uses the pin number to get the port number and the pin number on the port by reference to the Device ID; returns true if a valid pin, false otherwise
' function WS2812.getpin(MMpin as integer,portnum as integer,pinnum as integer) as integer
 
WS2812.INIT(16,7) 'set the pin for output and the number of LEDs
'
EXAMPLE 'execute the example program
'
end
 '___________________________________________________________ ____________________________________________________________ _______________
'
'number of LEDs, PIC port numer (0=A..2=C), Pin number within the port, array of colour codes, buffer array used by the CFunction
'
CFunction WS2812.Pulses
     00000000
     8fa30010 24020001 8ccc0000 01826004 8ca60000 14c20003 8ca50004 10a00009 
     3c0ebf88 24020002 14c20003 3c0ebf88 50a00007 25cd6234 25cd6034 10000005 
     25ce6038 25cd6134 10000002 25ce6138 25ce6238 34058000 3c02bf80 ac450600 
     8c820004 1c400005 8c880000 14400025 00000000 11000023 00000000 0060c021 
     00007821 1000001c 240bffff 30490020 8ce80004 00085040 00022827 00aa5004 
     8ce50000 00452806 01452825 00484007 0109280b 30a50001 a0c50000 2442ffff 
     144bfff2 24c60001 25ef0001 8c880000 8c820004 27180018 000f2fc3 00a2302a 
     14c00005 24e70008 14450006 01e8482b 11200004 00000000 03003021 1000ffe3 
     24020017 5c400006 3c02bf80 1440000b 3c05bf80 2d08001d 15000008 3c02bf80 
     8c460c00 3c05ffff 24a57fff 00c52824 ac450c00 10000006 8c820000 8ca20c10 
     2c420065 1040fffd 00000000 8c820000 000228c0 00021140 00453823 10e00025 
     00001021 3c05bf80 00623021 90c60000 10c0000f 00000000 adcc0000 aca00610 
     8ca60610 2cc60019 14c0fffd 00000000 adac0000 aca00610 8ca60610 2cc6000d 
     14c0fffd 00000000 1000000e 24420001 adcc0000 aca00610 8ca60610 2cc60005 
     14c0fffd 00000000 adac0000 aca00610 8ca60610 2cc60014 14c0fffd 00000000 
     24420001 1447ffe1 00623021 10000003 8c830004 00e01021 8c830004 5c600008 
     3c03bf80 14600009 00000000 8c830000 2c63001d 14600005 00000000 3c03bf80 
     8c640c00 34848000 ac640c00 adac0000 03e00008 00001821 
End CFunction
 
'
'long long WS2812.Pulses(long long *numleds, long long *portname,long long *mypin,long long parray[], unsigned char sarray[]){
'  #define tmr4 *(volatile unsigned int *)0xbf800C10 //timer 1 configuration register
'  #define tmr4con *(volatile unsigned int *)0xbf800C00 //timer 1 configuration register
'  #define tmr1con *(volatile unsigned int *)0xbf800600 //timer 1 configuration register
'  #define tmr1 *(volatile unsigned int *)0xbf800610 //timer 1 counter
'  unsigned int index,pin=1<<*mypin;
'  int k,bpos;
'  unsigned int volatile * mysetport;
'  unsigned int volatile * myclearport;
'  if(*portname==0) {
'      mysetport=(volatile unsigned int *)0xbf886038;
'      myclearport=(volatile unsigned int *)0xbf886034;
'  }
'  if(*portname==1) {
'      mysetport=(volatile unsigned int *)0xbf886138;
'      myclearport=(volatile unsigned int *)0xbf886134;
'  }
'  if(*portname==2) {
'      mysetport=(volatile unsigned int *)0xbf886238;
'      myclearport=(volatile unsigned int *)0xbf886234;
'  }
'  tmr1con=0x8000; //turn on timer at full speed
'  index=0;
'  for(k=0;k<*numleds;k++){ //move the data into a single dimensional array that we can step though in even time
'      for(bpos=23;bpos>=0;bpos--){
'         sarray[index]=(parray[k]>>bpos) & 1;
'         index++;
'     }
'  }
'  if(*numleds > 28) { //Decide how to avoid RTC interrupts
'      tmr4con &= 0xFFFF7FFF; //turn off the real time clock if it is going to interfere
'  } else {
'      while(tmr4>100); //synchronise with the RTC to avoid interrupts
'  }
'  k=*numleds * 24;; //get the number of bytes to output
'  for (index=0;index<k;index++){ //step through the input data
'  // Note the timer settings are not obvious as the execution of the loop elongates the low pulses
'      if (sarray[index]){
'          *mysetport=pin;
'          tmr1=0;
'          while(tmr1<25); //Tuned for the 700ns pulse
'          *myclearport=pin;
'          tmr1=0;
'          while(tmr1<13); //Tuned for the 600ns pulse
'       } else {
'          *mysetport=pin;
'          tmr1=0;
'          while(tmr1<5); //Tuned for the 350ns pulse
'          *myclearport=pin;
'          tmr1=0;
'          while(tmr1<20); //Tuned for the 800ns pulse
'      }
'  }
'  if(*numleds > 28) tmr4con |= 0x0008000; //turn the clock back on
'  *myclearport=pin; //Set the output low to create the reset pulse which loads the data
'  return index;
'}
'
' Load the colour array for a specific LED from the green, red, and blue components
'
sub WS2812.setcolour(led as integer, greenness as integer, redness as integer, blueness as integer)
  colours(led)= ((greenness and &HFF)<<16) + ((redness and &HFF)<<8) + (blueness and &HFF)
end sub
'
' Get the green, red, and blue components for a specific LED from the colour array
'
sub WS2812.getcolour(led as integer, greenness as integer, redness as integer, blueness as integer)
  greenness=colours(led)>>16
  redness=(colours(led)>>8) and &HFF
  blueness= colours(led) and &HFF
end sub
'
' uses the pin number to get the port number and the pin number on the port by reference to the Device ID
'
function WS2812.getpin(MMpin as integer,portnum as integer,pinnum as integer) as integer
  const  P28$="N/AA00A01B00B01B02B03N/AA02A03B04A04N/AB05B06B07B08B09N/AN/AB10B11B12B13B14B15N/AN/A"
   const  P40$="B09C06C07C08C09N/AN/AB10B11B12B13A10A07B14B15N/AN/AN/AA00A01B00B01B02B03C00C01C02N/AN/AA02A03A08B04A04A09C03C04C05N/AN/AB05B06B07B08"
  local integer i
  local a$ length 3
  i=(MMpin-1)*3 +1
  if (peek(word &HBF80F220) and &HFFFFFFF) = &H6610053 then
    if MMpin>=1 and MMpin<=28 then
      a$=mid$(p28$,i,3)
    else
      a$="N/A"
    endif
  else
    if MMpin>=1 and MMpin<=40 then
      a$=mid$(p40$,i,3)
    else
      a$="N/A"
    endif
  endif
  if a$="N/A" then 
     WS2812.getpin=0
  else
     portnum=asc(left$(a$,1))-65
     pinnum=val(right$(a$,2))
     WS2812.getpin=1
  endif
end function
'
' Initialise required global variables depending on the number of LEDs and set up the output pin and CPU speed
'
SUB WS2812.INIT(LED_PIN as integer,nLEDs as INTEGER)
  CPU 48 'This speed is fixed for the Cfunction to work
  ' Global variables
  DIM INTEGER NUMLEDS=nLEDS
  DIM integer buffer(NUMLEDS*3-1)
  dim INTEGER colours(NUMLEDS)
  dim integer portnum,pinnum
  setpin LED_PIN,dout
  LOCAL INTEGER i=WS2812.getpin(LED_PIN,portnum,pinnum)
end sub
'
sub EXAMPLE
  local integer i,j,green,red,blue,maxbright=40
  WS2812.setcolour(0,maxbright,maxbright,maxbright) 'white
  WS2812.setcolour(1, maxbright,0,0) 'green
  WS2812.setcolour(2,maxbright,maxbright,0) 'yellow
  WS2812.setcolour(3,0,maxbright,0) 'red
  WS2812.setcolour(4,0,maxbright,maxbright) 'magenta
  WS2812.setcolour(5,0,0,maxbright) 'blue
  WS2812.setcolour(6,maxbright,0,maxbright) 'cyan
  Do
    for j=1 to maxbright-1
      i=WS2812.pulses(NUMLEDS,portnum,pinnum,colours(),buffer()) 
      for i=0 to 6
        WS2812.getcolour(i,green,red,blue)
        if green<>0 then green=green-1
        if red<>0 then red=red-1
        if blue<>0 then blue=blue-1
        WS2812.setcolour(i,green,red,blue)
      next i
      pause 10
    next j
    rotate
    for j=1 to maxbright-1
      i=WS2812.pulses(NUMLEDS,portnum,pinnum,colours(),buffer()) 
      for i=0 to 6
        WS2812.getcolour(i,green,red,blue)
        if green<>0 then green=green+1
        if red<>0 then red=red+1
        if blue<>0 then blue=blue+1
        WS2812.setcolour(i,green,red,blue)
      next i
    pause 10
    next j
  loop
end sub
'
sub rotate 'rotates the colours round the edge of the display leaving white in the middle
 local integer i,j
 i=colours(6)
 for j=5 to 1 step -1
   colours(j+1)=colours(j)
 next j
 colours(1)=i
end sub

 

 

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

A Ton of Documentation

Open all | Close all

Projects made by Gizmo, Friends, and Members

open all | close all

Recent GizmoBlog Musings

  • Altair 8800 using a ColorMax!
  • Re-energizing the ColorMax, Pt. 3

Visit us!

  • Facebook

Electronic Products for Creative Minds

CircuitGizmos is your source for electronic products that help you create your embedded projects. Here at CircuitGizmos.com you will find a friendly store filled with creative products and all of the documentation that you need to use these gizmos.

We create devices that we believe make electronics fun, but we also know that our products are used for professional designs. For decades we have designed products for commercial, military, and medical industries. Our gizmos here are great for engineers and hobbyists alike.

Copyright © 2008+ CircuitGizmos, L.L.C. All rights reserved

Image already added

Recently Viewed Products

Copyright © 2021 · Generate Pro Theme on Genesis Framework · WordPress · Log in