be80be
Well-Known Member
Fun with AI but lots of bugs here with subs
Code:
'-------------------------------------------------------------------------------
' 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 = 18F252
Clock = 20 ' 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 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
' --- Pin Definitions ---
Dim WS2812BDataPin As PORTB.0 ' **CHANGE THIS if you use a different pin**
' (e.g., PortB.0, PortA.5, etc.)
' --- WS2812B Parameters ---
Const NUM_LEDS As Byte = 10 ' **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)
' --- Function Prototypes ---
Sub SendByte(ByVal DataByte As Byte) end sub
Sub SendColor(ByVal Green As Byte, ByVal Red As Byte, ByVal Blue As Byte) end sub
Sub ShowLEDs() end sub
Sub SetLEDColor(ByVal LED_Index As Byte, ByVal Red As Byte, ByVal Green As Byte, ByVal Blue As Byte) end sub
' --- Main Program ---
'Program Main
' Initialize the data pin as output
SetDirection(WS2812BDataPin, Output)
Clear(WS2812B_DataPin) ' Ensure data line is low initially
I = Byte
' Clear all LEDs initially (set to off)
For I = 0 To NUM_LEDS - 1
SetLEDColor(I, 0, 0, 0) ' All Off
Next I
ShowLEDs() ' Send all 'off' data to LEDs
Delay_ms(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
' --- Simple Animation Loop ---
Do
Delay_ms(500) ' Wait for 0.5 seconds
' Shift colors down the strip
For I = NUM_LEDS - 1 To 1 Step -1
LED_Data(I * 3) = LED_Data((I - 1) * 3) ' Green
LED_Data(I * 3 + 1) = LED_Data((I - 1) * 3 + 1) ' Red
LED_Data(I * 3 + 2) = LED_Data((I - 1) * 3 + 2) ' Blue
Next I
' Put a new color at the start (e.g., a rotating color)
Static Hue = Byte
If Hue = 0 Then SetLEDColor(0, 255, 0, 0) ' Red
If Hue = 1 Then SetLEDColor(0, 0, 255, 0) ' Green
If Hue = 2 Then SetLEDColor(0, 0, 0, 255) ' Blue
Inc(Hue)
If Hue > 2 Then Hue = 0
ShowLEDs() ' Update the LEDs with the new pattern
Loop
'End Program
' --- 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)
For I As Byte = 0 To 7 ' Loop 8 times for 8 bits
If TestBit(DataByte, 7 - I) Then ' Send a '1' bit
' Send 1-bit (T1H: ~0.8us HIGH, T1L: ~0.45us LOW)
' T1H: 4 instruction cycles (0.8us)
' T1L: 2-3 instruction cycles (0.4-0.6us)
Set(WS2812BDataPin)
NOP ' 200ns
NOP ' 400ns
NOP ' 600ns
NOP ' 800ns (approx T1H)
Clear(WS2812BDataPin)
NOP ' 200ns
NOP ' 400ns (approx T1L)
Else ' Send a '0' bit
' Send 0-bit (T0H: ~0.4us HIGH, T0L: ~0.85us LOW)
' T0H: 2 instruction cycles (0.4us)
' T0L: 4-5 instruction cycles (0.8-1.0us)
Set(WS2812BDataPin)
NOP ' 200ns
NOP ' 400ns (approx T0H)
Clear(WS2812BDataPin)
NOP ' 200ns
NOP ' 400ns
NOP ' 600ns
NOP ' 800ns (approx T0L)
NOP ' 1000ns (Optional, for slightly longer T0L if needed)
End If
Next I
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()
For I As Word = 0 To NUM_LEDS * 3 - 1 Step 3
SendColor(LED_Data(I), LED_Data(I + 1), LED_Data(I + 2))
Next I
' Send the reset pulse (data line low for > 50us)
Clear(WS2812B_DataPin)
Delay_us(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