Fun with AI and swordfish basic

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
 
Does it work?
 
The subs are not called right I’m getting errors figured some one point me in right direction
 
It looks good tho I just think I need to learn how to get the subs the way swordfish uses them I mean the timing and layout but subs and modules its been 14 years I gotting 62 now brain is way slow lol
 
Last edited:
I tried a little Swordfish code with Perplexity AI. I was surprised that some of it was spot on, but in other places, it was obviously not Swordfish Basic.

I did argue with Perplexity when I asked what Basic compilers there are for PIC18Fs and it didn't include Swordfish, which it added but it said it was a paid program.

I argued some more with a link to the page announcing release of the full version for free, and it corrected itself. I don't know if it was just humoring me
 
Bit of a nasty 'hit and miss' way of driving the WS2812's, most modern PIC's have CLC capability, and there are MicroChip examples of using the CLC to do the difficult timing in the CLC hardware. I've used therm on various PIC devices, and the code moved over with little change required.

Must admit though, I find the CLC really hard to understand?

Here's the CLC Initialisation code from a PIC16F18446 using it's internal 32MHz clock

C:
void CLC1_Initialize(void)
{
    // Set the CLC1 to the options selected in the User Interface

    // LC1G1POL inverted; LC1G2POL not_inverted; LC1G3POL not_inverted; LC1G4POL not_inverted; LC1POL not_inverted;
    CLC1POL = 0x01;
    // LC1D1S PWM6_OUT;
    CLC1SEL0 = 0x18;
    // LC1D2S SCK from MSSP1;
    CLC1SEL1 = 0x27;
    // LC1D3S SDO from MSSP1;
    CLC1SEL2 = 0x26;
    // LC1D4S CLCIN0 (CLCIN0PPS);
    CLC1SEL3 = 0x00;
    // LC1G1D3N disabled; LC1G1D2N enabled; LC1G1D4N disabled; LC1G1D1T disabled; LC1G1D3T disabled; LC1G1D2T disabled; LC1G1D4T disabled; LC1G1D1N enabled;
    CLC1GLS0 = 0x05;
    // LC1G2D2N disabled; LC1G2D1N disabled; LC1G2D4N disabled; LC1G2D3N enabled; LC1G2D2T disabled; LC1G2D1T disabled; LC1G2D4T disabled; LC1G2D3T disabled;
    CLC1GLS1 = 0x10;
    // LC1G3D1N disabled; LC1G3D2N disabled; LC1G3D3N disabled; LC1G3D4N disabled; LC1G3D1T disabled; LC1G3D2T enabled; LC1G3D3T disabled; LC1G3D4T disabled;
    CLC1GLS2 = 0x08;
    // LC1G4D1N disabled; LC1G4D2N disabled; LC1G4D3N disabled; LC1G4D4N disabled; LC1G4D1T disabled; LC1G4D2T disabled; LC1G4D3T enabled; LC1G4D4T disabled;
    CLC1GLS3 = 0x20;
    // LC1EN enabled; INTN disabled; INTP disabled; MODE AND-OR;
    CLC1CON = 0x80;

}
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…