'-------------------------------------------------------------------------------
' WS2812B Basic Control Example for Swordfish
' Microcontroller: PIC18F252
' Clock: 20MHz
'
' This code controls a WS2812B LED strip using software bit-banging.
' Timing is CRITICAL for WS2812B. The NOPs in SendByte are adjusted
' for a 20MHz clock (5 MIPS, 200ns per instruction cycle).
'
' You may need to fine-tune the NOP counts slightly for optimal performance
' with your specific LEDs and setup.
'-------------------------------------------------------------------------------
Device = 18f25q10
Clock = 64 ' MHz
' --- Configuration for PIC18F252 @ 20MHz ---
' Using INTRC as an option, but external crystal is more accurate for timing.
' Ensure your crystal and oscillator settings match your hardware.
'Config OSC = HSPLL ' High-Speed Crystal/Resonator with PLL (for higher speeds like 40MHz)
' If you are actually using a 20MHz crystal without PLL, use HS
' Config OSC = HS
'Config RSTOSC = HFINTOSC_64MHZ
'Config WDT = Off ' Watchdog Timer Off
'Config MCLRE = On ' Master Clear Enable
'Config PWRT = On ' Power-up Timer Enable
'Config BOR = On ' Brown-out Reset Enable
'Config LVP = Off ' Low-Voltage Programming Off (good practice for programming stability)
'Config CP0 = Off ' Code Protection Off
Include "system.bas" ' for NOP macro
Include "myosc" ' has these setting OSCCON1 = $60 OSCFRQ = 8
' --- Pin Definitions ---
Dim WS2812BDataPin As PORTC.2 ' **CHANGE THIS if you use a different pin**
' (e.g., PortB.0, PortA.5, etc.)
' --- WS2812B Parameters ---
Const NUM_LEDS As Byte = 20 ' **CHANGE THIS to the number of LEDs you have**
' Define the LED color data array (GRB format)
Dim LED_Data(NUM_LEDS * 3) As Byte ' 3 bytes per LED (Green, Red, Blue)
' --- Subroutines ---
' Subroutine to send a single byte (8 bits) to the WS2812B.
' This routine is highly time-sensitive and uses NOPs for precise delays.
' Assumes 20MHz clock (200ns per instruction cycle).
Sub SendByte(ByVal DataByte As Byte)
Dim i As Byte
For i = 0 To 7 ' Loop 8 times for 8 bits
If DataByte.bits(7 - i) = 1 Then ' Send a '1' bit
' Send 1-bit (T1H: ~0.8us HIGH, T1L: ~0.45us LOW)
' T1H: 12 instruction cycles (0.75us)
' T1L: 7 instruction cycles (0.4375us)
WS2812BDataPin = 1
nop ' 62.5ns
nop ' 125ns
nop ' 187.5ns
nop ' 250ns
nop ' 312.5ns
nop ' 375ns
nop ' 437.5ns
nop ' 500ns
nop ' 562.5ns
nop ' 625ns
nop ' 687.5ns
nop ' 750ns (approx T1H)
WS2812BDataPin = 0
nop ' 62.5ns
nop ' 125ns
nop ' 187.5ns
nop ' 250ns
nop ' 312.5ns
nop ' 375ns
nop ' 437.5ns (approx T1L)
Else ' Send a '0' bit
' Send 0-bit (T0H: ~0.4us HIGH, T0L: ~0.85us LOW)
' T0H: 6 instruction cycles (0.375us)
' T0L: 13 instruction cycles (0.8125us)
WS2812BDataPin = 1
nop ' 62.5ns
nop ' 125ns
nop ' 187.5ns
nop ' 250ns
nop ' 312.5ns
nop ' 375ns (approx T0H)
WS2812BDataPin = 0
nop ' 62.5ns
nop ' 125ns
nop ' 187.5ns
nop ' 250ns
nop ' 312.5ns
nop ' 375ns
nop ' 437.5ns
nop ' 500ns
nop ' 562.5ns
nop ' 625ns
nop ' 687.5ns
nop ' 750ns
nop ' 812.5ns (approx T0L)
End If
Next
End Sub
' Subroutine to send a single color (Green, Red, Blue) to the WS2812B.
' WS2812B expects GRB order.
Sub SendColor(ByVal Green As Byte, ByVal Red As Byte, ByVal Blue As Byte)
SendByte(Green)
SendByte(Red)
SendByte(Blue)
End Sub
' Subroutine to send all LED data from the buffer to the strip.
' This causes the LEDs to update their colors.
Sub ShowLEDs()
Dim i As Word
For i = 0 To (NUM_LEDS * 3 - 1) Step 3
SendColor(LED_Data(i), LED_Data(i + 1), LED_Data(i + 2))
Next
' Send the reset pulse (data line low for > 50us)
WS2812BDataPin = 0
DelayUS(60) ' Ensure at least 50us reset pulse (use Delay_us built-in)
End Sub
' Subroutine to set the color of a specific LED in the internal buffer.
' Colors are stored as Green, Red, Blue.
Sub SetLEDColor(ByVal LED_Index As Byte, ByVal Red As Byte, ByVal Green As Byte, ByVal Blue As Byte)
If LED_Index < NUM_LEDS Then
LED_Data(LED_Index * 3) = Green ' Store Green component
LED_Data(LED_Index * 3 + 1) = Red ' Store Red component
LED_Data(LED_Index * 3 + 2) = Blue ' Store Blue component
End If
End Sub
' --- Main Program ---
' temp variables
Dim i As Byte
Dim hue As Byte = 0
' Initialize the data pin as output low
Low(WS2812BDataPin)
' Clear all LEDs initially (set to off)
For i = 0 To NUM_LEDS - 1
SetLEDColor(i, 0, 0, 0) ' All Off
Next
ShowLEDs() ' Send all 'off' data to LEDs
DelayMS(100) ' Small delay for LEDs to update
' --- Set some colors for demonstration ---
SetLEDColor(0, 255, 0, 0) ' First LED Red
'SetLEDColor(1, 0, 255, 0) ' Second LED Green
'SetLEDColor(2, 0, 0, 255) ' Third LED Blue
'SetLEDColor(3, 255, 255, 0) ' Fourth LED Yellow (Red + Green)
'SetLEDColor(4, 0, 255, 255) ' Fifth LED Cyan (Green + Blue)
'SetLEDColor(5, 255, 0, 255) ' Sixth LED Magenta (Red + Blue)
'SetLEDColor(6, 255, 255, 255) ' Seventh LED White (Full Brightness)
'SetLEDColor(7, 10, 10, 10) ' Eighth LED Dim White
ShowLEDs() ' Send the updated data to the LEDs
'OSCCON1 = $60
' OSCFRQ = $08
' --- Simple Animation Loop ---
While (true)
SetLEDColor(0, 255, 255, 255) ' First LED white
' SetLEDColor(1, 0, 255, 0) ' First LED Red
' SetLEDColor(2, 0, 0, 255) ' First LED Red
' SetLEDColor(3, 0, 255, 0) ' First LED Red
' SetLEDColor(4, 0, 0, 255) ' First LED Red
' SetLEDColor(5, 255, 0, 0) ' First LED Red
' SetLEDColor(6, 0, 255, 0) ' First LED Red
' SetLEDColor(7, 0, 0, 255) ' First LED Red
' SetLEDColor(8, 255, 0, 0) ' First LED Red
'SetLEDColor(9, 255, 0, 0) ' First LED Red
' SetLEDColor(10, 255, 0, 0) ' First LED Red
' SetLEDColor(11, 255, 0, 0) ' First LED Red
' SetLEDColor(12, 255, 0, 0) ' First LED Red
' SetLEDColor(13, 255, 0, 0) ' First LED Red
' SetLEDColor(14, 255, 0, 0) ' First LED Red
' SetLEDColor(15, 255, 0, 0) ' First LED Red
' SetLEDColor(16, 255, 0, 0) ' First LED Red
' SetLEDColor(17, 255, 0, 0) ' First LED Red
' SetLEDColor(18, 255, 0, 0) ' First LED Red
' SetLEDColor(19, 255, 0, 0) ' First LED Red
ShowLEDs() ' Send the updated data to the LEDs.8..
End While
'End Program