Skip to content

Commit

Permalink
require
Browse files Browse the repository at this point in the history
  • Loading branch information
hasumikin committed Oct 28, 2023
1 parent 24b1b19 commit e4fe9fe
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 0 deletions.
1 change: 1 addition & 0 deletions _Sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
* [[Sounder]]
* [[Music Macro language]]
* [[BOOTSEL mode of RP2040]]
* [[require]]
* Examples
* [[Microcontroller boards and Keyboards]]
* Development
Expand Down
113 changes: 113 additions & 0 deletions require.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
## Valid version

|Feature|Version|
|----|----|
|Loading prebuilt libraries|0.9.14+ (maybe)|
|Loading external libraries|0.9.23+|

This page explains the loading external libraries feature introduced in 0.9.23.

## Description

CRuby loads external libraries using `Kernel.#require` method.
Likewise, PicoRuby has `require` method.
You can reuse a Ruby script by taking advantage of that.

## Gist

- Put your library files in the `/lib` directory in "PRK DRIVE"
- It may be easier to understand if you say `$LOAD_PATH` is `["/lib"]`
- The library file has to have `.rb` or `.mrb` extention. eg: `my_library.rb`
- `require` method ignores the extension, so just write `require "my_library"`
- `.rb` file will be compiled into mruby VM code in microcontrller on the fly
- A large Ruby file is more likely to cause Out of Memory
- In such case, precompled mrb file will help
- You can get `my_library.mrb` by `mrbc my_library.rb` or `picorbc my_library.rb`
- Make sure to use the same version of the compiler as the PicoRuby in PRK
- As of PRK 0.9.23, the corresponding version of mruby (picoruby) is 3.2.x

## Example

```ruby
# Library for ADNS-5050 optical sensor
# filepath: /lib/adns5050.rb
require "mouse"
require "spi"

class ADNS5050
def initialize(sck_pin:, copi_pin:, cipo_pin:, cs_pin:)
spi = SPI.new(unit: :BITBANG, sck_pin: sck_pin, copi_pin: copi_pin, cipo_pin: cipo_pin, cs_pin: cs_pin)
mouse = Mouse.new(driver: spi)
mouse.task do |mouse, keyboard|
next if mouse.driver.power_down
y, x = mouse.driver.select do |spi|
spi.write(0x63) # Motion_Burst
spi.read(2).bytes
end
if 0 < x || 0 < y
x = 0x7F < x ? (~x & 0xff) + 1 : -x
y = 0x7F < y ? (~y & 0xff) + 1 : -y
if keyboard.layer == :lower
x = 0 < x ? 1 : (x < 0 ? -1 : x)
y = 0 < y ? 1 : (y < 0 ? -1 : y)
USB.merge_mouse_report(0, 0, 0, y, -x)
else
mod = keyboard.modifier
if 0 < mod & 0b00100010
# Shift key pressed -> Horizontal or Vertical only
x.abs < y.abs ? x = 0 : y = 0
end
if 0 < mod & 0b01000100
# Alt key pressed -> Fix the move amount
x = 0 < x ? 2 : (x < 0 ? -2 : x)
y = 0 < y ? 2 : (y < 0 ? -2 : y)
end
USB.merge_mouse_report(0, y, x, 0, 0)
end
end
end
return mouse
end
end
```

```ruby
# filepath: /keyboard.rb
require "adns5050"

kbd = Keyboard.new

kbd.append ADNS5050.new(sck_pin: 23, copi_pin: 8, cipo_pin: 8, cs_pin: 9)

kbd.start!
```

## Pro tip

When you make font data for OLED, in general, remember that String objects are more memory-effective than Array objects.

```ruby
# Array object
FONT_DATA = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 0x00,
...
]
```

```ruby
# String object
FONT_DATA = "\x00\x00\x00\x00\x00\x00\x3E\x5B\x4F\x5B\x3E\x00..."
```

If OOM still occurs, splitting the data may work:

```ruby
# Split String objects
FONT_DATA_1 = "\x00\x00\x00\x00\x00\x00\x3E\x5B\x4F\x5B\x3E\x00..."
FONT_DATA_2 = "\xC0\x00\xDC\xD7\xDE\xDE\xDE\xD7\xDC\x00\xC0\x00..."
FONT_DATA = FONT_DATA_1 + FONT_DATA_2
```

Needless to say, precompiled `.mrb` is even more effective.

0 comments on commit e4fe9fe

Please sign in to comment.