Do not forget. Hardware needs root rights. PB so start with sudo
Update v1.01.6
WS2811.pbi
Code: Select all
;TOP
; Comment : Userspace Raspberry Pi library for controlling WS281X LEDs.
; Author  : mk-soft
; Version : v1.01.6
; Create  : 21.12.2021
; Update  : 28.12.2021
; Lisence : MIT and see github project
; Library : https://github.com/jgarff/rpi_ws281x
; Compile library: (See github projekt)
; -------------------------------------
;
; Open terminal:
;
; first install cmake:
;
;   sudo apt-get install cmake
; 
; also if git is not installed, install it:
;
;   sudo apt-get install git
; 
; now get the repository from the web:
;
;   git clone https://github.com/jgarff/rpi_ws281x.git
; 
; then go to the new directory:
;
;   cd rpi_ws281x
;
; follow:
;   mkdir build
;   cd build
;   cmake -D BUILD_SHARED=ON -D BUILD_TEST=OFF .. <--- don't forget double dots ;)
;   cmake --build . <--- don't forget dot ;)
;   sudo make install
; *********
EnableExplicit
  
; Header pwm.h
#RPI_PWM_CHANNELS = 2
; Header ws2811.h
#WS2811_TARGET_FREQ                     = 800000    ; Can go As low As 400000
#WS2811_TARGET_FREQ_LOW                 = 400000
; 4 color R, G, B And W ordering
#SK6812_STRIP_RGBW                      = $18100800
#SK6812_STRIP_RBGW                      = $18100008
#SK6812_STRIP_GRBW                      = $18081000
#SK6812_STRIP_GBRW                      = $18080010
#SK6812_STRIP_BRGW                      = $18001008
#SK6812_STRIP_BGRW                      = $18000810
#SK6812_SHIFT_WMASK                     = $f0000000
; 3 color R, G And B ordering
#WS2811_STRIP_RGB                       = $00100800
#WS2811_STRIP_RBG                       = $00100008
#WS2811_STRIP_GRB                       = $00081000
#WS2811_STRIP_GBR                       = $00080010
#WS2811_STRIP_BRG                       = $00001008
#WS2811_STRIP_BGR                       = $00000810
; predefined fixed LED types
#WS2812_STRIP                           = #WS2811_STRIP_GRB
#SK6812_STRIP                           = #WS2811_STRIP_GRB
#SK6812W_STRIP                          = #SK6812_STRIP_GRBW
;struct ws2811_device;
;typedef uint32_t ws2811_led_t;                   //< 0xWWRRGGBB
Structure ws2811_led_t
  Led.l[0]
EndStructure
;typedef struct ws2811_channel_t
Structure ws2811_channel_t Align #PB_Structure_AlignC
  ;{
  gpionum.l         ; //< GPIO Pin with PWM alternate function, 0 if unused
  invert.l          ; //< Invert output signal
  count.l           ; //< Number of LEDs, 0 if channel is unused
  strip_type.l      ; //< Strip color layout -- one of WS2811_STRIP_xxx constants
  *leds.ws2811_led_t; //< LED buffers, allocated by driver based on count
  brightness.a      ; //< Brightness value between 0 and 255
  wshift.a          ; //< White shift value
  rshift.a          ; //< Red shift value
  gshift.a          ; //< Green shift value
  bshift.a          ; //< Blue shift value
  *gamma            ; //< Gamma correction table
EndStructure
;typedef struct ws2811_t
Structure ws2811_t Align #PB_Structure_AlignC
  ;{
  render_wait_time.q; //< time in µs before the next render can run
  *device           ; //< Private data for driver use
  *rpi_hw           ; //< RPI Hardware Information
  freq.l            ; //< Required output frequency
  dmanum.l          ; //< DMA number _not_ already in use
  channel.ws2811_channel_t[#RPI_PWM_CHANNELS];
EndStructure  
;#define WS2811_RETURN_STATES(X)
#WS2811_SUCCESS = 0                 ; "Success"
#WS2811_ERROR_GENERIC = -1          ; "Generic failure"
#WS2811_ERROR_OUT_OF_MEMORY = -2    ; "Out of memory"
#WS2811_ERROR_HW_NOT_SUPPORTED = -3 ; "Hardware revision is not supported"
#WS2811_ERROR_MEM_LOCK = -4         ; "Memory lock failed"
#WS2811_ERROR_MMAP = -5             ; "mmap() failed"
#WS2811_ERROR_MAP_REGISTERS = -6    ; "Unable to map registers into userspace"
#WS2811_ERROR_GPIO_INIT = -7        ; "Unable to initialize GPIO"
#WS2811_ERROR_PWM_SETUP = -8        ; "Unable to initialize PWM"
#WS2811_ERROR_MAILBOX_DEVICE = -9   ; "Failed to create mailbox device"
#WS2811_ERROR_DMA = -10             ; "DMA error"
#WS2811_ERROR_ILLEGAL_GPIO = -11    ; "Selected GPIO not possible"
#WS2811_ERROR_PCM_SETUP = -12       ; "Unable to initialize PCM"
#WS2811_ERROR_SPI_SETUP = -13       ; "Unable to initialize SPI"
#WS2811_ERROR_SPI_TRANSFER = -14    ; "SPI transfer error"
; ws2811_return_t ws2811_init(ws2811_t *ws2811);                              //< Initialize buffers/hardware
; void ws2811_fini(ws2811_t *ws2811);                                         //< Tear it all down
; ws2811_return_t ws2811_render(ws2811_t *ws2811);                            //< Send LEDs off to hardware
; ws2811_return_t ws2811_wait(ws2811_t *ws2811);                              //< Wait for DMA completion
; const char * ws2811_get_return_t_str(const ws2811_return_t state);          //< Get string representation of the given return state
; void ws2811_set_custom_gamma_factor(ws2811_t *ws2811, double gamma_factor); //< Set a custom Gamma correction array based on a gamma correction factor
PrototypeC ws2811_init(*ws2811.ws2811_t);                                     //< Initialize buffers/hardware
PrototypeC ws2811_fini(*ws2811.ws2811_t);                                     //< Tear it all down
PrototypeC ws2811_render(*ws2811.ws2811_t);                                   //< Send LEDs off to hardware
PrototypeC ws2811_wait(*ws2811.ws2811_t)  ;                                   //< Wait for DMA completion
PrototypeC ws2811_get_return_t_str(ws2811_return_t_state);                    //< Get string representation of the given return state
PrototypeC ws2811_set_custom_gamma_factor(*ws2811.ws2811_t, gamma_factor.d);  //< Set a custom Gamma correction array based on a gamma correction factor
Global libws2811
Procedure InitLib_ws2811(pathlib.s = "libws2811.so")
  libws2811 = OpenLibrary(#PB_Any, pathlib)
  If libws2811
    Global ws2811_init.ws2811_init = GetFunction(libws2811, "ws2811_init")
    Global ws2811_fini.ws2811_fini = GetFunction(libws2811, "ws2811_fini")
    Global ws2811_render.ws2811_render = GetFunction(libws2811, "ws2811_render")
    Global ws2811_wait.ws2811_wait = GetFunction(libws2811, "ws2811_wait")
    Global __ws2811_get_return_t_str.ws2811_get_return_t_str = GetFunction(libws2811, "ws2811_get_return_t_str")
    Global ws2811_set_custom_gamma_factor.ws2811_set_custom_gamma_factor = GetFunction(libws2811, "ws2811_set_custom_gamma_factor")
  EndIf
  ProcedureReturn libws2811
EndProcedure
Procedure.s ws2811_get_return_t_str(state)
  Protected *state
  *state = __ws2811_get_return_t_str(state)
  If *state
    ProcedureReturn PeekS(*state, -1, #PB_UTF8)
  EndIf
EndProcedure
Procedure CloseLib_ws2811()
  CloseLibrary(libws2811)
EndProcedure
;- Example ws2812b (4 LEDs on GPIO 18 PWM)
CompilerIf #PB_Compiler_IsMainFile
  
  EnableExplicit
  
  ;IncludeFile "WS2811.pbi"
  
  If Not InitLib_ws2811()
    Debug "Error open library ws2811"
    End
  EndIf
  
  #TARGET_FREQ = #WS2811_TARGET_FREQ  ; Default 800000
  #GPIO_PIN = 18
  #DMA = 10
  ; #STRIP_TYPE = WS2811_STRIP_RGB    ; WS2812/SK6812RGB integrated chip+leds
  #STRIP_TYPE = #WS2811_STRIP_GRB     ; WS2812/SK6812RGB integrated chip+leds
  ;#STRIP_TYPE = #SK6812_STRIP_RGBW	  ; SK6812RGBW (Not SK6812RGB)
  #LED_COUNT = 4
  
  Global ledstring.ws2811_t
  Global r1
  
  With ledstring
    \freq = #TARGET_FREQ
    \dmanum = #DMA
    \channel[0]\gpionum = #GPIO_PIN
    \channel[0]\count = #LED_COUNT
    \channel[0]\invert = 0
    \channel[0]\brightness = 255
    \channel[0]\strip_type = #STRIP_TYPE
    
    Repeat ; Do
      r1 = ws2811_init(ledstring)
      If r1 <> #WS2811_SUCCESS
        Debug "Error Init: " + ws2811_get_return_t_str(r1)
        CloseLib_ws2811()
        End
      EndIf
      
      ; LEDs 0xWWRRGGBB
      \channel[0]\leds\led[0] = $00FF0000
      \channel[0]\leds\led[1] = $0000FF00
      \channel[0]\leds\led[2] = $000000FF
      \channel[0]\leds\led[3] = $00FFFFFF
      r1 = ws2811_render(ledstring)
      If r1 <> #WS2811_SUCCESS
        Debug "Error Render: " + ws2811_get_return_t_str(r1)
        Break
      EndIf
      ws2811_wait(ledstring)
      Delay(2000)
      
      ; LEDs
      \channel[0]\leds\led[0] = $00FFFFFF
      \channel[0]\leds\led[1] = $00FF0000
      \channel[0]\leds\led[2] = $0000FF00
      \channel[0]\leds\led[3] = $000000FF
      r1 = ws2811_render(ledstring)
      If r1 <> #WS2811_SUCCESS
        Debug "Error Render: " + ws2811_get_return_t_str(r1)
        Break
      EndIf
      ws2811_wait(ledstring)
      Delay(2000)
      
      ; LEDs
      \channel[0]\leds\led[0] = $000000FF
      \channel[0]\leds\led[1] = $00FFFFFF
      \channel[0]\leds\led[2] = $00FF0000
      \channel[0]\leds\led[3] = $0000FF00
      r1 = ws2811_render(ledstring)
      If r1 <> #WS2811_SUCCESS
        Debug "Error Render: " + ws2811_get_return_t_str(r1)
        Break
      EndIf
      ws2811_wait(ledstring)
      Delay(2000)
      
      \channel[0]\leds\led[0] = $00000000
      \channel[0]\leds\led[1] = $00000000
      \channel[0]\leds\led[2] = $00000000
      \channel[0]\leds\led[3] = $00000000
      r1 = ws2811_render(ledstring)
      If r1 <> #WS2811_SUCCESS
        Debug "Error Render: " + ws2811_get_return_t_str(r1)
        Break
      EndIf
      Delay(1000)
      
      \channel[0]\leds\led[0] = $0000FF00
      \channel[0]\leds\led[1] = $0000FF00
      \channel[0]\leds\led[2] = $0000FF00
      \channel[0]\leds\led[3] = $0000FF00
      r1 = ws2811_render(ledstring)
      If r1 <> #WS2811_SUCCESS
        Debug "Error Render: " + ws2811_get_return_t_str(r1)
        Break
      EndIf
      Delay(1000)
      
      \channel[0]\leds\led[0] = $00000000
      \channel[0]\leds\led[1] = $00000000
      \channel[0]\leds\led[2] = $00000000
      \channel[0]\leds\led[3] = $00000000
      r1 = ws2811_render(ledstring)
      If r1 <> #WS2811_SUCCESS
        Debug "Error Render: " + ws2811_get_return_t_str(r1)
        Break
      EndIf
      Delay(1000)
      
    Until #True ; EndDo
  EndWith
  
  ; Clear controler - DMA, etx
  ws2811_fini(ledstring)
  ; Close library
  CloseLib_ws2811()
  
CompilerEndIf


