Pascal Neopixels

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Pascal Neopixels

Anthony Walter-3
I'm not sure what would be the correct list for this question since it involves writing Pascal code and not Lazarus, so here goes ...

Can anyone offer me any advice or refer me to helpful resources on the subject of using Pascal code to control WS2128 led strips, or neopixels, from a Raspberry Pi?

I've wired up a some neopixels and am able to control them by way of PWM (pulse wave modulation) on GPIO 18 (pin 12 on a Pi 3) using this rpi_ws281x git repository. It works great either in C or using Python bindings, and I am able to create effects in C code easily. But obviously I'd prefer to interface with the neopixels using Pascal.

I've seen some Pascal libraries for both GPIO access, and DMA pin mapping, but the communication protocol for controlling neopixels is a bit more complex than writing a 24 bit value to a pin. Each pixel can be controlled in both brightness and color, though I'm unsure how the wx281x library is doing this.

Assuming I was to do this in from scratch  Pascal, that is control the colors and brightness of many pixels withing an entire neopixel strip, I believe I need to do the following in psuedo code.

  // open device memory
  fd = open('/dev/mem')
  // map the file descriptor to the memory address of gpio18
  gpio18 = mmap(fd, ...)
  // fd is no longer needed
  close(fd)
  
  [ then write to gpio18 in some loop as a data structure ]
  
  // cleanup
  unmap(gpio18)

If that psuedo code is the correct way to do things, I would need to know what is the offset and page size for PWM GPIO18, what flags to use with mmap, and finally what memory locations inside of the gpio18 pointer control which pixel, what is the brightness memory location and size, what is the color memory location and size for each pixel. Also, is there any other memory location inside gpio18 that is of importance or relevance, such as an on/off bit?

Does anyone have any insight into this subject that might be useful? After I get something that works I'll be sure to share the resulting Pascal code and a video plus tutorial.

TIA

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Pascal Neopixels

DaWorm
You should be able to use the library from Pascal directly rather than trying to recreate it from scratch. 

Jeff 

On Sun, Jul 29, 2018, 10:20 AM Anthony Walter <[hidden email]> wrote:
I'm not sure what would be the correct list for this question since it involves writing Pascal code and not Lazarus, so here goes ...

Can anyone offer me any advice or refer me to helpful resources on the subject of using Pascal code to control WS2128 led strips, or neopixels, from a Raspberry Pi?

I've wired up a some neopixels and am able to control them by way of PWM (pulse wave modulation) on GPIO 18 (pin 12 on a Pi 3) using this rpi_ws281x git repository. It works great either in C or using Python bindings, and I am able to create effects in C code easily. But obviously I'd prefer to interface with the neopixels using Pascal.

I've seen some Pascal libraries for both GPIO access, and DMA pin mapping, but the communication protocol for controlling neopixels is a bit more complex than writing a 24 bit value to a pin. Each pixel can be controlled in both brightness and color, though I'm unsure how the wx281x library is doing this.

Assuming I was to do this in from scratch  Pascal, that is control the colors and brightness of many pixels withing an entire neopixel strip, I believe I need to do the following in psuedo code.

  // open device memory
  fd = open('/dev/mem')
  // map the file descriptor to the memory address of gpio18
  gpio18 = mmap(fd, ...)
  // fd is no longer needed
  close(fd)
  
  [ then write to gpio18 in some loop as a data structure ]
  
  // cleanup
  unmap(gpio18)

If that psuedo code is the correct way to do things, I would need to know what is the offset and page size for PWM GPIO18, what flags to use with mmap, and finally what memory locations inside of the gpio18 pointer control which pixel, what is the brightness memory location and size, what is the color memory location and size for each pixel. Also, is there any other memory location inside gpio18 that is of importance or relevance, such as an on/off bit?

Does anyone have any insight into this subject that might be useful? After I get something that works I'll be sure to share the resulting Pascal code and a video plus tutorial.

TIA
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Pascal Neopixels

Michael Ring-2
In reply to this post by Anthony Walter-3

For me, the easiest way to solve this (on a microcontroller, not a raspberry) was using SPI, you can create a pretty precise timing with that method. And looking at the code in the repository you provided it looks like the SPI of the Raspberry is DMA-Enabled in kernel.


In my own code I use 16Bit SPI for finer resolution, but the same principle applies to 8Bit SPI, the only important thing here is to keep the line long enough on low to generate the proper timing.

Basic idea is to define a pattern for zero's ond ones:

  ZeroPattern := %0111000000000000;
  OnePattern  := %0111111000000000;


those patterns define either a zero or a one bit and you need a total of 24*this 16bit Pattern to make one Neopixel glow in the selected color. When you run SPI at 8Mhz then every bit in the pattern represents 125 microseconds and you now simply set as much "1" bits as you need to reach the proper timing of the neopixels. it is important to have the highest bit in the pattern set to '0' so that the neopixel can properly detect the 0->1 change.

You can also use 8Bit Patterns, this saves a little memory but you will have to reduce the SPI Frequency to 4MHz (will give you 250 microseconds per bit)

Once you have filled up a buffer with the proper Patterns you can send the buffer to /dev/spidev0.0 and the linux kernel should take over and send the data as a continous bitstream.

Here's an example on how to create this 16 bit buffer, you start with an array of TColor that you fill with the color value of each neopixel you want to use

var

  FRGBPixel: array of TColor;

and then you iterate through the array and write the Bit-Patterns for each Neopixel:

    for i := 0 to MaxPixelCount - 1 do
    begin
      //BRG format needed for APA106, also often RGB format is used, simply change the pixel shifting here
      Value := ((FRGBPixel[i] shl 8) and $00ffff00) or ((FRGBPixel[i] shr 16) and $ff);
      Mask := 1 shl 23;
      for j := 0 to 23 do
      begin
        if (Value and Mask) = 0 then
          WriteBuffer[j+i*24] := ZeroPattern
        else
          // Send 1 Bit
          WriteBuffer[j+i*24] := OnePattern;
        Mask := Mask shr 1;
      end;
    end;


Now you have a properly built WriteBuffer that you cen send to the SPI Device.

The only other thing you should need to do is to convert the

ws2811_return_t spi_init(ws2811_t *ws2811)

startup code or look at this page:

http://wiki.freepascal.org/Raspberry_Pi_-_SPI/de

for the lowlevel initialization stuff of SPI, although I am not sure if DMA is enabled in this example, I never used this code.

Michael




Am 29.07.18 um 16:19 schrieb Anthony Walter:
I'm not sure what would be the correct list for this question since it involves writing Pascal code and not Lazarus, so here goes ...

Can anyone offer me any advice or refer me to helpful resources on the subject of using Pascal code to control WS2128 led strips, or neopixels, from a Raspberry Pi?

I've wired up a some neopixels and am able to control them by way of PWM (pulse wave modulation) on GPIO 18 (pin 12 on a Pi 3) using this rpi_ws281x git repository. It works great either in C or using Python bindings, and I am able to create effects in C code easily. But obviously I'd prefer to interface with the neopixels using Pascal.

I've seen some Pascal libraries for both GPIO access, and DMA pin mapping, but the communication protocol for controlling neopixels is a bit more complex than writing a 24 bit value to a pin. Each pixel can be controlled in both brightness and color, though I'm unsure how the wx281x library is doing this.

Assuming I was to do this in from scratch  Pascal, that is control the colors and brightness of many pixels withing an entire neopixel strip, I believe I need to do the following in psuedo code.

  // open device memory
  fd = open('/dev/mem')
  // map the file descriptor to the memory address of gpio18
  gpio18 = mmap(fd, ...)
  // fd is no longer needed
  close(fd)
  
  [ then write to gpio18 in some loop as a data structure ]
  
  // cleanup
  unmap(gpio18)

If that psuedo code is the correct way to do things, I would need to know what is the offset and page size for PWM GPIO18, what flags to use with mmap, and finally what memory locations inside of the gpio18 pointer control which pixel, what is the brightness memory location and size, what is the color memory location and size for each pixel. Also, is there any other memory location inside gpio18 that is of importance or relevance, such as an on/off bit?

Does anyone have any insight into this subject that might be useful? After I get something that works I'll be sure to share the resulting Pascal code and a video plus tutorial.

TIA


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Pascal Neopixels

Anthony Walter-3
Thanks Michael, that's some good information. I'll poke around with Pascal using the information you provided and see if I can turn an LED on/off, set its color and brightness, and whatever else then post back here with the results.

If anyone else cares to chime in with advice I'd much appreciate your insights.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Pascal Neopixels

R0b0t1
On Sunday, July 29, 2018, Anthony Walter <[hidden email]> wrote:
> Thanks Michael, that's some good information. I'll poke around with Pascal using the information you provided and see if I can turn an LED on/off, set its color and brightness, and whatever else then post back here with the results.
> If anyone else cares to chime in with advice I'd much appreciate your insights.

There are device nodes you can interact with to drive the I2C/SPI peripherals. This will be cleaner and more portable than interacting with the registers yourself.

There may also be C libraries wrapping the details of the device nodes. Creating headers for and calling that code may or may not save you any work. Some of those libraries, like the devicemode USB one, are very poorly written.

Should you not be able to open the device you may nneed to be root. Also check that a "platform" driver hasn't already claimed it (like for power management bus).

Cheers,
   R0b0t1
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Pascal Neopixels

R0b0t1
In reply to this post by Anthony Walter-3
On Sunday, July 29, 2018, Anthony Walter <[hidden email]> wrote:
> Thanks Michael, that's some good information. I'll poke around with Pascal using the information you provided and see if I can turn an LED on/off, set its color and brightness, and whatever else then post back here with the results.
> If anyone else cares to chime in with advice I'd much appreciate your insights.

There are device nodes you can interact with to drive the I2C/SPI peripherals. This will be cleaner and more portable than interacting with the registers yourself.

There may also be C libraries wrapping the details of the device nodes. Creating headers for and calling that code may or may not save you any work. Some of those libraries, like the devicemode USB one,

Cheers,
   R0b0t1

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal