• [Mecrisp Stellaris] Compiling words?

    From Niclas Hedhman@21:1/5 to All on Sun Aug 27 09:38:36 2023
    Hi,

    I want to interface with a WS2812, and I have set up the MCU so that I can simply send $88, $8C, $C8, $CC (for 00,01,10,11) twelve times to get the 24 bits in the RGB LED wire "protocol".

    So, if I do;

    : off $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi ;

    I can set the LED to off. There is not enough time to keep that in an array, loop and read out each on the fly, and DMA has a side-effect that makes it not possible to use for this LED on this MCU, so I thought I should just generate the code;

    : rgb ( rgb -- )( -- )
    create split-rgb (ws2812b) (ws2812b) (ws2812b)
    does> execute ;
    ;

    where "split-rgb" breaks the rgb into r g b and then "(ws2812b)" loops through the 8 bits to generate the word. So, usage would be

    $0 rgb off
    $FFFF rgb warning

    and in the background the "off" word executes the same way as the defined word above.

    This is nothing I have done before and don't grok how I inject "call this particular word" into the dictionary body.

    I think that I can "literal," to pop the computed byte from TOS into the dictionary so that when it is executed it pushes that value onto stack. But how do I do the same for a word to execute?

    Any help/pointer would be greatly appreciated.

    Niclas


    P.S. for reference, I the (ws2812b) will look something like;

    : (ws2812b) ( n -- )
    #24 lshift \ move all bits up
    4 0 do
    rol rol \ shift in next two bits
    dup 3 and
    case
    0 of $88 endof
    1 of $C8 endof
    2 of $8C endof
    3 of $CC endof
    endcase
    literal, \ <-- I need a "add execute '>spi' to dictionary" here
    loop
    drop
    ;

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Niclas Hedhman@21:1/5 to Niclas Hedhman on Mon Aug 28 00:05:21 2023
    [SOLVED!]

    The words that I found by studying the "codegenerator-m3.s" source were;
    call,
    [']
    ret,

    Now I just need to get the bits in the stream in the right order, and will post the solution later...


    Cheers
    Niclas

    On Sunday, August 27, 2023 at 6:38:38 PM UTC+2, Niclas Hedhman wrote:
    Hi,

    I want to interface with a WS2812, and I have set up the MCU so that I can simply send $88, $8C, $C8, $CC (for 00,01,10,11) twelve times to get the 24 bits in the RGB LED wire "protocol".

    So, if I do;

    : off $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi $88 >spi ;

    I can set the LED to off. There is not enough time to keep that in an array, loop and read out each on the fly, and DMA has a side-effect that makes it not possible to use for this LED on this MCU, so I thought I should just generate the code;

    : rgb ( rgb -- )( -- )
    create split-rgb (ws2812b) (ws2812b) (ws2812b)
    does> execute ;
    ;

    where "split-rgb" breaks the rgb into r g b and then "(ws2812b)" loops through the 8 bits to generate the word. So, usage would be

    $0 rgb off
    $FFFF rgb warning

    and in the background the "off" word executes the same way as the defined word above.

    This is nothing I have done before and don't grok how I inject "call this particular word" into the dictionary body.

    I think that I can "literal," to pop the computed byte from TOS into the dictionary so that when it is executed it pushes that value onto stack. But how do I do the same for a word to execute?

    Any help/pointer would be greatly appreciated.

    Niclas


    P.S. for reference, I the (ws2812b) will look something like;

    : (ws2812b) ( n -- )
    #24 lshift \ move all bits up
    4 0 do
    rol rol \ shift in next two bits
    dup 3 and
    case
    0 of $88 endof
    1 of $C8 endof
    2 of $8C endof
    3 of $CC endof
    endcase
    literal, \ <-- I need a "add execute '>spi' to dictionary" here
    loop
    drop
    ;

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Niclas Hedhman@21:1/5 to Niclas Hedhman on Mon Aug 28 00:26:14 2023
    On Monday, August 28, 2023 at 9:05:23 AM UTC+2, Niclas Hedhman wrote:
    [SOLVED!]

    The words that I found by studying the "codegenerator-m3.s" source were; call,
    [']
    ret,

    Now I just need to get the bits in the stream in the right order, and will post the solution later...


    : (neopixel) ( n -- )
    #24 lshift \ move all bits up
    4 0 do
    rol rol \ shift in next two bits
    dup 3 and ( input masked )
    case
    0 of $88 endof
    1 of $C8 endof
    2 of $8C endof
    3 of $CC endof
    endcase
    literal, \ compile top of stack (TOS) as a literal to word being defined
    ['] >spi \ address of ">spi" to TOS
    call, \ compile a call to the address on TOS
    loop
    drop
    ;

    : split-rgb ( rgb -- b r g )
    dup $FF and swap ( blue )
    dup #16 rshift $FF and swap ( red )
    #8 rshift $FF and ( green )
    ;

    : rgb ( rgb -- )( -- )
    <builds
    split-rgb \ convert 24 bits into three 8bits in order of b r g (green on TOS)
    (neopixel) \ generate bitstream for green
    (neopixel) \ generate bitstream for red
    (neopixel) \ generate bitstream for blue
    ret, \ generate a return
    does> execute
    ;


    For those interested, the Neopixel (WS2812B) is connected to the MOSI pin on SPI1 and that is set to 4Mbits/sec and 16bit mode. ">spi" simply check that the previous transfer is complete and the write directly to the SPI1-DR register.
    I don't recommend using the MOSI for interfacing with the WS2812B. In my case; if I use DMA, then the MOSI pin ends up "high" and with a small delay between DMA transfers, this "high" becomes a bit. This doesn't happen when writing directly to the SPI1-
    DR register. One should instead use a Timer+DMA to get the bitstream, for more precise control.

    BTW; this is done on STM32WLE5 and a Mecrisp Stellaris variant in parallel with CubeMX from ST, and FreeRTOS in place. See https://github.com/niclash/colibri-1dp-mcu1 for full codebase (Work in progress, as LoraWAN part is still having issues, but the
    Forth side feels quite solid.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)