Lazarus

Programming => Embedded => Operating Systems => Embedded - ARM => Topic started by: jb007 on August 03, 2022, 10:16:13 pm

Title: pi PICO controlling ws2812b leds, ledstrips
Post by: jb007 on August 03, 2022, 10:16:13 pm
Hi, recently started coding pi PICO using fpcLaz!

A lots of tnx to Michael Ring for his example programms!

After understanding the PICO's Software IO, I started to code for ws2812b.

I managed to get the timing right and things are going nice!
( allready had this done on Arduino, using pascal: https://www.youtube.com/playlist?list=PLcCKmeWXkrzSm4-kT055wc9f1ITOjBx16 )

When the code is kinda finished and clear, I will post it if wanted, here some video's of ws2812b led's/bars on my PICO:
https://www.youtube.com/playlist?list=PLcCKmeWXkrzRoul43A6f0xf8baJPggiu0


Kind regards. Marcel





Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MarkMLl on August 03, 2022, 10:51:58 pm
What technique are you using: bitbanging or PIO state machine?

MarkMLl
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: jb007 on August 04, 2022, 03:00:29 pm
Oops...first had to google for the meaning 'bitbanging'... :)

So...Yes, my code is bitbanging!
Wasn't aware of this term, just started coding with ( in this case ) the single NRZ protocol AND my scope next to me.


BUT...to get the 'electrical One or Zero I'm using:
( in this case I have ledbars, each 8xRGB, so 192 bit )


procedure writeLogicOne(pinNr:byte);
var
  byCntr: byte;
begin
  sio.gpio_set := 1 shl pinNr;  //   800
  for byCntr:= 0 to 4 do;            // = 720
  sio.gpio_clr := 1 shl pinNr;  //   400
  for byCntr:= 0 to 1 do;            // = 420

end; // p\writeLogicOne


procedure writeLogicZero(pinNr: byte);
var
  byCntr: byte;
begin
  sio.gpio_set := 1 shl pinNr;  //   400
  for byCntr:= 0 to 1 do;            // = 320
  sio.gpio_clr := 1 shl pinNr;  //   800
  for byCntr:= 0 to 4 do;            // = 820

end; // p\writeLogicZero       


procedure doLEDwrite(pinNR: byte);
var
  byCntrBIT: byte;
begin
  for byCntrBIT:= 0 to 191 do
    begin
      if (lightBL[byCntrBIT] = true ) then writeLogicOne(pinLightBR)
      else writeLogicZero(pinLightBR);
    end;

  for byCntrBIT:= 0 to 191 do
    begin
      if (lightBL[byCntrBIT] = true ) then writeLogicOne(pinlightBL)
      else writeLogicZero(pinLightBL);
    end;

end; // p\





BE AWARE of the fOLLOWING:

The timing is NOT ONLY determed by the for byCntr:= 0 to 1
and for byCntr:= 0 to 4 do; but by the whole 'process' above'.

This 'proces' is time-sollid at itself!

Sure, there are multiple ways leading to Rome... ;D


As written before, just jumped into 'pascal for pico' and this
way of setting/resetting an output pin is new for me.
I'm used to this: portA.4:= 1 (or 0 )  instead of sio.gpio_set/clr 'thing'


I'm using this array method, cause between ( refreshrate ) writing a bunch of ws2812b, there's is plenty of time
to calcutale/determen and placing the 24bits for each led in the array.
Multiple led arrays can be used, if eachr strip/bar has difference colourvariations/patterns.

To get an idea:
f_bit = 800kHz 
T_bit = 1.25us
T_led = 24 x 1.25 = 30us
f_led = 1/30us = 33k33Hz

When suggestions ( assembly? ) about setting resetting output bit, please commecnt!

Kind regards.

 






Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: ccrause on August 04, 2022, 03:29:33 pm
Nice work!
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MarkMLl on August 04, 2022, 03:49:33 pm
Well done :-)

Now obviously there's been a lot of experience built up around these devices, largely based on the Arduino. The dominant technique is bitbanging using e.g. https://github.com/FastLED/FastLED , but some people have also experimented using the SPI bus... I forget the precise detail, but I think it was something like sending three consecutive bytes at double-clock-speed to get the appropriate mark/space ratio.

/However/, since a strip of these LEDs is intolerant of glitches it effectively meant that the processor would still have to give the transfer its entire attention, since the IRQ etc. latency was quite simply unacceptable.

There's a fair amount of interest in the idea of using the RP2040's PIO hardware to generate the pulsetrain to drive an LED string: see https://dubinko.info/blog/2021/09/raspberry-pi-neopixel-code-wrong/ as a particular example.

I've not looked at this yet using C++, and I don't think that anybody's looked at it using Pascal... in fact I'm not sure anybody's looked at supporting the PIO hardware (using pioasm source) from Pascal yet. So if you're looking for a challenge :-)

MarkMLl
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MiR on August 04, 2022, 05:59:42 pm
Pio Hardware is the way to go, however I never played with this part of pico.

The unit for integration is already in the source tree:

https://github.com/michael-ring/pico-fpcexamples/blob/main/units/pico_pio_c.pas

but untested.

With APA106 using SPI is pretty straightforward, ws2812b is another story….

Example for APA106 is here (pascal code, but not for pico)

https://github.com/michael-ring/mbf/blob/master/Samples/APA106Demo/APA106Demo.lpr
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: jb007 on August 04, 2022, 08:45:42 pm
Tnx for all the replies.

Sure, I started ( and learning fpc for PICo ) with the Micheal Ring's examples.

For the ws2812b I dove into that pico_gpio_c file

There's is this gpio_put procedure.

      procedure gpio_put(gpio:TPinIdentifier; value:boolean);
      begin
        if value = true then
          gpio_set_mask(1 shl gpio)
        else
          gpio_clr_mask(1 shl gpio);
      end;   

               
                this is calling


         procedure gpio_set_mask(mask:longWord);
         begin
           sio.gpio_set := mask;
         end;     

                 or
           
         procedure gpio_clr_mask(mask:longWord);
         begin
           sio.gpio_clr := mask;
         end;   


For the ws2812b on PCIO all this calling takes to long. ( +/- 150ns )

So, I shortened it to this:

procedure writeLogicOne(pinNr:byte);
var
  byCntr: byte;
begin
  sio.gpio_set := 1 shl pinNr;  //   800
  for byCntr:= 0 to 4 do;            // = 720
  sio.gpio_clr := 1 shl pinNr;  //   400
  for byCntr:= 0 to 1 do;            // = 420

end; // p\writeLogicOne

AND


procedure writeLogicZero(pinNr: byte);
var
  byCntr: byte;
begin
  sio.gpio_set := 1 shl pinNr;  //   400
  for byCntr:= 0 to 1 do;            // = 320
  sio.gpio_clr := 1 shl pinNr;  //   800
  for byCntr:= 0 to 4 do;            // = 820

end; // p\writeLogicZero   





(1)                       if (lightBL[byCntrBIT] = true )
(2)                         then writeLogicOne(pinLightBR)
(3)                            else writeLogicZero(pinLightBR);


But still, this can also be shortenend when placing the code from procedures writeLogicOne and writeLogicZero in the 3 lines above!

Gonna play whit that, and conenct my scope and see the exact timing values!

To bee continued!

Kind regards. Marcel










Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MarkMLl on August 04, 2022, 08:48:36 pm
Note that PIO <> GPIO, it's a functional block with its own state machine etc.

Michael, is there an example for the Pascal unit you highlighted earlier?

MarkMLl
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MiR on August 04, 2022, 09:08:40 pm
Unfortunately there is no example but when I remember correctly everything is there that is needed. I think one has to upload the sequence that pico should run and then trigger this small ‚program‘ and that‘s it.

Only issue was that you have to compile the sequence but you may be able to steal that compiled code from the pico SDK example for ws2812…

Michael
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MarkMLl on August 04, 2022, 09:52:36 pm
Only issue was that you have to compile the sequence but you may be able to steal that compiled code from the pico SDK example for ws2812…

At present that's quite a biggy. My understanding is that the new (~FPC 3.3) attribute specification can be used for target-specific things like specifying linkage sections (as well as its nominal role for decorating types), but I've not seen any suggestion that this can be generalised to do things like invoking pioasm.

I've previously raised my head above the parapet and risked suggesting that FPC really could do with an improved frontend/macro capability that would allow it to e.g. embed SQL (or in the current case source for the PIO state machine), and was given to understand that the core team were dead against that sort of thing (I'm British. We're into understatement. OK?).

I appreciate that this is "argumentum ab auctoritate", but I've been knocking around for long enough and seen enough languages and development systems come and go that my experience suggests that the core team is wrong. At the same time, I recognise that the project isn't a democracy and that if I feel strongly about it I should nail my colours to the mast and start a new fork. But I've been knocking around for long enough that I feel I don't have the years to do it justice, or anything like the acuity I once had.

So, what are we left with? I still feel that it would be desirable to be able to define the PIO state machine as close as possible to the Pascal that will interface with it. I'm reminded of one or other of the mainframe systems programming languages which allowed machine-level opcodes to be inserted in the instruction sequence by having a predefined function for each, it might /possibly/ be feasible to do something like that for pioasm in conjunction with backend-specific attributes.

However much I loathe Python, I have to admire the fact that the language can cope with this sort of thing without missing a beat https://github.com/raspberrypi/pico-micropython-examples/blob/master/pio/pio_ws2812.py

MarkMLl
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MiR on August 05, 2022, 10:15:22 am
I had a quick look at the example from the pico sdk, things may not be that difficult after all because the header of the pio example includes the 'compiled' program:

Code: C  [Select][+][-]
  1. #define ws2812_wrap_target 0
  2. #define ws2812_wrap 3
  3.  
  4. #define ws2812_T1 2
  5. #define ws2812_T2 5
  6. #define ws2812_T3 3
  7.  
  8. static const uint16_t ws2812_program_instructions[] = {
  9.             //     .wrap_target
  10.     0x6221, //  0: out    x, 1            side 0 [2]
  11.     0x1123, //  1: jmp    !x, 3           side 1 [1]
  12.     0x1400, //  2: jmp    0               side 1 [4]
  13.     0xa442, //  3: nop                    side 0 [4]
  14.             //     .wrap
  15. };

https://github.com/raspberrypi/pico-examples/tree/master/pio/ws2812

So Marcel, if you like a challenge then I'd propose you look at that code, things should translate quite easy in the Freepascal Implementation.

I might create the example myself, but not right now, I am busy with real life work atm....

Michael
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MarkMLl on August 05, 2022, 10:56:20 am
I had a quick look at the example from the pico sdk, things may not be that difficult after all because the header of the pio example includes the 'compiled' program:

Well spotted.So the question is going to be how to integrate it, and I suspect that we'll be told that we have to run pioasm separately and build a resource file.

One thing I noticed about the SDK yesterday was that it includes the entire TinyUSB stack, so searching for files by name or content is complicated by the fact that there are files for all supported processors (i.e. not just the RP2040). There's also a stub in there for lwIP which will probably have every possible network device. No wonder it's bulky...

I also spot a couple of MIT licenses and a BSD... I certainly hope that somebody has checked that these are compatible with the SDK's overall loose copyleft approach.

MarkMLl


Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: jb007 on August 05, 2022, 01:37:08 pm

Hi, that's a lot of info!

Have to read that multiple times to get a full understanding.

I think it will help to shorten/simplify the ws2812b WRITING part, even while things already are working fine.


Tnx in advance!
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MarkMLl on August 05, 2022, 01:58:57 pm
READING the WS2812 string is left as an exercise... :-)

While not all of the parts are in place yet, the ultimate idea is that one of those chips will be able to run two simultaneous hardware threads, two simultaneous state machines driving PIOs, and SPI etc. on GPIO pins. You do have to give close attention though to what functionality is available on which pin: there's not a full crossbar exchange in there.

MarkMLl
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: jb007 on August 06, 2022, 12:34:30 pm
Hi,

 where can I find the declarations/code of all those pi PICO

- sio.gpio_set
- gpio_clr_mask
- sio.gpio_clr

etc.?

I'm used to work directly at bitlevel in the registers of my AVR-controllers
( PWM, ADC, UART etc )

Kind regards.






Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MarkMLl on August 06, 2022, 12:41:57 pm
First document to read, even if not directly relevant to Pascal:

https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf

Second document to read:

https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf

After that you're basically at the mercy of what's in this forum and the relevant wiki pages (or equivalent for other languages not supported by the RPi Foundation).

MarkMLl
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MiR on August 06, 2022, 12:52:12 pm
Not sure what sio is, did you mean pio?
You can always grep through the sources in the repository of my pascal bindings, check the pico-SDK in GitHub and if you want to go the hard way you can always check the hardware reference manual. But I‘d advise against going fully lowlevel, with the new pico w things like wifi and multitasking are hard to implement on your own, it is better to stand on the shoulders of giants like FreeRTOS and lwip.


One more hint, pico functions often only exist as macros in C, so you cannot link to them and have to implement them in Pascal, there are tons of examples in my code for this.

Michael
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MiR on August 06, 2022, 02:41:50 pm
I just realized that I already did a lot more with pio as I thought....

This is what I found on my computer, looks like 90% of the way to get things working:

Code: Pascal  [Select][+][-]
  1. program pio_ws2812;
  2. {
  3.   This file is part of pico-fpcsamples
  4.   Copyright (c) 2021 -  Michael Ring
  5.  
  6.   This program is free software: you can redistribute it and/or modify it under the terms of the FPC modified GNU
  7.   Library General Public License for more
  8.  
  9.   This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
  10.   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the FPC modified GNU Library General Public
  11.   License for more details.
  12. }
  13.  
  14. {$MODE OBJFPC}
  15. {$H+}
  16. {$MEMORY 10000,10000}
  17.  
  18. uses
  19.   pico_c,
  20.   pico_gpio_c,
  21.   pico_clocks_c,
  22.   pico_pio_c;
  23.  
  24. const
  25.   ws2812_wrap_target=0;
  26.   ws2812_wrap=3;
  27.   ws2812_T1=2;
  28.   ws2812_T2=5;
  29.   ws2812_T3=3;
  30.  
  31.   ws2812_program_instructions : array of word = (
  32.            //     .wrap_target
  33.     $6221, //  0: out    x, 1            side 0 [2]
  34.     $1123, //  1: jmp    !x, 3           side 1 [1]
  35.     $1400, //  2: jmp    0               side 1 [4]
  36.     $a442  //  3: nop                    side 0 [4]
  37.            //     .wrap
  38.   );
  39.  
  40.   ws2812_program : Tpio_program  = (
  41.     instructions : @ws2812_program_instructions;
  42.     length : 4;
  43.     origin : -1;
  44.   );
  45.  
  46. function ws2812_program_get_default_config(offset:longWord):Tpio_sm_config;
  47. begin
  48.   Result := pio_get_default_sm_config();
  49.   sm_config_set_wrap(Result, offset + ws2812_wrap_target, offset + ws2812_wrap);
  50.   sm_config_set_sideset(Result, 1, false, false);
  51. end;
  52.  
  53. procedure ws2812_program_init(var pio : TPIO_Registers; sm : longWord; offset : longWord; pin : TPinIdentifier; freq : Real; rgbw : boolean);
  54. var
  55.   c : Tpio_sm_config;
  56.   cycles_per_bit : longWord;
  57.   &div : real;
  58. begin
  59.   pio_gpio_init(pio, pin);
  60.   pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
  61.   c := ws2812_program_get_default_config(offset);
  62.   sm_config_set_sideset_pins(c, pin);
  63.   if rgbw = true then
  64.     sm_config_set_out_shift(c, false, true, 32)
  65.   else
  66.     sm_config_set_out_shift(c, false, true, 24);
  67.  
  68.   sm_config_set_fifo_join(c, PIO_FIFO_JOIN_TX);
  69.   cycles_per_bit := ws2812_T1 + ws2812_T2 + ws2812_T3;
  70.   &div := clock_get_hz(clk_sys) / (freq * cycles_per_bit);
  71.   sm_config_set_clkdiv(c, &div);
  72.   pio_sm_init(pio, sm, offset, c);
  73.   pio_sm_set_enabled(pio, sm, true);
  74. end;
  75.  
  76. var
  77.   sm : longWord;
  78.   offset : longWord;
  79. begin
  80.   sm := 0;
  81.   offset := pio_add_program(pio0, ws2812_program);
  82.   ws2812_program_init(pio0, sm, offset, TPicoPin.UART_TX, 800000, true);
  83.   //pio_sm_put_blocking(pio0, 0, pixel_grb shl 8);
  84. end.
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MarkMLl on August 06, 2022, 06:09:43 pm
Interesting, TFT. So in principle a preprocessor could recognise e.g. //#begin and //#end markers for pioasm source, and use that to generate a file for an immediately-following $include directive.

Looking closely at pioasm, it apparently supports hex- and Ada-format output... I wonder how close those are to being usable without a complex wrapper?

MarkMLl
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MiR on August 06, 2022, 06:42:35 pm
Likely (at least from my point of view) this is not worth the effort. Most people will not want want to go down the rabbit hole of low level coding and do not have the equipment to do so, like a logic analyzer.

Once ws2812 works flawlessly it can be wrapped in an unit and people will simply use that unit, ignoring the underlying complexity.

Looking at the examples that are in pico-examples on github the main usecases are apa102, manchester/quadrature encoding, st7789 interface and ws2812. The other stuff is more or less duplication of already available peripherals like spi, uart, pwm. Anyway, it is always the same pattern, compile pio file, convert the interface for your pio code and then apply.

If you really really want make things better then you could create a patch for picoasm so that it generates pascal output, this is likely the best and easiest way to fix the issue if you still feel fixing is needed.
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MarkMLl on August 06, 2022, 07:15:37 pm
If you really really want make things better then you could create a patch for picoasm so that it generates pascal output, this is likely the best and easiest way to fix the issue if you still feel fixing is needed.

Yes, definitely the way to go. It looks as though Python is the only language that embeds PIO source, and C- which in fairness is a special case- has a special facility for embedding C source in a .pio file. It looks as though converting the Ada variant would be trivial, possibly with the presence of the -p option determining whether the result was an include file or a unit.

MarkMLl
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MiR on August 06, 2022, 07:18:24 pm
Just fo the fun of it I already started the patch, creating freepascal output is totally easy, I like the way the guys from Raspberry Foundation write their code...

Code: Text  [Select][+][-]
  1. ./pioasm/pioasm                                                                                             (master)pico-examples
  2. error: expected input filename
  3.  
  4. usage: pioasm <options> <input> (<output>)
  5.  
  6. Assemble file of PIO program(s) for use in applications.
  7.    <input>             the input filename
  8.    <output>            the output filename (or filename prefix if the output format produces multiple outputs).
  9.                        if not specified, a single output will be written to stdout
  10.  
  11. options:
  12.   -o <output_format>   select output_format (default 'c-sdk'); available options are:
  13.                            c-sdk
  14.                                C header suitable for use with the Raspberry Pi Pico SDK
  15.                            python
  16.                                Python file suitable for use with MicroPython
  17.                            hex
  18.                                Raw hex output (only valid for single program inputs)
  19.                            ada
  20.                                Ada specification
  21.                            freepascal
  22.                                Freepascal include file suitable for use with the Raspberry Pi Pico SDK
  23.   -p <output_param>    add a parameter to be passed to the output format generator
  24.   -?, --help           print this help and exit
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MiR on August 06, 2022, 08:07:55 pm
Done.. Patch for pioasm attached...


Code: Text  [Select][+][-]
  1. ring@macbook-pro build-pico $ ./pioasm/pioasm -o freepascal ~/devel/pico-fpcexamples/pio_ws2812/ws2812.pio                                (master)pico-examples
  2. // -------------------------------------------------- //
  3. // This file is autogenerated by pioasm; do not edit! //
  4. // -------------------------------------------------- //
  5.  
  6. // ------ //
  7. // ws2812 //
  8. // ------ //
  9.  
  10. const ws2812_wrap_target=0;
  11. const ws2812_wrap=3;
  12.  
  13. const ws2812_T1=2;
  14. const ws2812_T2=5;
  15. const ws2812_T3=3;
  16.  
  17. const ws2812_program_instructions : array of word = (
  18.            //     .wrap_target
  19.     $6221, //  0: out    x, 1            side 0 [2]
  20.     $1123, //  1: jmp    !x, 3           side 1 [1]
  21.     $1400, //  2: jmp    0               side 1 [4]
  22.     $a442  //  3: nop                    side 0 [4]
  23.            //     .wrap
  24. );
  25.  
  26. const ws2812_program : Tpio_program = (
  27.     instructions : @ws2812_program_instructions;
  28.     length : 4;
  29.     origin : -1;
  30. );
  31.  
  32. function ws2812_program_get_default_config(offset : longWord):Tpio_sm_config;
  33. begin
  34.   Result := pio_get_default_sm_config();
  35.   sm_config_set_wrap(Result, offset + ws2812_wrap_target, offset + ws2812_wrap);
  36.   sm_config_set_sideset(Result, 1, false, false);
  37. end;
  38.  
  39.  
  40. procedure ws2812_program_init(var pio : TPIO_Registers; sm : longWord; offset : longWord; pin : TPinIdentifier; freq : Real; rgbw : boolean);
  41. var
  42.   c : Tpio_sm_config;
  43.   cycles_per_bit : longWord;
  44.   &div : real;
  45. begin
  46.   pio_gpio_init(pio, pin);
  47.   pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
  48.   c := ws2812_program_get_default_config(offset);
  49.   sm_config_set_sideset_pins(c, pin);
  50.   if rgbw = true then
  51.     sm_config_set_out_shift(c, false, true, 32)
  52.   else
  53.     sm_config_set_out_shift(c, false, true, 24);
  54.   sm_config_set_fifo_join(c, PIO_FIFO_JOIN_TX);
  55.   cycles_per_bit := ws2812_T1 + ws2812_T2 + ws2812_T3;
  56.   &div := clock_get_hz(clk_sys) / (freq * cycles_per_bit);
  57.   sm_config_set_clkdiv(c, &div);
  58.   pio_sm_init(pio, sm, offset, c);
  59.   pio_sm_set_enabled(pio, sm, true);
  60. end;
  61.  
  62.  
  63. // --------------- //
  64. // ws2812_parallel //
  65. // --------------- //
  66.  
  67. const ws2812_parallel_wrap_target=0;
  68. const ws2812_parallel_wrap=3;
  69.  
  70. const ws2812_parallel_T1=2;
  71. const ws2812_parallel_T2=5;
  72. const ws2812_parallel_T3=3;
  73.  
  74. const ws2812_parallel_program_instructions : array of word = (
  75.            //     .wrap_target
  76.     $6020, //  0: out    x, 32
  77.     $a10b, //  1: mov    pins, !null            [1]
  78.     $a401, //  2: mov    pins, x                [4]
  79.     $a103  //  3: mov    pins, null             [1]
  80.            //     .wrap
  81. );
  82.  
  83. const ws2812_parallel_program : Tpio_program = (
  84.     instructions : @ws2812_parallel_program_instructions;
  85.     length : 4;
  86.     origin : -1;
  87. );
  88.  
  89. function ws2812_parallel_program_get_default_config(offset : longWord):Tpio_sm_config;
  90. begin
  91.   Result := pio_get_default_sm_config();
  92.   sm_config_set_wrap(Result, offset + ws2812_parallel_wrap_target, offset + ws2812_parallel_wrap);
  93. end;
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: jb007 on August 06, 2022, 08:09:20 pm

https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf

https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf

MarkMLl

Thanks!
At first quickview these documents, it will defenitely give me more understanding.

( Last few days I was studying the rp2040-datasheet itself ).
 
Tnx also for the other replies, it will take a while for me to understand the content!

Kind regards.





Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MiR on August 06, 2022, 08:11:00 pm
There also need to be a few changes in the pio file for the freepascal specific code:

Code: Text  [Select][+][-]
  1. .wrap_target
  2. bitloop:
  3.     out x, 1       side 0 [T3 - 1] ; Side-set still takes place when instruction stalls
  4.     jmp !x do_zero side 1 [T1 - 1] ; Branch on the bit we shifted out. Positive pulse
  5. do_one:
  6.     jmp  bitloop   side 1 [T2 - 1] ; Continue driving high, for a long pulse
  7. do_zero:
  8.     nop            side 0 [T2 - 1] ; Or drive low, for a short pulse
  9. .wrap
  10.  
  11. % c-sdk {
  12. #include "hardware/clocks.h"
  13.  
  14. static inline void ws2812_program_init(PIO pio, uint sm, uint offset, uint pin, float freq, bool rgbw) {
  15.  
  16.     pio_gpio_init(pio, pin);
  17.     pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
  18.  
  19.     pio_sm_config c = ws2812_program_get_default_config(offset);
  20.     sm_config_set_sideset_pins(&c, pin);
  21.     sm_config_set_out_shift(&c, false, true, rgbw ? 32 : 24);
  22.     sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
  23.  
  24.     int cycles_per_bit = ws2812_T1 + ws2812_T2 + ws2812_T3;
  25.     float div = clock_get_hz(clk_sys) / (freq * cycles_per_bit);
  26.     sm_config_set_clkdiv(&c, div);
  27.  
  28.     pio_sm_init(pio, sm, offset, &c);
  29.     pio_sm_set_enabled(pio, sm, true);
  30. }
  31. %}
  32.  
  33. % freepascal {
  34.  
  35. procedure ws2812_program_init(var pio : TPIO_Registers; sm : longWord; offset : longWord; pin : TPinIdentifier; freq : Real; rgbw : boolean);
  36. var
  37.   c : Tpio_sm_config;
  38.   cycles_per_bit : longWord;
  39.   &div : real;
  40. begin
  41.   pio_gpio_init(pio, pin);
  42.   pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
  43.   c := ws2812_program_get_default_config(offset);
  44.   sm_config_set_sideset_pins(c, pin);
  45.   if rgbw = true then
  46.     sm_config_set_out_shift(c, false, true, 32)
  47.   else
  48.     sm_config_set_out_shift(c, false, true, 24);
  49.  
  50.   sm_config_set_fifo_join(c, PIO_FIFO_JOIN_TX);
  51.   cycles_per_bit := ws2812_T1 + ws2812_T2 + ws2812_T3;
  52.   &div := clock_get_hz(clk_sys) / (freq * cycles_per_bit);
  53.   sm_config_set_clkdiv(c, &div);
  54.   pio_sm_init(pio, sm, offset, c);
  55.   pio_sm_set_enabled(pio, sm, true);
  56. end;
  57.  
  58. %}
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MarkMLl on August 06, 2022, 09:21:05 pm
/Very/ nicely done. It occurs to me that getting that patch into the SDK- including modified PIO files- would be a /very/ good advert for FPC since anybody looking at the PIO files will see it.

Might also be better to use "object-pascal" rather than "freepascal", which would be in line with the way that the other targets specify a language but not an implementation.

MarkMLl
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MiR on August 07, 2022, 01:37:35 pm
Unfortunately pio needs spinlocks, not sure if it is enough to simply reset them on runtime init or if more complex work is needed.

So for now I'd advise not to spend much time on this unless you are willing to really dig deep.

If there is a simple solution I will come back here, if things are more complex I will first have to rethink the overall integration with the switch to pico sdk 1.4.

 
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MarkMLl on August 07, 2022, 02:16:27 pm
What you've done is certainly very interesting, and I'm sure (or at least fervently hope) that I'm not the only person that appreciates it.

As I've noted elsewhere, I'm a little uncertain as to the extent to which the appropriate SDK version is /required/ for a particular Pico iteration. For example, I'm still not sure about this but I /suspect/ the the onboard LED has been moved to a different electrical signal for the -W.

And however much the RPi foundation loves it, I'm very much inclined to avoid Visual Studio which once installed appears to leave a Trojan running on a Linux system.

MarkMLl
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MiR on August 07, 2022, 07:59:10 pm
success...

I managed to make pio work with fortunately very little extra changes.

please pull

https://github.com/michael-ring/pico-fpcexamples

and enjoy!

Michael
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: jb007 on August 07, 2022, 08:29:59 pm
Hi,

 tnx for all the repleis and guidelines etc.

I decided ( al least for the coming time ) not to dive into all off the stuff
'cause it is getting too much/difficult for me right now...
Again all, the replies are apriciated!

Next step is to use the example spi_st7735 ( got the screens allready ) and the serial uart example.
Allready have made a nice setup with AVR mega2560 ( 2560 core pcb ).

Designed and made some pcb's myself. Here some pcb's combined.
https://www.youtube.com/watch?v=XCanufiR4r4&list=PLcCKmeWXkrzRS5It-4WRdyveafrhZfa_2&index=2

The pico wil be ad later and via Tx/Rx conencted to mega2560.

PCB's designed/routed with Altium's CircuitMaker. PCB produced by JLC pcb.
Soldered all the components myself.

For testing the 2560 is connected to pc ( later it will be by RC  a DIY transmitter ).

pc to mega2560: https://www.youtube.com/watch?v=bSEvQQRRrq8&t=2s

Fot those interrested, one can checkout the rest on same youtubecahnnel as above.t
to see the DIY truck, modified excavator etc.https://www.youtube.com/channel/UCGfykOE4EGG5v1ArdRYYOCw/playlists

Michaels Ring, thank you very much again for you examples!
They are very good for me to continue the PICO-things I want to achieve.

Kind regards. Marcel


Soon, I'll post my ws2812b code when it's ready and clear.











Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: jb007 on August 08, 2022, 09:14:10 pm
success...

I managed to make pio work with fortunately very little extra changes.

please pull

https://github.com/michael-ring/pico-fpcexamples

and enjoy!




Michael


Well done!




 

Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: PascalDragon on August 08, 2022, 10:34:30 pm
At present that's quite a biggy. My understanding is that the new (~FPC 3.3) attribute specification can be used for target-specific things like specifying linkage sections (as well as its nominal role for decorating types), but I've not seen any suggestion that this can be generalised to do things like invoking pioasm.

FPC 3.2.0 already supports the section NAME directive on embedded targets (e.g. section '.progmem' on AVR).
Also you can use tools like data2inc to convert binary data to include files that are essentially arrays of Byte. You just need to invoke tools that generate the binary data from the PIO assembly source (Lazarus can do this with the before-built step).
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MarkMLl on August 08, 2022, 10:56:06 pm
FPC 3.2.0 already supports the section NAME directive on embedded targets (e.g. section '.progmem' on AVR).
Also you can use tools like data2inc to convert binary data to include files that are essentially arrays of Byte. You just need to invoke tools that generate the binary data from the PIO assembly source (Lazarus can do this with the before-built step).

Thanks for that, other people didn't mention it when I raised something related to noinit a few days ago.

MarkMLl
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: PascalDragon on August 08, 2022, 11:30:27 pm
FPC 3.2.0 already supports the section NAME directive on embedded targets (e.g. section '.progmem' on AVR).
Also you can use tools like data2inc to convert binary data to include files that are essentially arrays of Byte. You just need to invoke tools that generate the binary data from the PIO assembly source (Lazarus can do this with the before-built step).

Thanks for that, other people didn't mention it when I raised something related to noinit a few days ago.

But ccrause had done so here (https://forum.lazarus.freepascal.org/index.php/topic,60158.msg449208.html#msg449208)?
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MarkMLl on August 09, 2022, 09:11:00 am
But ccrause had done so here (https://forum.lazarus.freepascal.org/index.php/topic,60158.msg449208.html#msg449208)?

Sorry, you're right.

MarkMLl
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: PascalDragon on August 09, 2022, 01:22:35 pm
But ccrause had done so here (https://forum.lazarus.freepascal.org/index.php/topic,60158.msg449208.html#msg449208)?

Sorry, you're right.

No problem. :)
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: jb007 on August 18, 2022, 08:53:33 pm
Hi,

 gonna redo my ws2812 code.

Didn't know this, to get a bit out of a byte, now I do:

https://www.delphipraxis.net/1134-bits-eines-bytes-auslesen.html
function TestBit(aByte: Byte; aBitNum: Integer): Boolean;
   begin
      Result := (aByte and (1 shl aBitNum)) > 0;
   end;

Before I was only used to use e.g.: bit:= byte.5 to single out bit5.

I realize now that something simulair is used to set an outputPin to One/Zero!
( due of the Michel's examples )

Now, 'calculating the RGB 3-bytes' makes more sense and is easier, like I used to do on AVR/ws2812b.

I wil not to go to deep in details.

Kind regards.














Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MarkMLl on August 18, 2022, 10:40:44 pm
I would /hope/ that that byte.5 notation, since it's something supported by the compiler, is more efficient.

MarkMLl
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: PascalDragon on August 19, 2022, 09:02:39 am
function TestBit(aByte: Byte; aBitNum: Integer): Boolean;
   begin
      Result := (aByte and (1 shl aBitNum)) > 0;
   end;

You should declare that as inline so the compiler can optimize this better (especially important on smaller platforms ;) ).

Before I was only used to use e.g.: bit:= byte.5 to single out bit5.

What do you mean with that?

I realize now that something simulair is used to set an outputPin to One/Zero!
( due of the Michel's examples )

Well, that's normal bit manipulation. Maybe you should read up on that as these are very common operations on microcontrollers.
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: jb007 on August 19, 2022, 08:28:21 pm
I would /hope/ that that byte.5 notation, since it's something supported by the compiler, is more efficient.

MarkMLl


That was first thing I did, a time ago, but didn't work.

First gonna try that again!
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: jb007 on August 20, 2022, 07:10:24 pm
Same error again as I started on pi-PICO.

'illigal qualifier indentifier expected but ordinal const found'

initial I started with:


procedure bitByteStuff;   
var
   bBit: boolean;
   byByte: byte:
begin
   bByte:= 127;
   bBit:= byByte.4;  // illigal qualifier indentifier expected but ordinal const found

end; // p\


it's the .4 what Lazarus doens't want!
At least in my IDE.



Then I played/messed around, with types, but that diddn't change the .4 error:


procedure bitByteStuff;   // how to get a bit out of a byte
var                               // regualr pascal bit4:= byte.4
  byByte: byte;
  iByte : integer;

   bBit: boolean;
  byBit: byte;
   iBit: integer;

  byNumber: byte;
   iNumber: integer;


begin
  byByte:= 127;
  iByte := 127;

  byNumber:= 4;
   iNumber:= 4;

  //bBit := byByte.4;  // illigal qualifier indentifier expected but ordinal const found
  //byBit:= byByte.4; // illigal qualifier indentifier expected but ordinal const found
  //iBit := byByte.4;  // illigal qualifier indentifier expected but ordinal const found

  //bBit := iByte.4;    //illigal qualifier indentifier expected but ordinal const found
  //byBit:= iByte.4;   // illigal qualifier indentifier expected but ordinal const found
  //iBit := iByte.4;    // illigal qualifier indentifier expected but ordinal const found


// I know some of above don't make sense, with or without the error, but ok.


end; // p\bitByteStuff   



procedure from mikroPascal. ws2812b on AVR2560. working code on ATMEGA2560:
 
  procedure tstBitByte;
  var
    byOneByte: byte;
    bOneBit: boolean;
    iOneBit: integer;
  begin
    byOneByte:= 255;
    bOneBit:= byOneByte.4;
    iOneBit:= byOneByte.4;

  end; // p\



Kind regards!






Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: PascalDragon on August 20, 2022, 08:36:44 pm
procedure from mikroPascal. ws2812b on AVR2560. working code on ATMEGA2560:

That would explain this then. This kind of syntax is simply not supported in Free Pascal.

But you can simulate something similar using type helpers:

Code: Pascal  [Select][+][-]
  1. program ttypehlp;
  2.  
  3. {$mode objfpc}{$H+}
  4. {$modeswitch typehelpers}
  5.  
  6. uses
  7.   SysUtils;
  8.  
  9. type
  10.   TByteHelper = type helper for Byte
  11.   public type
  12.     TBitRange = 0..7;
  13.   private
  14.     function GetBits(aIndex: TBitRange): Boolean; inline;
  15.     procedure SetBits(aIndex: TBitRange; aValue: Boolean); inline;
  16.   public
  17.     property Bits[Index: TBitRange]: Boolean read GetBits write SetBits;
  18.   end;
  19.  
  20. function TByteHelper.GetBits(aIndex: TBitRange): Boolean; inline;
  21. begin
  22.   Result := (Self and (1 shl aIndex)) <> 0;
  23. end;
  24.  
  25. procedure TByteHelper.SetBits(aIndex: TBitRange; aValue: Boolean); inline;
  26. begin
  27.   Self := (Self and not (1 shl aIndex)) or (Ord(aValue) shl aIndex);
  28. end;
  29.  
  30. var
  31.   b: Byte;
  32.   i: SmallInt;
  33. begin
  34.   b := %10110110;
  35.   for i := 0 to 7 do
  36.     Writeln('Bit ', i, ': ', b.Bits[i]);
  37.  
  38.   b.Bits[3] := True;
  39.   b.Bits[7] := False;
  40.  
  41.   Writeln(BinStr(b, 8));
  42. end.
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MiR on August 20, 2022, 09:19:55 pm
When trying to optimize stuff that lowlevel it is often helping to look at the generated assembler code to see if you have a good solution or not.

Adding -a to the commandline does the trick.

Michael
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: jb007 on August 21, 2022, 10:29:22 am
Ok, not allowed!

Then I go back to my initial method:

type
  tLightLEDS = array[0..191] of boolean; // 8x24 bit   
var
  lightBL: tLightLEDS;
  lightBR: tLightLEDS;

begin
  // determ/wrtie array, 192-bits, non time critical,



  // procedure writeLedbar( 'barNr' )  // time critical, code is sollid from it self!

     for 0-191 loop

     'write' array to outPutpin 'barNr' using:

//logic ONE
  sio.gpio_set := 1 shl pinNr;  //   800
  for byCntr:= 0 to 4 do;            // = 720
  sio.gpio_clr := 1 shl pinNr;  //   400
  for byCntr:= 0 to 1 do;            // = 420 

//logic ZERO
  sio.gpio_set := 1 shl pinNr;  //   400
  for byCntr:= 0 to 1 do;            // = 320
  sio.gpio_clr := 1 shl pinNr;  //   800
  for byCntr:= 0 to 4 do;            // = 820 

It's ok with this!














Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: MarkMLl on August 21, 2022, 10:32:20 am
Ok, not allowed!

  tLightLEDS = array[0..191] of boolean; // 8x24 bit   

Hint: please use the forum's code tags. Things like array subscripts will get badly messed up if you don't, making life far more difficult for people trying to help you.

MarkMLl
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: jb007 on August 21, 2022, 10:42:46 am
Ok, not allowed!

  tLightLEDS = array[0..191] of boolean; // 8x24 bit   

Hint: please use the forum's code tags. Things like array subscripts will get badly messed up if you don't, making life far more difficult for people trying to help you.

MarkMLl

Thanks foor the hint!
Title: Re: pi PICO controlling ws2812b leds, ledstrips
Post by: jb007 on November 07, 2022, 07:39:51 pm
Hi,

 unfortunately I'm not sure how my code can be usefull for others.

I'll keep it by the funcioning NTR-protocol one's and zero's, as in previous comments.

Coming time I'm dive into the other example-codes.

Tnx again. Michael!

Kind regards. Marcel



TinyPortal © 2005-2018