lgpio 0.1.5 → 0.1.6

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: 984afd62543a10d3fc0b6d2a9a581b05b4d9bf7c159d2747f990b2247b59aef1
4
- data.tar.gz: d2431adb24613fdd42b9f9f06a428c399fe48be2e215a13463237a798113630c
3
+ metadata.gz: 0ba4963055ec58ea685427a0c9395eedfbc20cf0159df764edbd3b735dd7ce40
4
+ data.tar.gz: b4149669d2ac089120582d09db4ab6d0e9bb45f8c93e22a62164272f9150c758
5
5
  SHA512:
6
- metadata.gz: f32ceb3af8218d26f1f5713302a9891365af498fe76e2a750037f2ae10a437b747b40167e9fd9c5170fc28696d90c9244ce5d9a36269eba0d0c827a79be47fcd
7
- data.tar.gz: b167ef512729754b46dd3cd14750dd715c8541987014a254465c72619f1ead5d4ae8ff74bcbb6c9122b331c5f65a159e0f0c9890f9e0ad7a5b582dafe2763e54
6
+ metadata.gz: 9e3397df71dadb44d9ebfb96d6732d9ba211f9dc5a530b96747e7ec2ee93e22b6412218f61938560864c10208fdc60609b93c18707ca67332c2a8800e880d21c
7
+ data.tar.gz: 7ebd239afcd78e16ea893943f1e226b06e68c9b0b2cf4c3a98acebe3f23a33e044fa51c1309b1779ac5415877be8512b78cff651e48a87fc0fe860ef2405531f
data/README.md CHANGED
@@ -1,39 +1,52 @@
1
1
  # lgpio
2
2
 
3
- Ruby bindings for the [lgpio (lg)](https://github.com/joan2937/lg) Linux library, running on single board computers (SBCs), like Raspberry Pi.
3
+ Ruby gem with bindings for the [lgpio (lg)](https://github.com/joan2937/lg) C library. This is for single-board-computers (SBCs) running Linux, such as Orange Pi, Raspberry Pi, etc. It provides low-level access to the GPIO, I2C, SPI, and PWM subsytems.
4
+
5
+ ## Standard LGPIO Features
4
6
 
5
- ## Mapped LGPIO Features
6
7
  - [x] GPIO Read/Write
7
8
  - [x] GPIO Group Read/Write
8
- - [x] GPIO Alerts / Callbacks
9
- - lg generates alerts at high speed in a separate thread. You can read them from a queue in Ruby, as part of your application loop.
10
- - [x] Software PWM Out
11
- - Software timed (not 100% precise), on any pin
12
- - Not recommended for servo motors
9
+ - [x] GPIO Alerts
10
+ - Alerts are generated by a separate thread, and can be read from a queue in Ruby.
11
+ - No real "callback" functionality.
12
+ - [x] Software PWM Output
13
+ - Timing not 100% precise, but works on any GPIO.
14
+ - Not recommended for servo motors, will jitter.
13
15
  - [x] Wave
14
- - Software timed on any pin, as with PWM.
15
- - [x] I2C
16
- - [x] SPI
16
+ - Software timed on any pin(s), as with PWM.
17
+ - [x] Hardware I2C
18
+ - [x] Hardware SPI
19
+
20
+ ## Extra Features (Built on LGPIO)
21
+
22
+ - [x] `LGPIO.gpio_read_ultrasonic` sends a pulse on a `trigger` pin, then measures a single pulse on a separate `echo` pin. Used for HC-SR04 or similar. See `examples/hcsr04.rb`.
23
+ - [x] `LGPIO.gpio_read_pulses_us` outputs a reset pulse on a pin, then polls for a sequence of input pulses. Used for DHT enviro sensors or similar. See `examples/dht.rb`.
24
+ - [x] Bit Bang I2C
25
+ - [x] Bit Bang SPI
26
+ - [x] Bit Bang 1-Wire
27
+ - [x] WS2812 addressable LEDs over hardware SPI
28
+ - Outputs on MOSI/PICO pin
29
+ - Must be able to set SPI clock frequency to 2.4 MHz
30
+
31
+ ## Hardware PWM Features
32
+
33
+ These use the sysfs PWM interface, not lgpio C, but are a good fit for this gem.
17
34
 
18
- ## Extra Features, based on LGPIO
19
- - [x] WS2812 over SPI
20
- - Only outputs on a SPI MOSI pin. Must be able to set SPI clock frequency to 2.4 MHz.
21
- - [ ] Bit Bang SPI
22
- - [ ] Bit Bang I2C
35
+ - [x] Hardware PWM Output
36
+ - [x] Servo (based on hardware PWM)
37
+ - [x] On-off Keying (OOK) Modulated Waves
38
+ - Carrier generated by hardware PWM. Software modulated with monotonic clock timing.
39
+ - Useful for sending infrared signals at 38kHz, for example.
23
40
 
24
- ## Sysfs PWM Interface Features
25
- - [x] Hardware PWM Out (specific pins per chip)
26
- - [x] Servo
41
+ **Note:** Once hardware PWM is used on a pin, it stays PWM until reboot. The associated GPIO won't work.
27
42
 
28
43
  ## Installation
29
44
  On Debian-based Linuxes (RaspberryPi OS, Armbian, DietPi etc.):
30
45
  ```bash
31
46
  sudo apt install swig python3-dev python3-setuptools
32
47
 
33
- # NOTE: There's a bug with GPIO numbers > 255.
34
- # If you need to use those, wget the second URL instead, until that fix is merged.
35
- wget https://github.com/joan2937/lg/archive/master.zip
36
- # wget https://github.com/vickash/lg/archive/refs/heads/master.zip
48
+ # Temporary fork of: wget https://github.com/joan2937/lg/archive/master.zip
49
+ wget https://github.com/vickash/lg/archive/refs/heads/master.zip
37
50
 
38
51
  unzip master.zip
39
52
  cd lg-master
@@ -44,17 +57,18 @@ gem install lgpio
44
57
  ```
45
58
 
46
59
  ## Enabling Hardware & Permissions
47
- 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.
60
+ Depending on your SBC and Linux distro/version, you may need to manually enable hardware I2C, SPI, and PWM. You should use the config tool that came with your distro for that, if possible.
48
61
 
49
- 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:
62
+ Even when these are enabled, you may not have permission to access them. To run without `sudo`, you need read+write permission to some or all of the following:
50
63
  ```
51
- /dev/gpiochip* (For GPIO, example: /dev/gpiochip0)
52
- /dev/i2c-* (For I2C, example: /dev/i2c-1)
53
- /dev/spidev* (For SPI, example: /dev/spidev-0.1)
64
+ /dev/gpiochip* (For GPIO, example: /dev/gpiochip0)
65
+ /dev/i2c-* (For I2C, example: /dev/i2c-1)
66
+ /dev/spidev* (For SPI, example: /dev/spidev0.1)
67
+ /sys/class/pwm/pwmchip* (For PWM, example: /sys/class/pwm/pwmchip0)
54
68
  ```
55
69
 
56
70
  ## Documentation
57
- - See examples folder for demos of every implemented interface.
71
+ - See examples folder for demos of everything implemented.
58
72
  - Development was done on an Orange Pi Zero 2W. Your GPIO numbers may be different, so change them.
59
73
  - For more info, see the [lgpio C API docs.](https://abyz.me.uk/lg/lgpio.html)
60
74
  - As much as possible, the Ruby methods closely follow the C API functions, except:
data/examples/bench_in.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'lgpio'
2
2
 
3
3
  GPIO_CHIP = 0
4
- PIN = 258
4
+ PIN = 260
5
5
  COUNT = 1000000
6
6
 
7
7
  chip_handle = LGPIO.chip_open(GPIO_CHIP)
@@ -1,7 +1,7 @@
1
1
  require 'lgpio'
2
2
 
3
3
  GPIO_CHIP = 0
4
- PIN = 260
4
+ PIN = 272
5
5
  COUNT = 1000000
6
6
 
7
7
  chip_handle = LGPIO.chip_open(GPIO_CHIP)
data/examples/blink.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'lgpio'
2
2
 
3
3
  GPIO_CHIP = 0
4
- LED = 260
4
+ LED = 272
5
5
  INTERVAL = 0.25
6
6
 
7
7
  chip_handle = LGPIO.chip_open(GPIO_CHIP)
data/examples/dht.rb ADDED
@@ -0,0 +1,47 @@
1
+ require 'lgpio'
2
+
3
+ GPIO_CHIP = 0
4
+ DHT_PIN = 267
5
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
6
+ #
7
+ # Read a series of pulses input to a GPIO, with an (optional) reset output pulse at start.
8
+ # Arguments in order are:
9
+ # gpiochip handle
10
+ # GPIO number
11
+ # Starting (reset) output pulse time in microseconds (0 for no reset)
12
+ # Reset pulse level (0 or 1)
13
+ # Maximum number of pulses to read
14
+ # Timeout in milliseconds
15
+ #
16
+ data = LGPIO.gpio_read_pulses_us(chip_handle, DHT_PIN, 20_000, 0, 84, 100)
17
+
18
+ # Handle errors.
19
+ raise "error: DHT sensor not connected" unless data
20
+ raise "LGPIO error: #{data}" if data.class == Integer
21
+
22
+ # Discard unneeded pulses
23
+ data = data.last(81)
24
+ raise "error: incomplete DHT data" unless data.length == 81
25
+ data = data.first(80)
26
+
27
+ # Convert to bytes
28
+ bytes = []
29
+ data.each_slice(16) do |b|
30
+ byte = 0b00000000
31
+ b.each_slice(2) do |x,y|
32
+ bit = (y<x) ? 0 : 1
33
+ byte = (byte << 1) | bit
34
+ end
35
+ bytes << byte
36
+ end
37
+
38
+ # CRC
39
+ crc = bytes[0..3].reduce(0, :+) & 0xFF == bytes[4]
40
+ raise "error: DHT CRC check failed" unless crc
41
+
42
+ # Convert and display
43
+ temperature = ((bytes[2] << 8) | bytes[3]).to_f / 10
44
+ humidity = ((bytes[0] << 8) | bytes[1]).to_f / 10
45
+
46
+ puts "DHT Temperature: #{temperature} \xC2\xB0C"
47
+ puts "DHT Humidity: #{humidity} %"
data/examples/group_in.rb CHANGED
@@ -2,8 +2,8 @@
2
2
  require 'lgpio'
3
3
 
4
4
  GPIO_CHIP = 0
5
- BUTTONS = [258, 256]
6
- LEDS = [260, 267]
5
+ BUTTONS = [259, 267]
6
+ LEDS = [272, 258]
7
7
  INIT_STATE = [0, 0]
8
8
 
9
9
  chip_handle = LGPIO.chip_open(GPIO_CHIP)
@@ -1,7 +1,7 @@
1
1
  require 'lgpio'
2
2
 
3
3
  GPIO_CHIP = 0
4
- LEDS = [260, 267]
4
+ LEDS = [272, 258]
5
5
  INIT_STATE = [0, 0]
6
6
  INTERVAL = 250_000 # 250ms
7
7
  TIMES = 10
@@ -0,0 +1,32 @@
1
+ #
2
+ # Example showing an HC-S04 ultrasonic distance sensor.
3
+ #
4
+ # NOTE: Some versions of this sensor require 5V power to function properly.
5
+ # If using one of these, use a 5V to 3.3V level shifter between your board and
6
+ # the sensor, at least on the echo pin.
7
+ #
8
+ require 'lgpio'
9
+
10
+ GPIO_CHIP = 0
11
+ ECHO_PIN = 228
12
+ TRIGGER_PIN = 270
13
+ SPEED_OF_SOUND = 343.0
14
+
15
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
16
+
17
+ loop do
18
+ # Arguments in order are:
19
+ # chip handle, trigger pin, echo pin, trigger time (us)
20
+ #
21
+ # HC-SR04 uses 10 microseconds for trigger. Some others use 20us.
22
+ #
23
+ microseconds = LGPIO.gpio_read_ultrasonic(chip_handle, TRIGGER_PIN, ECHO_PIN, 10)
24
+
25
+ if microseconds
26
+ mm = (microseconds / 2000.0) * SPEED_OF_SOUND
27
+ puts "Distance: #{mm.round} mm"
28
+ else
29
+ puts "Cound not read HC-SR04 sensor"
30
+ end
31
+ sleep 0.5
32
+ end
@@ -1,6 +1,7 @@
1
1
  require 'lgpio'
2
2
 
3
3
  I2C_DEV = 3
4
+ ADDRESS = 0x38
4
5
  POWER_ON_DELAY = 0.100
5
6
  RESET_DELAY = 0.020
6
7
  COMMAND_DELAY = 0.010
@@ -10,7 +11,7 @@ SOFT_RESET = [0xBA]
10
11
  INIT_AND_CALIBRATE = [0xE1, 0x08, 0x00]
11
12
  START_MEASUREMENT = [0xAC, 0x33, 0x00]
12
13
 
13
- aht10_handle = LGPIO.i2c_open(I2C_DEV, 0x38, 0)
14
+ aht10_handle = LGPIO.i2c_open(I2C_DEV, ADDRESS, 0)
14
15
 
15
16
  # Startup sequence
16
17
  sleep(POWER_ON_DELAY)
@@ -1,6 +1,7 @@
1
1
  require 'lgpio'
2
2
 
3
3
  I2C_DEV = 3
4
+ ADDRESS = 0x38
4
5
  POWER_ON_DELAY = 0.100
5
6
  RESET_DELAY = 0.020
6
7
  COMMAND_DELAY = 0.010
@@ -10,7 +11,7 @@ INIT_AND_CALIBRATE = [5, 3, 0xE1, 0x08, 0x00, 0]
10
11
  START_MEASUREMENT = [5, 3, 0xAC, 0x33, 0x00, 0]
11
12
  READ_SIX = [4, 6, 0]
12
13
 
13
- aht10_handle = LGPIO.i2c_open(I2C_DEV, 0x38, 0)
14
+ aht10_handle = LGPIO.i2c_open(I2C_DEV, ADDRESS, 0)
14
15
 
15
16
  # Startup sequence
16
17
  sleep(POWER_ON_DELAY)
@@ -0,0 +1,40 @@
1
+ require 'lgpio'
2
+
3
+ POWER_ON_DELAY = 0.100
4
+ RESET_DELAY = 0.020
5
+ COMMAND_DELAY = 0.010
6
+ MEASURE_DELAY = 0.080
7
+ DATA_LENGTH = 6
8
+ SOFT_RESET = [0xBA]
9
+ INIT_AND_CALIBRATE = [0xE1, 0x08, 0x00]
10
+ START_MEASUREMENT = [0xAC, 0x33, 0x00]
11
+
12
+ GPIO_CHIP = 0
13
+ SCL_PIN = 228
14
+ SDA_PIN = 270
15
+ ADDRESS = 0x38
16
+
17
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
18
+ i2c_bb = LGPIO::I2CBitBang.new(chip_handle, SCL_PIN, SDA_PIN)
19
+
20
+ # Startup sequence
21
+ sleep(POWER_ON_DELAY)
22
+ i2c_bb.write(ADDRESS, SOFT_RESET)
23
+ sleep(RESET_DELAY)
24
+ i2c_bb.write(ADDRESS, INIT_AND_CALIBRATE)
25
+ sleep(COMMAND_DELAY)
26
+
27
+ # Read and close
28
+ i2c_bb.write(ADDRESS, START_MEASUREMENT)
29
+ sleep(MEASURE_DELAY)
30
+ bytes = i2c_bb.read(ADDRESS, DATA_LENGTH)
31
+
32
+ # Humidity uses the upper 4 bits of the shared byte as its lowest 4 bits.
33
+ h_raw = ((bytes[1] << 16) | (bytes[2] << 8) | (bytes[3])) >> 4
34
+ humidity = (h_raw.to_f / 2**20) * 100
35
+
36
+ # Temperature uses the lower 4 bits of the shared byte as its highest 4 bits.
37
+ t_raw = ((bytes[3] & 0x0F) << 16) | (bytes[4] << 8) | bytes[5]
38
+ temperature = (t_raw.to_f / 2**20) * 200 - 50
39
+
40
+ puts "#{Time.now.strftime '%Y-%m-%d %H:%M:%S'} - Temperature: #{temperature.round(2)} \xC2\xB0C | Humidity: #{humidity.round(2)} %"
@@ -0,0 +1,35 @@
1
+ require 'lgpio'
2
+
3
+ INIT_ARRAY = [0, 168, 63, 211, 0, 64, 161, 200, 218, 18, 164, 166, 213, 128, 219, 32, 217, 241, 141, 20, 32, 0, 175]
4
+ START_ARRAY = [0, 33, 0, 127, 34, 0, 7]
5
+ PATTERN_1 = [64] + Array.new(1024) { 0b00110011 }
6
+ PATTERN_2 = [64] + Array.new(1024) { 0b11001100 }
7
+
8
+ GPIO_CHIP = 0
9
+ SCL_PIN = 228
10
+ SDA_PIN = 270
11
+ ADDRESS = 0x3C
12
+
13
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
14
+ i2c_bb = LGPIO::I2CBitBang.new(chip_handle, SCL_PIN, SDA_PIN)
15
+
16
+ i2c_bb.write(ADDRESS, INIT_ARRAY)
17
+ FRAME_COUNT = 400
18
+
19
+ start = Time.now
20
+ (FRAME_COUNT / 2).times do
21
+ i2c_bb.write(ADDRESS, START_ARRAY)
22
+ i2c_bb.write(ADDRESS, PATTERN_1)
23
+ i2c_bb.write(ADDRESS, START_ARRAY)
24
+ i2c_bb.write(ADDRESS, PATTERN_2)
25
+ end
26
+ finish = Time.now
27
+
28
+ LGPIO.chip_close(chip_handle)
29
+
30
+ fps = FRAME_COUNT / (finish - start)
31
+ # Also calculate C calls per second, using roughly 23 calls per byte written.
32
+ cps = (START_ARRAY.length + ((PATTERN_1.length + PATTERN_2.length) / 2) + 2) * 23 * fps
33
+ cps = (cps / 1000.0).round
34
+
35
+ puts "SSD1306 benchmark result: #{fps.round(2)} fps | #{cps}k C calls/s"
@@ -0,0 +1,40 @@
1
+ require 'lgpio'
2
+
3
+ POWER_ON_DELAY = 0.100
4
+ RESET_DELAY = 0.020
5
+ COMMAND_DELAY = 0.010
6
+ MEASURE_DELAY = 0.080
7
+ DATA_LENGTH = 6
8
+ SOFT_RESET = [0xBA]
9
+ INIT_AND_CALIBRATE = [0xE1, 0x08, 0x00]
10
+ START_MEASUREMENT = [0xAC, 0x33, 0x00]
11
+
12
+ GPIO_CHIP = 0
13
+ SCL_PIN = 228
14
+ SDA_PIN = 270
15
+ ADDRESS = 0x38
16
+
17
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
18
+ LGPIO.i2c_bb_claim(chip_handle, SCL_PIN, SDA_PIN)
19
+
20
+ # Startup sequence
21
+ sleep(POWER_ON_DELAY)
22
+ LGPIO.i2c_bb_write(chip_handle, SCL_PIN, SDA_PIN, ADDRESS, SOFT_RESET)
23
+ sleep(RESET_DELAY)
24
+ LGPIO.i2c_bb_write(chip_handle, SCL_PIN, SDA_PIN, ADDRESS, INIT_AND_CALIBRATE)
25
+ sleep(COMMAND_DELAY)
26
+
27
+ # Read and close
28
+ LGPIO.i2c_bb_write(chip_handle, SCL_PIN, SDA_PIN, ADDRESS, START_MEASUREMENT)
29
+ sleep(MEASURE_DELAY)
30
+ bytes = LGPIO.i2c_bb_read(chip_handle, SCL_PIN, SDA_PIN, ADDRESS, DATA_LENGTH)
31
+
32
+ # Humidity uses the upper 4 bits of the shared byte as its lowest 4 bits.
33
+ h_raw = ((bytes[1] << 16) | (bytes[2] << 8) | (bytes[3])) >> 4
34
+ humidity = (h_raw.to_f / 2**20) * 100
35
+
36
+ # Temperature uses the lower 4 bits of the shared byte as its highest 4 bits.
37
+ t_raw = ((bytes[3] & 0x0F) << 16) | (bytes[4] << 8) | bytes[5]
38
+ temperature = (t_raw.to_f / 2**20) * 200 - 50
39
+
40
+ puts "#{Time.now.strftime '%Y-%m-%d %H:%M:%S'} - Temperature: #{temperature.round(2)} \xC2\xB0C | Humidity: #{humidity.round(2)} %"
@@ -0,0 +1,20 @@
1
+ require 'lgpio'
2
+
3
+ GPIO_CHIP = 0
4
+ SCL_PIN = 228
5
+ SDA_PIN = 270
6
+
7
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
8
+ LGPIO.i2c_bb_claim(chip_handle, SCL_PIN, SDA_PIN)
9
+
10
+ devices = LGPIO.i2c_bb_search(chip_handle, SCL_PIN, SDA_PIN)
11
+
12
+ if devices.empty?
13
+ puts "No devices found on I2C bus"
14
+ else
15
+ puts "I2C device addresses found:"
16
+ devices.each do |address|
17
+ # Print as hexadecimal.
18
+ puts "0x#{address.to_s(16).upcase}"
19
+ end
20
+ end
@@ -0,0 +1,35 @@
1
+ require 'lgpio'
2
+
3
+ INIT_ARRAY = [0, 168, 63, 211, 0, 64, 161, 200, 218, 18, 164, 166, 213, 128, 219, 32, 217, 241, 141, 20, 32, 0, 175]
4
+ START_ARRAY = [0, 33, 0, 127, 34, 0, 7]
5
+ PATTERN_1 = [64] + Array.new(1024) { 0b00110011 }
6
+ PATTERN_2 = [64] + Array.new(1024) { 0b11001100 }
7
+
8
+ GPIO_CHIP = 0
9
+ SCL_PIN = 228
10
+ SDA_PIN = 270
11
+ ADDRESS = 0x3C
12
+
13
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
14
+ LGPIO.i2c_bb_claim(chip_handle, SCL_PIN, SDA_PIN)
15
+
16
+ LGPIO.i2c_bb_write(chip_handle, SCL_PIN, SDA_PIN, ADDRESS, INIT_ARRAY)
17
+ FRAME_COUNT = 400
18
+
19
+ start = Time.now
20
+ (FRAME_COUNT / 2).times do
21
+ LGPIO.i2c_bb_write(chip_handle, SCL_PIN, SDA_PIN, ADDRESS, START_ARRAY)
22
+ LGPIO.i2c_bb_write(chip_handle, SCL_PIN, SDA_PIN, ADDRESS, PATTERN_1)
23
+ LGPIO.i2c_bb_write(chip_handle, SCL_PIN, SDA_PIN, ADDRESS, START_ARRAY)
24
+ LGPIO.i2c_bb_write(chip_handle, SCL_PIN, SDA_PIN, ADDRESS, PATTERN_2)
25
+ end
26
+ finish = Time.now
27
+
28
+ LGPIO.chip_close(chip_handle)
29
+
30
+ fps = FRAME_COUNT / (finish - start)
31
+ # Also calculate C calls per second, using roughly 23 calls per byte written.
32
+ cps = (START_ARRAY.length + ((PATTERN_1.length + PATTERN_2.length) / 2) + 2) * 23 * fps
33
+ cps = (cps / 1000.0).round
34
+
35
+ puts "SSD1306 benchmark result: #{fps.round(2)} fps | #{cps}k C calls/s"
@@ -1,21 +1,22 @@
1
1
  require 'lgpio'
2
2
 
3
3
  I2C_DEV = 3
4
+ ADDRESS = 0x3C
4
5
  INIT_ARRAY = [0, 168, 63, 211, 0, 64, 161, 200, 218, 18, 164, 166, 213, 128, 219, 32, 217, 241, 141, 20, 32, 0, 175]
5
6
  START_ARRAY = [0, 33, 0, 127, 34, 0, 7]
6
- BLANK_ARRAY = [64] + Array.new(1024) { 0 }
7
- FILL_ARRAY = [64] + Array.new(1024) { 255 }
7
+ PATTERN_1 = [64] + Array.new(1024) { 0b00110011 }
8
+ PATTERN_2 = [64] + Array.new(1024) { 0b11001100 }
8
9
 
9
- ssd1306_handle = LGPIO.i2c_open(I2C_DEV, 0x3C, 0)
10
+ ssd1306_handle = LGPIO.i2c_open(I2C_DEV, ADDRESS, 0)
10
11
  LGPIO.i2c_write_device(ssd1306_handle, INIT_ARRAY)
11
12
  FRAME_COUNT = 100
12
13
 
13
14
  start = Time.now
14
15
  (FRAME_COUNT / 2).times do
15
16
  LGPIO.i2c_write_device(ssd1306_handle, START_ARRAY)
16
- LGPIO.i2c_write_device(ssd1306_handle, FILL_ARRAY)
17
+ LGPIO.i2c_write_device(ssd1306_handle, PATTERN_1)
17
18
  LGPIO.i2c_write_device(ssd1306_handle, START_ARRAY)
18
- LGPIO.i2c_write_device(ssd1306_handle, BLANK_ARRAY)
19
+ LGPIO.i2c_write_device(ssd1306_handle, PATTERN_2)
19
20
  end
20
21
  finish = Time.now
21
22
 
@@ -0,0 +1,22 @@
1
+ require 'lgpio'
2
+
3
+ FREQUENCY = 38_000
4
+
5
+ # NEC Raw-Data=0xF708FB04. LSBFIRST, so the binary for each hex digit below is backward.
6
+ CODE = [ 9000, 500, # Start bit
7
+ 560, 560, 560, 560, 560, 1690, 560, 560, # 0010 0x4 command
8
+ 560, 560, 560, 560, 560, 560, 560, 560, # 0000 0x0 command
9
+ 560, 1690, 560, 1690, 560,560, 560, 1690, # 1101 0xB command inverted
10
+ 560, 1690, 560, 1690, 560, 1690, 560, 1690, # 1111 0xF command inverted
11
+ 560, 560, 560, 560, 560, 560, 560, 1690, # 0001 0x8 address
12
+ 560, 560, 560, 560, 560, 560, 560, 560, # 0000 0x0 address
13
+ 560, 1690, 560, 1690, 560, 1690, 560, 560, # 1110 0x7 address inverted
14
+ 560, 1690, 560, 1690, 560, 1690, 560, 1690, # 1111 0xF address inverted
15
+ 560] # Stop bit
16
+
17
+ infrared = LGPIO::Infrared.new(0, 2, frequency: FREQUENCY)
18
+
19
+ loop do
20
+ infrared.transmit(CODE)
21
+ sleep 1
22
+ end
@@ -1,8 +1,8 @@
1
1
  require 'lgpio'
2
2
 
3
3
  GPIO_CHIP = 0
4
- BUTTON = 258
5
- LED = 260
4
+ BUTTON = 259
5
+ LED = 272
6
6
 
7
7
  chip_handle = LGPIO.chip_open(GPIO_CHIP)
8
8
  LGPIO.gpio_claim_input(chip_handle, LGPIO::SET_PULL_UP, BUTTON)
@@ -0,0 +1,30 @@
1
+ require 'lgpio'
2
+
3
+ GPIO_CHIP = 0
4
+ PIN = 256
5
+ PARASITE = false
6
+
7
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
8
+ one_wire = LGPIO::OneWire.new(chip_handle, PIN)
9
+
10
+ one_wire.reset
11
+ # Skip ROM
12
+ one_wire.write([LGPIO::OneWire::SKIP_ROM], parasite: PARASITE)
13
+ # Start conversion
14
+ one_wire.write([LGPIO::OneWire::CONVERT_T], parasite: PARASITE)
15
+ # Wait for conversion
16
+ sleep(1)
17
+ # Reset
18
+ one_wire.reset
19
+ # Skip ROM
20
+ one_wire.write([LGPIO::OneWire::SKIP_ROM], parasite: PARASITE)
21
+ # Read 9 bytes from scratchpad
22
+ one_wire.write([LGPIO::OneWire::READ_SCRATCH], parasite: PARASITE)
23
+ bytes = one_wire.read(9)
24
+
25
+ # Temperature is the first 16 bits (2 bytes of 9 read).
26
+ # It's a signed, 2's complement, little-endian decimal. LSB = 2 ^ -4.
27
+ #
28
+ temperature = bytes[0..1].pack('C*').unpack('s<')[0] * (2.0 ** -4)
29
+
30
+ puts "DS18B20 reading: #{temperature} \xC2\xB0C"
@@ -0,0 +1,15 @@
1
+ require 'lgpio'
2
+
3
+ GPIO_CHIP = 0
4
+ PIN = 256
5
+
6
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
7
+ one_wire = LGPIO::OneWire.new(chip_handle, PIN)
8
+ one_wire.search
9
+
10
+ puts; puts "Found these 1-wire addresss (HEX) on the bus:"; puts
11
+
12
+ one_wire.found_addresses.each do |address|
13
+ puts address.to_s(16)
14
+ end
15
+ puts
data/examples/pwm.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'lgpio'
2
2
 
3
3
  GPIO_CHIP = 0
4
- LED = 260
4
+ LED = 272
5
5
  PWM_FREQ = 500
6
6
  PWM_OFFSET = 0
7
7
  PWM_CYCLES = 0 # 0 = infinite
data/examples/reports.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'lgpio'
2
2
 
3
3
  GPIO_CHIP = 0
4
- PIN = 76
4
+ PIN = 259
5
5
 
6
6
  chip_handle = LGPIO.chip_open(GPIO_CHIP)
7
7
 
@@ -5,9 +5,9 @@
5
5
  require 'lgpio'
6
6
 
7
7
  GPIO_CHIP = 0
8
- PIN_A = 76
9
- PIN_B = 228
10
- PIN_SW = 226
8
+ PIN_A = 260
9
+ PIN_B = 76
10
+ PIN_SW = 259
11
11
 
12
12
  # Encoder state
13
13
  position = 0
@@ -5,10 +5,10 @@
5
5
  require 'lgpio'
6
6
 
7
7
  GPIO_CHIP = 0
8
- PIN_A = 76
9
- PIN_B = 228
8
+ PIN_A = 260
9
+ PIN_B = 76
10
10
 
11
- PIN_LED = 260
11
+ PIN_LED = 272
12
12
  PWM_FREQ = 500
13
13
  PWM_OFFSET = 0
14
14
  PWM_CYCLES = 0 # 0 = infinite
@@ -44,7 +44,7 @@ loop do
44
44
  elsif report[:gpio] == PIN_B
45
45
  delta = (report[:level] == state_a) ? -1 : 1
46
46
  state_b = report[:level]
47
-
47
+
48
48
  led_duty += delta
49
49
  led_duty = 0 if led_duty < 0
50
50
  led_duty = 100 if led_duty > 100
@@ -0,0 +1,25 @@
1
+ require 'lgpio'
2
+
3
+ GPIO_CHIP = 0
4
+ CLOCK_PIN = 22
5
+ INPUT_PIN = 17
6
+ OUTPUT_PIN = 27
7
+
8
+ MODES = [0, 1, 2, 3]
9
+ ORDERS = [:msbfirst, :lsbfirst]
10
+ TX_BYTES = [0, 1, 2, 3, 4, 5, 6, 7]
11
+
12
+ chip_handle = LGPIO.chip_open(GPIO_CHIP)
13
+ spi_bb = LGPIO::SPIBitBang.new(handle: chip_handle, clock: CLOCK_PIN, input: INPUT_PIN, output: OUTPUT_PIN)
14
+
15
+ puts "TX bytes => #{TX_BYTES.inspect}"
16
+
17
+ # Connect (loop back) INPUT_PIN to OUTPUT_PIN to see received bytes.
18
+ ORDERS.each do |order|
19
+ MODES.each do |mode|
20
+ rx_bytes = spi_bb.transfer(write: TX_BYTES, read: TX_BYTES.length, order: order, mode: mode)
21
+ puts "RX (order: #{order}, mode: #{mode}) => #{rx_bytes.inspect}"
22
+ end
23
+ end
24
+
25
+ LGPIO.chip_close(chip_handle)