' --- Device Configuration ---
Device = 18F25Q10 ' Target microcontroller device
Clock = 64 ' System clock frequency in MHz (using 64 MHz internal oscillator for precise timing)
Config RSTOSC = HFINTOSC_64MHZ ' Configure reset oscillator to internal HFINTOSC at 64 MHz (ensures MCU starts at 64 MHz)
' (Other config bits like WDT, LVP, etc., can be set as needed for your project)
' --- Include Libraries ---
Include "system.bas" ' System library (provides NOP, Delay routines, etc.)
'Include "intosc.bas" ' Alternative: this library can auto-configure the internal oscillator (if available)
' --- Pin Definition ---
Dim WS2812BDataPin As PORTC.2 ' Data output pin for WS2812B LED strip (change if using a different pin or port)
' --- WS2812B LED Strip Parameters ---
Const NUM_LEDS As Byte = 20 ' Number of LEDs in the strip (modify if different)
Dim LED_Data(NUM_LEDS * 3) As Byte ' LED color data buffer (3 bytes per LED for Green, Red, Blue)
' --- WS2812B Timing-critical Subroutines ---
' Subroutine to send a single byte to the WS2812B.
' This routine bit-bangs 8 bits with precise timing.
' At 64 MHz (16 MIPS, 62.5 ns per instruction), the NOPs produce the required pulse widths:
' - For a "1" bit: ~0.8 µs HIGH and ~0.45 µs LOW (approx 12 NOPs high, 7 NOPs low).
' - For a "0" bit: ~0.4 µs HIGH and ~0.85 µs LOW (approx 6 NOPs high, 13 NOPs low).
Sub SendByte(ByVal DataByte As Byte)
Dim bitIndex As Byte
For bitIndex = 0 To 7 ' Send 8 bits (MSB first)
If DataByte.bits(7 - bitIndex) = 1 Then
' Send a "1" bit (data line high then low)
WS2812BDataPin = 1 ' begin HIGH pulse for "1"
nop ' ~62.5 ns
nop ' ~125 ns
nop ' ~187.5 ns
nop ' ~250 ns
nop ' ~312.5 ns
nop ' ~375 ns
nop ' ~437.5 ns
nop ' ~500 ns
nop ' ~562.5 ns
nop ' ~625 ns
nop ' ~687.5 ns
nop ' ~750 ns (HIGH for ~0.75 µs)
WS2812BDataPin = 0 ' end HIGH pulse, start LOW pulse
nop ' ~62.5 ns
nop ' ~125 ns
nop ' ~187.5 ns
nop ' ~250 ns
nop ' ~312.5 ns
nop ' ~375 ns
nop ' ~437.5 ns (~0.44 µs LOW)
' (HIGH ~0.75 µs, LOW ~0.44 µs for "1" bit)
Else
' Send a "0" bit (data line high then low)
WS2812BDataPin = 1 ' begin HIGH pulse for "0"
nop ' ~62.5 ns
nop ' ~125 ns
nop ' ~187.5 ns
nop ' ~250 ns
nop ' ~312.5 ns
nop ' ~375 ns (~0.375 µs HIGH)
WS2812BDataPin = 0 ' end HIGH pulse, start LOW pulse
nop ' ~62.5 ns
nop ' ~125 ns
nop ' ~187.5 ns
nop ' ~250 ns
nop ' ~312.5 ns
nop ' ~375 ns
nop ' ~437.5 ns
nop ' ~500 ns
nop ' ~562.5 ns
nop ' ~625 ns
nop ' ~687.5 ns
nop ' ~750 ns
nop ' ~812.5 ns (~0.813 µs LOW)
' (HIGH ~0.375 µs, LOW ~0.813 µs for "0" bit)
End If
Next
End Sub
' Subroutine to send one complete LED's color (3 bytes for Green, Red, Blue) to the strip.
' WS2812B LED expects data in GRB order.
Sub SendColor(ByVal Green As Byte, ByVal Red As Byte, ByVal Blue As Byte)
SendByte(Green) ' send Green component
SendByte(Red) ' send Red component
SendByte(Blue) ' send Blue component
End Sub
' Subroutine to push out the entire LED_Data buffer to the LED strip.
' This iterates over each LED's GRB values and uses SendColor to update them.
' After sending all data, it sends a reset/latch pulse by keeping data line LOW for >50 µs.
Sub ShowLEDs()
Dim idx As Word
For idx = 0 To (NUM_LEDS * 3 - 1) Step 3
SendColor(LED_Data(idx), LED_Data(idx + 1), LED_Data(idx + 2))
Next
WS2812BDataPin = 0 ' ensure the data line is LOW
DelayUS(60) ' hold LOW for at least 60 µs to latch data (reset pulse > 50 µs)
End Sub
' Subroutine to set the color of a specific LED in the LED_Data buffer.
' Parameters:
' LED_Index - index of the LED (0-based)
' Red, Green, Blue - 0-255 intensity values for each color channel.
' This does NOT immediately update the LED; it only updates the buffer.
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 ' check bounds
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 ---
Dim i As Byte
Const BLINK_DELAY_MS As Word = 500 ' Delay time in milliseconds for blink intervals (adjust for faster/slower blink)
Low(WS2812BDataPin) ' Initialize the data pin to LOW and set it as output
' Initial LED setup: start with all LEDs off
For i = 0 To NUM_LEDS - 1
SetLEDColor(i, 0, 0, 0) ' set each LED color to off (R=0, G=0, B=0)
Next
ShowLEDs() ' send initial off state to all LEDs
DelayMS(100) ' small delay to ensure LEDs have latched off
' Now enter the blink loop: all LEDs will turn on, wait, then turn off, wait, repeatedly
While true
' 1. Turn all LEDs ON (set to a chosen color)
For i = 0 To NUM_LEDS - 1
' Example: make all LEDs white. You can change the values for a different color.
SetLEDColor(i, 255, 255, 255) ' set each LED to White (Red=255, Green=255, Blue=255)
Next
ShowLEDs() ' output the "all ON" data to the LED strip
DelayMS(BLINK_DELAY_MS) ' keep LEDs on for BLINK_DELAY_MS (pause with LEDs lit)
' 2. Turn all LEDs OFF
For i = 0 To NUM_LEDS - 1
SetLEDColor(i, 0, 0, 0) ' set each LED to off (black)
Next
ShowLEDs() ' output the "all OFF" data to turn off the LEDs
DelayMS(BLINK_DELAY_MS) ' delay with LEDs off before the next cycle
' The loop then repeats, causing the LEDs to blink on and off continuously.
Wend ' (Alternatively, you can use "Loop" or another infinite loop mechanism in Swordfish Basic)