Module: LGPIO
- Defined in:
- lib/lgpio.rb,
lib/lgpio/version.rb,
lib/lgpio/infrared.rb,
lib/lgpio/one_wire.rb,
lib/lgpio/i2c_bitbang.rb,
lib/lgpio/spi_bitbang.rb,
lib/lgpio/hardware_pwm.rb,
lib/lgpio/positional_servo.rb,
ext/lgpio/lgpio.c
Defined Under Namespace
Classes: HardwarePWM, I2CBitBang, Infrared, OneWire, PositionalServo, SPIBitBang
Constant Summary collapse
- LOW =
0
- HIGH =
1
- VERSION =
"0.1.11"
- SET_ACTIVE_LOW =
Constants
INT2NUM(LG_SET_ACTIVE_LOW)
- SET_OPEN_DRAIN =
INT2NUM(LG_SET_OPEN_DRAIN)
- SET_OPEN_SOURCE =
INT2NUM(LG_SET_OPEN_SOURCE)
- SET_PULL_UP =
INT2NUM(LG_SET_PULL_UP)
- SET_PULL_DOWN =
INT2NUM(LG_SET_PULL_DOWN)
- SET_PULL_NONE =
INT2NUM(LG_SET_PULL_NONE)
- RISING_EDGE =
INT2NUM(LG_RISING_EDGE)
- FALLING_EDGE =
INT2NUM(LG_FALLING_EDGE)
- BOTH_EDGES =
INT2NUM(LG_BOTH_EDGES)
- TX_PWM =
Soft PWM / Wave
INT2NUM(LG_TX_PWM)
- TX_WAVE =
INT2NUM(LG_TX_WAVE)
Class Method Summary collapse
- .chip_close(handle) ⇒ Object
-
.chip_open(gpio_dev) ⇒ Object
**************************************************************************.
- .gpio_claim_alert(handle, gpio, flags, eFlags) ⇒ Object
- .gpio_claim_input(handle, gpio, flags) ⇒ Object
- .gpio_claim_output(handle, gpio, flags, level) ⇒ Object
- .gpio_free(handle, gpio) ⇒ Object
- .gpio_get_mode(handle, gpio) ⇒ Object
- .gpio_get_report ⇒ Object
- .gpio_read(handle, gpio) ⇒ Object
- .gpio_read_pulses_us(rbHandle, rbGPIO, rbReset_us, rbResetLevel, rbLimit, rbTimeout_ms) ⇒ Object
-
.gpio_read_ultrasonic(rbHandle, rbTrigger, rbEcho, rbTriggerTime) ⇒ Object
**************************************************************************.
-
.gpio_set_debounce(handle, gpio, debounce) ⇒ Object
Alerts / Reports.
- .gpio_start_reporting ⇒ Object
- .gpio_write(handle, gpio, level) ⇒ Object
-
.group_claim_input(handle, gpios, flags) ⇒ Object
Grouped.
- .group_claim_output(handle, gpios, flags, levels) ⇒ Object
- .group_free(handle, gpio) ⇒ Object
- .group_read(handle, gpio) ⇒ Object
- .group_write(handle, gpio, bits, mask) ⇒ Object
- .i2c_bb_read_byte(rbSCL_H, rbSCL_L, rbSDA_H, rbSDA_L, rbACK) ⇒ Object
-
.i2c_bb_write_byte(rbSCL_H, rbSCL_L, rbSDA_H, rbSDA_L, rbByte) ⇒ Object
Bit-bang I2C Helpers.
- .i2c_close(handle) ⇒ Object
-
.i2c_open(i2cDev, i2cAddr, i2cFlags) ⇒ Object
**************************************************************************.
- .i2c_read_device(handle, count) ⇒ Object
- .i2c_write_device(handle, txArray) ⇒ Object
- .i2c_zip(handle, txArray, rb_rxCount) ⇒ Object
-
.micro_delay(micros) ⇒ Object
Generic Helpers.
-
.one_wire_bit_read(rbHandle, rbGPIO) ⇒ Object
**************************************************************************.
- .one_wire_bit_write(rbHandle, rbGPIO, rbBit) ⇒ Object
- .one_wire_reset(rbHandle, rbGPIO) ⇒ Object
- .spi_close(handle) ⇒ Object
-
.spi_open(spiDev, spiChan, spiBaud, spiFlags) ⇒ Object
**************************************************************************.
- .spi_read(handle, rxCount) ⇒ Object
- .spi_write(handle, txArray) ⇒ Object
- .spi_ws2812_write(handle, pixelArray) ⇒ Object
- .spi_xfer(handle, txArray, rxLength) ⇒ Object
-
.tx_busy(handle, gpio, kind) ⇒ Object
**************************************************************************.
- .tx_pulse(handle, gpio, on, off, offset, cycles) ⇒ Object
- .tx_pwm(handle, gpio, freq, duty, offset, cycles) ⇒ Object
- .tx_room(handle, gpio, kind) ⇒ Object
-
.tx_servo(handle, gpio, width, freq, offset, cycles) ⇒ Object
Don’t use this.
- .tx_wave(handle, lead_gpio, pulses) ⇒ Object
Class Method Details
.chip_close(handle) ⇒ Object
58 59 60 61 |
# File 'ext/lgpio/lgpio.c', line 58
static VALUE chip_close(VALUE self, VALUE handle) {
int result = lgGpiochipClose(NUM2INT(handle));
return INT2NUM(result);
}
|
.chip_open(gpio_dev) ⇒ Object
**************************************************************************
53 54 55 56 |
# File 'ext/lgpio/lgpio.c', line 53
static VALUE chip_open(VALUE self, VALUE gpio_dev) {
int result = lgGpiochipOpen(NUM2INT(gpio_dev));
return INT2NUM(result);
}
|
.gpio_claim_alert(handle, gpio, flags, eFlags) ⇒ Object
140 141 142 143 |
# File 'ext/lgpio/lgpio.c', line 140
static VALUE gpio_claim_alert(VALUE self, VALUE handle, VALUE gpio, VALUE flags, VALUE eFlags) {
int result = lgGpioClaimAlert(NUM2INT(handle), NUM2INT(flags), NUM2INT(eFlags), NUM2INT(gpio), -1);
return INT2NUM(result);
}
|
.gpio_claim_input(handle, gpio, flags) ⇒ Object
73 74 75 76 |
# File 'ext/lgpio/lgpio.c', line 73
static VALUE gpio_claim_input(VALUE self, VALUE handle, VALUE gpio, VALUE flags) {
int result = lgGpioClaimInput(NUM2INT(handle), NUM2INT(flags), NUM2INT(gpio));
return INT2NUM(result);
}
|
.gpio_claim_output(handle, gpio, flags, level) ⇒ Object
68 69 70 71 |
# File 'ext/lgpio/lgpio.c', line 68
static VALUE gpio_claim_output(VALUE self, VALUE handle, VALUE gpio, VALUE flags, VALUE level) {
int result = lgGpioClaimOutput(NUM2INT(handle), NUM2INT(flags), NUM2INT(gpio), NUM2INT(level));
return INT2NUM(result);
}
|
.gpio_free(handle, gpio) ⇒ Object
78 79 80 81 |
# File 'ext/lgpio/lgpio.c', line 78
static VALUE gpio_free(VALUE self, VALUE handle, VALUE gpio) {
int result = lgGpioFree(NUM2INT(handle), NUM2INT(gpio));
return INT2NUM(result);
}
|
.gpio_get_mode(handle, gpio) ⇒ Object
63 64 65 66 |
# File 'ext/lgpio/lgpio.c', line 63
static VALUE gpio_get_mode(VALUE self, VALUE handle, VALUE gpio) {
int result = lgGpioGetMode(NUM2INT(handle), NUM2INT(gpio));
return INT2NUM(result);
}
|
.gpio_get_report ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'ext/lgpio/lgpio.c', line 161
static VALUE gpio_get_report(VALUE self){
VALUE hash = rb_hash_new();
bool popped = false;
pthread_mutex_lock(&queueLock);
// qWritePos is where the NEXT report will go. Always trail it by 1.
if (qWritePos - qReadPos != 1){
qReadPos += 1;
rb_hash_aset(hash, ID2SYM(rb_intern("timestamp")), ULL2NUM(reportQueue[qReadPos].timestamp));
rb_hash_aset(hash, ID2SYM(rb_intern("chip")), UINT2NUM(reportQueue[qReadPos].chip));
rb_hash_aset(hash, ID2SYM(rb_intern("gpio")), UINT2NUM(reportQueue[qReadPos].gpio));
rb_hash_aset(hash, ID2SYM(rb_intern("level")), UINT2NUM(reportQueue[qReadPos].level));
rb_hash_aset(hash, ID2SYM(rb_intern("flags")), UINT2NUM(reportQueue[qReadPos].flags));
popped = true;
}
pthread_mutex_unlock(&queueLock);
return (popped) ? hash : Qnil;
}
|
.gpio_read(handle, gpio) ⇒ Object
83 84 85 86 |
# File 'ext/lgpio/lgpio.c', line 83
static VALUE gpio_read(VALUE self, VALUE handle, VALUE gpio) {
int result = lgGpioRead(NUM2INT(handle), NUM2INT(gpio));
return INT2NUM(result);
}
|
.gpio_read_pulses_us(rbHandle, rbGPIO, rbReset_us, rbResetLevel, rbLimit, rbTimeout_ms) ⇒ Object
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 |
# File 'ext/lgpio/lgpio.c', line 502
static VALUE gpio_read_pulses_us(VALUE self, VALUE rbHandle, VALUE rbGPIO, VALUE rbReset_us, VALUE rbResetLevel, VALUE rbLimit, VALUE rbTimeout_ms) {
// C values
int handle = NUM2INT(rbHandle);
int gpio = NUM2INT(rbGPIO);
uint32_t reset_us = NUM2UINT(rbReset_us);
uint8_t resetLevel = NUM2UINT(rbResetLevel);
uint32_t limit = NUM2UINT(rbLimit);
uint64_t timeout_ns = NUM2UINT(rbTimeout_ms) * 1000000;
// State setup
uint64_t pulses_ns[limit];
uint32_t pulseIndex = 0;
int gpioState;
struct timespec start;
struct timespec lastPulse;
struct timespec now;
// Perform reset
if (reset_us > 0) {
int result = lgGpioClaimOutput(handle, LG_SET_PULL_NONE, gpio, resetLevel);
if (result < 0) return NUM2INT(result);
microDelay(reset_us);
}
// Initialize timing
clock_gettime(CLOCK_MONOTONIC, &start);
lastPulse = start;
now = start;
// Switch to input and read initial state
lgGpioClaimInput(handle, LG_SET_PULL_NONE, gpio);
gpioState = lgGpioRead(handle, gpio);
// Read pulses in nanoseconds
while ((nanoDiff(&now, &start) < timeout_ns) && (pulseIndex < limit)) {
clock_gettime(CLOCK_MONOTONIC, &now);
if (lgGpioRead(handle, gpio) != gpioState) {
pulses_ns[pulseIndex] = nanoDiff(&now, &lastPulse);
lastPulse = now;
gpioState = gpioState ^ 0b1;
pulseIndex++;
}
}
// Return Ruby array of pulse as microseconds
if (pulseIndex == 0) return Qnil;
VALUE retArray = rb_ary_new2(pulseIndex);
for(uint32_t i=0; i<pulseIndex; i++){
uint32_t pulse_us = round(pulses_ns[i] / 1000.0);
rb_ary_store(retArray, i, UINT2NUM(pulse_us));
}
return retArray;
}
|
.gpio_read_ultrasonic(rbHandle, rbTrigger, rbEcho, rbTriggerTime) ⇒ Object
**************************************************************************
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 |
# File 'ext/lgpio/lgpio.c', line 459
static VALUE gpio_read_ultrasonic(VALUE self, VALUE rbHandle, VALUE rbTrigger, VALUE rbEcho, VALUE rbTriggerTime) {
int handle = NUM2UINT(rbHandle);
int trigger = NUM2UINT(rbTrigger);
int echo = NUM2UINT(rbEcho);
uint32_t triggerTime = NUM2UINT(rbTriggerTime);
struct timespec start;
struct timespec now;
bool echoSeen = false;
// Pull down avoids false readings if disconnected.
lgGpioClaimInput(handle, LG_SET_PULL_DOWN, echo);
// Initial pulse on the triger pin.
lgGpioClaimOutput(handle, LG_SET_PULL_NONE, trigger, 0);
microDelay(5);
lgGpioWrite(handle, trigger, 1);
microDelay(triggerTime);
lgGpioWrite(handle, trigger, 0);
clock_gettime(CLOCK_MONOTONIC, &start);
now = start;
// Wait for echo to go high, up to 25,000 us after trigger.
while(nanoDiff(&now, &start) < 25000000){
clock_gettime(CLOCK_MONOTONIC, &now);
if (lgGpioRead(handle, echo) == 1) {
echoSeen = true;
start = now;
break;
}
}
if (!echoSeen) return Qnil;
// Wait for echo to go low again, up to 25,000 us after echo start.
while(nanoDiff(&now, &start) < 25000000){
clock_gettime(CLOCK_MONOTONIC, &now);
if (lgGpioRead(handle, echo) == 0) break;
}
// High pulse time in microseconds.
return INT2NUM(round(nanoDiff(&now, &start) / 1000.0));
}
|
.gpio_set_debounce(handle, gpio, debounce) ⇒ Object
Alerts / Reports
135 136 137 138 |
# File 'ext/lgpio/lgpio.c', line 135
static VALUE gpio_set_debounce(VALUE self, VALUE handle, VALUE gpio, VALUE debounce) {
int result = lgGpioSetDebounce(NUM2INT(handle), NUM2INT(gpio), NUM2INT(debounce));
return INT2NUM(result);
}
|
.gpio_start_reporting ⇒ Object
156 157 158 159 |
# File 'ext/lgpio/lgpio.c', line 156 static VALUE gpio_start_reporting(VALUE self) { lgGpioSetSamplesFunc(queue_gpio_reports, NULL); return Qnil; } |
.gpio_write(handle, gpio, level) ⇒ Object
88 89 90 91 |
# File 'ext/lgpio/lgpio.c', line 88
static VALUE gpio_write(VALUE self, VALUE handle, VALUE gpio, VALUE level) {
int result = lgGpioWrite(NUM2INT(handle), NUM2INT(gpio), NUM2INT(level));
return INT2NUM(result);
}
|
.group_claim_input(handle, gpios, flags) ⇒ Object
Grouped
93 94 95 96 97 98 99 100 101 102 103 |
# File 'ext/lgpio/lgpio.c', line 93
static VALUE group_claim_input(VALUE self, VALUE handle, VALUE gpios, VALUE flags) {
Check_Type(gpios, T_ARRAY);
int count = rb_array_len(gpios);
int lgGpios[count];
int i;
for(i=0; i<count; i++) {
lgGpios[i] = NUM2INT(rb_ary_entry(gpios, i));
}
int result = lgGroupClaimInput(NUM2INT(handle), NUM2INT(flags), count, lgGpios);
return INT2NUM(result);
}
|
.group_claim_output(handle, gpios, flags, levels) ⇒ Object
105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'ext/lgpio/lgpio.c', line 105
static VALUE group_claim_output(VALUE self, VALUE handle, VALUE gpios, VALUE flags, VALUE levels) {
Check_Type(gpios, T_ARRAY);
int count = rb_array_len(gpios);
int lgGpios[count];
int lgLevels[count];
int i;
for(i=0; i<count; i++) {
lgGpios[i] = NUM2INT(rb_ary_entry(gpios, i));
lgLevels[i] = NUM2INT(rb_ary_entry(levels, i));
}
int result = lgGroupClaimOutput(NUM2INT(handle), NUM2INT(flags), count, lgGpios, lgLevels);
return INT2NUM(result);
}
|
.group_free(handle, gpio) ⇒ Object
119 120 121 122 |
# File 'ext/lgpio/lgpio.c', line 119
static VALUE group_free(VALUE self, VALUE handle, VALUE gpio) {
int result = lgGroupFree(NUM2INT(handle), NUM2INT(gpio));
return INT2NUM(result);
}
|
.group_read(handle, gpio) ⇒ Object
124 125 126 127 128 |
# File 'ext/lgpio/lgpio.c', line 124
static VALUE group_read(VALUE self, VALUE handle, VALUE gpio) {
uint64_t result;
lgGroupRead(NUM2INT(handle), NUM2INT(gpio), &result);
return UINT2NUM(result);
}
|
.group_write(handle, gpio, bits, mask) ⇒ Object
130 131 132 133 |
# File 'ext/lgpio/lgpio.c', line 130
static VALUE group_write(VALUE self, VALUE handle, VALUE gpio, VALUE bits, VALUE mask) {
int result = lgGroupWrite(NUM2INT(handle), NUM2INT(gpio), NUM2UINT(bits), NUM2UINT(mask));
return INT2NUM(result);
}
|
.i2c_bb_read_byte(rbSCL_H, rbSCL_L, rbSDA_H, rbSDA_L, rbACK) ⇒ Object
646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 |
# File 'ext/lgpio/lgpio.c', line 646
static VALUE i2c_bb_read_byte(VALUE self, VALUE rbSCL_H, VALUE rbSCL_L, VALUE rbSDA_H, VALUE rbSDA_L, VALUE rbACK) {
int scl_H = NUM2INT(rbSCL_H);
int scl_L = NUM2INT(rbSCL_L);
int sda_H = NUM2INT(rbSDA_H);
int sda_L = NUM2INT(rbSDA_L);
uint8_t ack = RTEST(rbACK);
// Prevent caching by setting opposite to first state SDA will take.
uint8_t sdaState = 0;
uint8_t b;
uint8_t bit;
// Receive MSB first.
for (int i=7; i>=0; i--) {
i2c_bb_set_sda(sda_H, sda_L, &sdaState, 1);
lgGpioWrite(scl_H, scl_L, 1);
bit = lgGpioRead(sda_H, sda_L);
lgGpioWrite(scl_H, scl_L, 0);
bitWriteU8(&b, i, bit);
}
// Send ACK or NACK.
i2c_bb_set_sda(sda_H, sda_L, &sdaState, ack ^ 0b1);
lgGpioWrite(scl_H, scl_L, 1);
lgGpioWrite(scl_H, scl_L, 0);
return UINT2NUM(b);
}
|
.i2c_bb_write_byte(rbSCL_H, rbSCL_L, rbSDA_H, rbSDA_L, rbByte) ⇒ Object
Bit-bang I2C Helpers
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 |
# File 'ext/lgpio/lgpio.c', line 676
static VALUE i2c_bb_write_byte(VALUE self, VALUE rbSCL_H, VALUE rbSCL_L, VALUE rbSDA_H, VALUE rbSDA_L, VALUE rbByte) {
int scl_H = NUM2INT(rbSCL_H);
int scl_L = NUM2INT(rbSCL_L);
int sda_H = NUM2INT(rbSDA_H);
int sda_L = NUM2INT(rbSDA_L);
uint8_t b = NUM2UINT(rbByte);
// Prevent caching by setting opposite to first state SDA will take.
uint8_t sdaState = bitReadU8(&b, 7) ^ 0b1;
uint8_t ack;
// Write MSBFIRST.
for (int i=7; i>=0; i--) {
i2c_bb_set_sda(sda_H, sda_L, &sdaState, bitReadU8(&b, i));
lgGpioWrite(scl_H, scl_L, 1);
lgGpioWrite(scl_H, scl_L, 0);
}
// Read and return ACK.
i2c_bb_set_sda(sda_H, sda_L, &sdaState, 1);
lgGpioWrite(scl_H, scl_L, 1);
ack = lgGpioRead(sda_H, sda_L);
lgGpioWrite(scl_H, scl_L, 0);
return (ack == 0) ? Qtrue : Qfalse;
}
|
.i2c_close(handle) ⇒ Object
282 283 284 285 |
# File 'ext/lgpio/lgpio.c', line 282
static VALUE i2c_close(VALUE self, VALUE handle){
int result = lgI2cClose(NUM2INT(handle));
return INT2NUM(result);
}
|
.i2c_open(i2cDev, i2cAddr, i2cFlags) ⇒ Object
**************************************************************************
277 278 279 280 |
# File 'ext/lgpio/lgpio.c', line 277
static VALUE i2c_open(VALUE self, VALUE i2cDev, VALUE i2cAddr, VALUE i2cFlags){
int handle = lgI2cOpen(NUM2INT(i2cDev), NUM2INT(i2cAddr), NUM2INT(i2cFlags));
return INT2NUM(handle);
}
|
.i2c_read_device(handle, count) ⇒ Object
302 303 304 305 306 307 308 309 310 311 312 313 314 |
# File 'ext/lgpio/lgpio.c', line 302
static VALUE i2c_read_device(VALUE self, VALUE handle, VALUE count){
int rxCount = NUM2INT(count);
uint8_t rxBuf[rxCount];
int result = lgI2cReadDevice(NUM2INT(handle), rxBuf, rxCount);
if(result < 0) return INT2NUM(result);
VALUE retArray = rb_ary_new2(rxCount);
for(int i=0; i<rxCount; i++){
rb_ary_store(retArray, i, UINT2NUM(rxBuf[i]));
}
return retArray;
}
|
.i2c_write_device(handle, txArray) ⇒ Object
287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
# File 'ext/lgpio/lgpio.c', line 287
static VALUE i2c_write_device(VALUE self, VALUE handle, VALUE txArray){
Check_Type(txArray, T_ARRAY);
int count = rb_array_len(txArray);
uint8_t txBuf[count];
VALUE currentByte;
for(int i=0; i<count; i++){
currentByte = rb_ary_entry(txArray, i);
Check_Type(currentByte, T_FIXNUM);
txBuf[i] = NUM2CHR(currentByte);
}
int result = lgI2cWriteDevice(NUM2INT(handle), txBuf, count);
return INT2NUM(result);
}
|
.i2c_zip(handle, txArray, rb_rxCount) ⇒ Object
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 |
# File 'ext/lgpio/lgpio.c', line 316
static VALUE i2c_zip(VALUE self, VALUE handle, VALUE txArray, VALUE rb_rxCount){
Check_Type(txArray, T_ARRAY);
int txCount = rb_array_len(txArray);
uint8_t txBuf[txCount];
VALUE currentByte;
for(int i=0; i<txCount; i++){
currentByte = rb_ary_entry(txArray, i);
Check_Type(currentByte, T_FIXNUM);
txBuf[i] = NUM2CHR(currentByte);
}
int rxCount = NUM2INT(rb_rxCount);
uint8_t rxBuf[rxCount+1];
// Buffer size must be rxCount+1 or result is LG_BAD_I2C_RLEN
int result = lgI2cZip(NUM2INT(handle), txBuf, txCount, rxBuf, rxCount+1);
if(result < 0) return INT2NUM(result);
if (rxCount == 0) return Qnil;
VALUE retArray = rb_ary_new2(rxCount);
for(int i=0; i<rxCount; i++){
rb_ary_store(retArray, i, UINT2NUM(rxBuf[i]));
}
return retArray;
}
|
.micro_delay(micros) ⇒ Object
Generic Helpers
45 46 47 48 |
# File 'ext/lgpio/lgpio.c', line 45
static VALUE rbMicroDelay(VALUE self, VALUE micros) {
microDelay(NUM2ULL(micros));
return Qnil;
}
|
.one_wire_bit_read(rbHandle, rbGPIO) ⇒ Object
**************************************************************************
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 |
# File 'ext/lgpio/lgpio.c', line 559
static VALUE one_wire_bit_read(VALUE self, VALUE rbHandle, VALUE rbGPIO) {
int handle = NUM2INT(rbHandle);
int gpio = NUM2INT(rbGPIO);
uint8_t bit = 1;
struct timespec start;
struct timespec now;
// Start the read slot.
lgGpioWrite(handle, gpio, 0);
microDelay(1);
lgGpioWrite(handle, gpio, 1);
// Poll for 60us to see if pin goes low.
clock_gettime(CLOCK_MONOTONIC, &start);
now = start;
while(nanoDiff(&now, &start) < 60000){
if (lgGpioRead(handle, gpio) == 0) bit = 0;
clock_gettime(CLOCK_MONOTONIC, &now);
}
return UINT2NUM(bit);
}
|
.one_wire_bit_write(rbHandle, rbGPIO, rbBit) ⇒ Object
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 |
# File 'ext/lgpio/lgpio.c', line 581
static VALUE one_wire_bit_write(VALUE self, VALUE rbHandle, VALUE rbGPIO, VALUE rbBit) {
int handle = NUM2INT(rbHandle);
int gpio = NUM2INT(rbGPIO);
uint8_t bit = NUM2CHR(rbBit);
// Write slot starts by going low for at least 1us.
lgGpioWrite(handle, gpio, 0);
microDelay(1);
// If 0, keep it low for the rest of the 60us write slot, then release.
if (bit == 0) {
microDelay(59);
lgGpioWrite(handle, gpio, 1);
// If 1, release first, then wait the rest of the 60us slot.
} else {
lgGpioWrite(handle, gpio, 1);
microDelay(59);
}
// Minimum 1us recovery time after each slot.
microDelay(1);
return Qnil;
}
|
.one_wire_reset(rbHandle, rbGPIO) ⇒ Object
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 |
# File 'ext/lgpio/lgpio.c', line 604
static VALUE one_wire_reset(VALUE self, VALUE rbHandle, VALUE rbGPIO) {
int handle = NUM2INT(rbHandle);
int gpio = NUM2INT(rbGPIO);
struct timespec start;
uint8_t presence = 1;
// Hold low for 500us to reset, then go high.
lgGpioFree(handle, gpio);
lgGpioClaimOutput(handle, LG_SET_OPEN_DRAIN | LG_SET_PULL_UP, gpio, 0);
microDelay(500);
lgGpioWrite(handle, gpio, 1);
// Poll for 250us. If a device pulls the line low, return 0 (device present).
clock_gettime(CLOCK_MONOTONIC, &start);
while(nanosSince(&start) < 250000){
if (lgGpioRead(handle, gpio) == 0) presence = 0;
}
return UINT2NUM(presence);
}
|
.spi_close(handle) ⇒ Object
350 351 352 353 |
# File 'ext/lgpio/lgpio.c', line 350
static VALUE spi_close(VALUE self, VALUE handle){
int result = lgSpiClose(NUM2INT(handle));
return INT2NUM(result);
}
|
.spi_open(spiDev, spiChan, spiBaud, spiFlags) ⇒ Object
**************************************************************************
345 346 347 348 |
# File 'ext/lgpio/lgpio.c', line 345
static VALUE spi_open(VALUE self, VALUE spiDev, VALUE spiChan, VALUE spiBaud, VALUE spiFlags){
int handle = lgSpiOpen(NUM2INT(spiDev), NUM2INT(spiChan), NUM2INT(spiBaud), NUM2INT(spiFlags));
return INT2NUM(handle);
}
|
.spi_read(handle, rxCount) ⇒ Object
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 |
# File 'ext/lgpio/lgpio.c', line 355
static VALUE spi_read(VALUE self, VALUE handle, VALUE rxCount){
int count = NUM2INT(rxCount);
// Not sure if this needs null termination like I2C. +1 won't hurt.
uint8_t rxBuf[count+1];
int result = lgSpiRead(NUM2INT(handle), rxBuf, count);
if(result < 0) return INT2NUM(result);
VALUE retArray = rb_ary_new2(count);
for(int i=0; i<count; i++){
rb_ary_store(retArray, i, UINT2NUM(rxBuf[i]));
}
return retArray;
}
|
.spi_write(handle, txArray) ⇒ Object
371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
# File 'ext/lgpio/lgpio.c', line 371
static VALUE spi_write(VALUE self, VALUE handle, VALUE txArray){
Check_Type(txArray, T_ARRAY);
int count = rb_array_len(txArray);
uint8_t txBuf[count];
VALUE currentByte;
for(int i=0; i<count; i++){
currentByte = rb_ary_entry(txArray, i);
Check_Type(currentByte, T_FIXNUM);
txBuf[i] = NUM2CHR(currentByte);
}
int result = lgSpiWrite(NUM2INT(handle), txBuf, count);
return INT2NUM(result);
}
|
.spi_ws2812_write(handle, pixelArray) ⇒ Object
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 |
# File 'ext/lgpio/lgpio.c', line 419
static VALUE spi_ws2812_write(VALUE self, VALUE handle, VALUE pixelArray){
Check_Type(pixelArray, T_ARRAY);
int count = rb_array_len(pixelArray);
// Pull low for at least one byte at 2.4 Mhz before data, and 90 after.
int zeroesBefore = 1;
int zeroesAfter = 90;
int txBufLength = zeroesBefore + (count*3) + zeroesAfter;
uint8_t txBuf[txBufLength];
for (int i=0; i<txBufLength; i++) { txBuf[i] = 0; }
VALUE currentByte_rb;
uint8_t currentByte;
uint8_t currentBit;
uint32_t temp;
for (int i=0; i<count; i++){
temp = 0;
currentByte_rb = rb_ary_entry(pixelArray, i);
Check_Type(currentByte_rb, T_FIXNUM);
currentByte = NUM2CHR(currentByte_rb);
for (int i=7; i>=0; i--) {
currentBit = (currentByte & (1 << i));
temp = temp << 3;
temp = (currentBit == 0) ? (temp | 0b100) : (temp | 0b110);
}
txBuf[zeroesBefore+(i*3)] = (temp >> 16) & 0xFF;
txBuf[zeroesBefore+(i*3)+1] = (temp >> 8) & 0xFF;
txBuf[zeroesBefore+(i*3)+2] = temp & 0xFF;
}
int result = lgSpiWrite(NUM2INT(handle), txBuf, txBufLength);
return INT2NUM(result);
}
|
.spi_xfer(handle, txArray, rxLength) ⇒ Object
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 |
# File 'ext/lgpio/lgpio.c', line 386
static VALUE spi_xfer(VALUE self, VALUE handle, VALUE txArray, VALUE rxLength){
Check_Type(txArray, T_ARRAY);
int txCount = rb_array_len(txArray);
int rxCount = NUM2INT(rxLength);
int count = txCount;
if (rxCount > txCount) count = rxCount;
uint8_t txBuf[count];
// Not sure if this needs null termination like I2C. +1 won't hurt.
uint8_t rxBuf[count+1];
// Add given bytes to transmit.
VALUE currentByte;
for(int i=0; i<txCount; i++){
currentByte = rb_ary_entry(txArray, i);
Check_Type(currentByte, T_FIXNUM);
txBuf[i] = NUM2CHR(currentByte);
}
// Extend with zeroes if reading more than writing.
if (count > txCount) {
for(int i=txCount; i<count; i++) txBuf[i] = 0;
}
int result = lgSpiXfer(NUM2INT(handle), txBuf, rxBuf, count);
if(result < 0) return INT2NUM(result);
VALUE retArray = rb_ary_new2(rxCount);
for(int i=0; i<rxCount; i++){
rb_ary_store(retArray, i, UINT2NUM(rxBuf[i]));
}
return retArray;
}
|
.tx_busy(handle, gpio, kind) ⇒ Object
**************************************************************************
184 185 186 187 |
# File 'ext/lgpio/lgpio.c', line 184
static VALUE tx_busy(VALUE self, VALUE handle, VALUE gpio, VALUE kind) {
int result = lgTxBusy(NUM2INT(handle), NUM2INT(gpio), NUM2INT(kind));
return INT2NUM(result);
}
|
.tx_pulse(handle, gpio, on, off, offset, cycles) ⇒ Object
194 195 196 197 |
# File 'ext/lgpio/lgpio.c', line 194
static VALUE tx_pulse(VALUE self, VALUE handle, VALUE gpio, VALUE on, VALUE off, VALUE offset, VALUE cycles) {
int result = lgTxPulse(NUM2INT(handle), NUM2INT(gpio), NUM2INT(on), NUM2INT(off), NUM2INT(offset), NUM2INT(cycles));
return INT2NUM(result);
}
|
.tx_pwm(handle, gpio, freq, duty, offset, cycles) ⇒ Object
199 200 201 202 |
# File 'ext/lgpio/lgpio.c', line 199
static VALUE tx_pwm(VALUE self, VALUE handle, VALUE gpio, VALUE freq, VALUE duty, VALUE offset, VALUE cycles) {
int result = lgTxPwm(NUM2INT(handle), NUM2INT(gpio), NUM2INT(freq), NUM2DBL(duty), NUM2INT(offset), NUM2INT(cycles));
return INT2NUM(result);
}
|
.tx_room(handle, gpio, kind) ⇒ Object
189 190 191 192 |
# File 'ext/lgpio/lgpio.c', line 189
static VALUE tx_room(VALUE self, VALUE handle, VALUE gpio, VALUE kind) {
int result = lgTxRoom(NUM2INT(handle), NUM2INT(gpio), NUM2INT(kind));
return INT2NUM(result);
}
|
.tx_servo(handle, gpio, width, freq, offset, cycles) ⇒ Object
Don’t use this. Servo will jitter.
204 205 206 207 |
# File 'ext/lgpio/lgpio.c', line 204
static VALUE tx_servo(VALUE self, VALUE handle, VALUE gpio, VALUE width, VALUE freq, VALUE offset, VALUE cycles) {
int result = lgTxServo(NUM2INT(handle), NUM2INT(gpio), NUM2INT(width), NUM2INT(freq), NUM2INT(offset), NUM2INT(cycles));
return INT2NUM(result);
}
|
.tx_wave(handle, lead_gpio, pulses) ⇒ Object
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'ext/lgpio/lgpio.c', line 209
static VALUE tx_wave(VALUE self, VALUE handle, VALUE lead_gpio, VALUE pulses) {
// Copy Ruby array to array of lgPulse_t.
Check_Type(pulses, T_ARRAY);
int pulseCount = rb_array_len(pulses);
lgPulse_t pulsesOut[pulseCount];
VALUE rbPulse;
int i;
for(i=0; i<pulseCount; i++) {
rbPulse = rb_ary_entry(pulses, i);
pulsesOut[i].bits = NUM2UINT(rb_ary_entry(rbPulse, 0));
pulsesOut[i].mask = NUM2UINT(rb_ary_entry(rbPulse, 1));
pulsesOut[i].delay = NUM2INT (rb_ary_entry(rbPulse, 2));
}
// Add it to wave queue.
int result = lgTxWave(NUM2INT(handle), NUM2INT(lead_gpio), pulseCount, pulsesOut);
return INT2NUM(result);
}
|