lgpio 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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