lgpio 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e24e221cb39d27714d3fdd9486c47dd01e33115980d29e5104a455e14fd40890
4
- data.tar.gz: 4ffd6e35644bc8dcde49486cd43d8e7ca73ebbfe9b46955a8de89a4ecff49d33
3
+ metadata.gz: 84493ab6ca425d960887480b8f186a610fd9e41f0885657c79b5a4038a8a2035
4
+ data.tar.gz: 705d88399e518bdbc167eca65cd795dea2d33936b919aaaf22a34c8be032a1a1
5
5
  SHA512:
6
- metadata.gz: 5060a2fd7a5ef20a1de29f01a87aa2ff2639c9d0e9005594de672d7fa011df48e7a65b893ad4310d07d780f9677c1544ccc80018a5bb4794e014513f4864fae4
7
- data.tar.gz: 16e6a32af1a358ffcf18c7864d2748527f635a83f42734fc3191ecb6eed7fb50cef3ffe4370651b063fde6e4a28bd2075a12b6adb8d04b3e4646353d973515c3
6
+ metadata.gz: 77f3c42ed9a94f8ea0c59acc2cb276efd400990099ac4272f06619645953f6014dbc4a9330d04ed154eee86fabba4791290fcd7201b326f2d6f4b2437a5d5812
7
+ data.tar.gz: 7fd2aa6715e36f3e95d35248b1b13ffb141dca3c50b1ab7a5fbe2e420b67a3873d3de50a24b5eda460a50bd69133492043356715522b27cbe509e280c3174699
data/.gitignore CHANGED
@@ -23,3 +23,4 @@ tmp
23
23
  .ruby-version
24
24
  .rvmrc
25
25
  .zed
26
+ ._*
data/README.md CHANGED
@@ -1,18 +1,24 @@
1
1
  # lgpio
2
2
 
3
- Ruby bindings for the [lgpio (lg)](https://github.com/joan2937/lg) C library, for Linux on single board computers (SBCs), like the Raspberry Pi and its competitors.
4
-
5
- ## Features
6
- - GPIO Read/Write
7
- - GPIO Group Read/Write
8
- - GPIO Alerts / Callbacks
9
- - lg generates alerts at high speed, in a separate thread. In Ruby they can be read from a queue as part of your application loop.
10
- - PWM Output
3
+ Ruby bindings for the [lgpio (lg)](https://github.com/joan2937/lg) Linux library, running on single board computers (SBCs), like Raspberry Pi.
4
+
5
+ ## Standard LGPIO Functions
6
+ - [x] GPIO Read/Write
7
+ - [x] GPIO Group Read/Write
8
+ - [x] GPIO Alerts / Callbacks
9
+ - lg generates alerts at high speed, in a separate thread. In Ruby, they can be read from a queue as part of your application loop.
10
+ - [x] PWM Output
11
11
  - Software timed on any pin. No interface for hardware PWM yet.
12
- - Wave
12
+ - [x] Wave
13
13
  - Software timed on any pin, as with PWM.
14
- - I2C
15
- - SPI
14
+ - [x] I2C
15
+ - [x] SPI
16
+
17
+ ## Extras
18
+ - [x] WS2812 over SPI
19
+ - Only outputs on a SPI MOSI pin. Must be able to set SPI clock frequency to 2.4 MHz.
20
+ - [ ] Bit Bang SPI
21
+ - [ ] Bit Bang I2C
16
22
 
17
23
  ## Installation
18
24
  On Debian-based Linuxes (RaspberryPi OS, Armbian, DietPi etc.):
@@ -33,9 +39,9 @@ gem install lgpio
33
39
  ```
34
40
 
35
41
  ## Enabling Hardware & Permissions
36
- Depending on your SBC and Linux distro/version, you may need to manually enable I2C and SPI hardware. You may use the setup or config tool that came with your distro for that.
42
+ Depending on your SBC and Linux distro/version, you may need to manually enable I2C and SPI hardware. You should use the setup or config tool that came with your distro for that.
37
43
 
38
- You may also not have permission to access some or all of the GPIO and peripherals. To run without `sudo`, you will need read+write permission to some or all of the following devices:
44
+ You may also not have permission to access the GPIO and peripherals. To run without `sudo`, you need read+write permission to some or all of the following devices:
39
45
  ```
40
46
  /dev/gpiochip* (For GPIO, example: /dev/gpiochip0)
41
47
  /dev/i2c-* (For I2C, example: /dev/i2c-1)
@@ -44,11 +50,11 @@ You may also not have permission to access some or all of the GPIO and periphera
44
50
 
45
51
  ## Documentation
46
52
  - See examples folder for demos of every implemented interface.
47
- - Development was done on an Orange Pi Zero 2W. Your GPIO numbers will be different, so change them.
53
+ - Development was done on an Orange Pi Zero 2W. Your GPIO numbers may be different, so change them.
48
54
  - For more info, see the [lgpio C API docs.](https://abyz.me.uk/lg/lgpio.html)
49
55
  - As much as possible, the Ruby methods closely follow the C API functions, except:
50
56
  - Snake case instead of camel case names for methods.
51
57
  - Method names have the leading `lg` removed, since inside the `LGPIO` class.
52
58
  - Constants have leading `LG_` removed, as above.
53
59
  - "count" or "length" arguments associated with array args are not needed.
54
- - Check the return values of your method calls. On failure, they return negative values values, matching the `LG_` error codes at the bottom of the C API doc page.
60
+ - Check the return values of your method calls. On failure, they return negative values, matching the `LG_` error codes at the bottom of the C API doc page.
@@ -1,42 +1,15 @@
1
1
  #
2
- # 2.4 MHz SPI method for writing WS2812 addressable LEDs
3
- # Based on:https://learn.adafruit.com/dma-driven-neopixels/overview
2
+ # 2.4 MHz SPI method for writing WS2812 addressable LEDs.
3
+ # Based on: https://learn.adafruit.com/dma-driven-neopixels/overview
4
4
  #
5
5
  require 'lgpio'
6
6
 
7
- # WS2812 Constants
8
- NP_ONE = 0b110
9
- NP_ZERO = 0b100
10
- NP_START = [0]
11
- NP_END = Array.new(90) { 0 }
12
- BITS = (0..7).to_a.reverse
13
-
14
7
  # SPI Config
15
8
  SPI_DEV = 1
16
9
  SPI_CHAN = 0
17
10
  SPI_MODE = 0
18
11
  SPI_BAUD = 2_400_000
19
12
 
20
- # Map array of pixel values (3 bytes each) to raw SPI bytes (1bit -> 3 bits).
21
- def pixel_to_raw_spi_bytes(pixel_arr)
22
- raw_spi_bytes = []
23
- pixel_arr.flatten.each do |byte|
24
- long = 0b0
25
- for i in BITS do
26
- long = long << 3
27
- if byte[i] == 0
28
- long |= NP_ZERO
29
- else
30
- long |= NP_ONE
31
- end
32
- end
33
- # Pack as big-endian uint32, then unpack to bytes, taking lowest 24 bits only.
34
- long = [long].pack('L>')
35
- raw_spi_bytes << long.unpack('C*')[1..3]
36
- end
37
- return raw_spi_bytes.flatten
38
- end
39
-
40
13
  # 4 pixels: RGBW. Data order per pixel is GRB.
41
14
  pixels_on = [
42
15
  0, 255, 0,
@@ -44,17 +17,14 @@ pixels_on = [
44
17
  0, 0, 255,
45
18
  255, 255, 255,
46
19
  ]
47
- data_on = NP_START + pixel_to_raw_spi_bytes(pixels_on) + NP_END
48
-
49
20
  # 4 pixels, all off.
50
21
  pixels_off = Array.new(12) { 0 }
51
- data_off = NP_START + pixel_to_raw_spi_bytes(pixels_off) + NP_END
52
22
 
53
23
  spi_handle = LGPIO.spi_open(SPI_DEV, SPI_CHAN, SPI_BAUD, SPI_MODE)
54
24
 
55
25
  loop do
56
- LGPIO.spi_write(spi_handle, data_on)
26
+ LGPIO.spi_ws2812_write(spi_handle, pixels_on)
57
27
  sleep 0.5
58
- LGPIO.spi_write(spi_handle, data_off)
28
+ LGPIO.spi_ws2812_write(spi_handle, pixels_off)
59
29
  sleep 0.5
60
30
  end
@@ -0,0 +1,44 @@
1
+ #
2
+ # 2.4 MHz SPI method for writing WS2812 addressable LEDs.
3
+ # Based on: https://learn.adafruit.com/dma-driven-neopixels/overview
4
+ #
5
+ require 'lgpio'
6
+
7
+ # SPI config
8
+ SPI_DEV = 1
9
+ SPI_CHAN = 0
10
+ SPI_MODE = 0
11
+ SPI_BAUD = 2_400_000
12
+
13
+ PIXEL_COUNT = 8
14
+ COLORS = [
15
+ [255, 255, 255],
16
+ [0, 255, 0],
17
+ [255, 0, 0],
18
+ [0, 0, 255],
19
+ [255, 255, 0],
20
+ [255, 0, 255],
21
+ [0, 255, 255]
22
+ ]
23
+
24
+ # Move along the strip and back, one pixel at a time.
25
+ POSITIONS = (0..PIXEL_COUNT-1).to_a + (1..PIXEL_COUNT-2).to_a.reverse
26
+
27
+ pixels = Array.new(PIXEL_COUNT) { [0, 0, 0] }
28
+ spi_handle = LGPIO.spi_open(SPI_DEV, SPI_CHAN, SPI_BAUD, SPI_MODE)
29
+
30
+ loop do
31
+ COLORS.each do |color|
32
+ POSITIONS.each do |index|
33
+ # Clear and write.
34
+ (0..PIXEL_COUNT-1).each { |i| pixels[i] = [0, 0, 0] }
35
+ LGPIO.spi_ws2812_write(spi_handle, pixels.flatten)
36
+
37
+ # Set one pixel and write.
38
+ pixels[index] = color
39
+ LGPIO.spi_ws2812_write(spi_handle, pixels.flatten)
40
+
41
+ sleep 0.05
42
+ end
43
+ end
44
+ end
data/ext/lgpio/lgpio.c CHANGED
@@ -302,6 +302,42 @@ static VALUE spi_xfer(VALUE self, VALUE handle, VALUE txArray){
302
302
  return retArray;
303
303
  }
304
304
 
305
+ static VALUE spi_ws2812_write(VALUE self, VALUE handle, VALUE pixelArray){
306
+ int count = RARRAY_LEN(pixelArray);
307
+
308
+ // Pull low for at least one byte at 2.4 Mhz before data, and 90 after.
309
+ int zeroesBefore = 1;
310
+ int zeroesAfter = 90;
311
+ int txBufLength = zeroesBefore + (count*3) + zeroesAfter;
312
+ uint8_t txBuf[txBufLength];
313
+ for (int i=0; i<txBufLength; i++) { txBuf[i] = 0; }
314
+
315
+ VALUE currentByte_rb;
316
+ uint8_t currentByte;
317
+ uint8_t currentBit;
318
+ uint32_t temp;
319
+
320
+ for (int i=0; i<count; i++){
321
+ temp = 0;
322
+ currentByte_rb = rb_ary_entry(pixelArray, i);
323
+ Check_Type(currentByte_rb, T_FIXNUM);
324
+ currentByte = NUM2CHR(currentByte_rb);
325
+
326
+ for (int i=7; i>=0; i--) {
327
+ currentBit = (currentByte & (1 << i));
328
+ temp = temp << 3;
329
+ temp = (currentBit == 0) ? (temp | 0b100) : (temp | 0b110);
330
+ }
331
+
332
+ txBuf[zeroesBefore+(i*3)] = (temp >> 16) & 0xFF;
333
+ txBuf[zeroesBefore+(i*3)+1] = (temp >> 8) & 0xFF;
334
+ txBuf[zeroesBefore+(i*3)+2] = temp & 0xFF;
335
+ }
336
+
337
+ int result = lgSpiWrite(NUM2INT(handle), txBuf, txBufLength);
338
+ return INT2NUM(result);
339
+ }
340
+
305
341
  void Init_lgpio(void) {
306
342
  // Modules
307
343
  VALUE mLGPIO = rb_define_module("LGPIO");
@@ -360,4 +396,5 @@ void Init_lgpio(void) {
360
396
  rb_define_singleton_method(mLGPIO, "spi_read", spi_read, 2);
361
397
  rb_define_singleton_method(mLGPIO, "spi_write", spi_write, 2);
362
398
  rb_define_singleton_method(mLGPIO, "spi_xfer", spi_xfer, 2);
399
+ rb_define_singleton_method(mLGPIO, "spi_ws2812_write", spi_ws2812_write, 2);
363
400
  }
data/lib/lgpio/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module LGPIO
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.4"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lgpio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - vickash
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-03 00:00:00.000000000 Z
11
+ date: 2024-08-05 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Use GPIO / PWM / I2C / SPI / UART on Linux SBCs in Ruby
14
14
  email: mail@vickash.com
@@ -37,6 +37,7 @@ files:
37
37
  - examples/spi_loopback.rb
38
38
  - examples/spi_read.rb
39
39
  - examples/spi_ws2812.rb
40
+ - examples/spi_ws2812_bounce.rb
40
41
  - examples/wave.rb
41
42
  - ext/lgpio/extconf.rb
42
43
  - ext/lgpio/lgpio.c