extmod/modbluetooth: Make modbluetooth event not a bitfield.

There doesn't appear to be any use for only triggering on specific events,
so it's just easier to number them sequentially.  This makes them smaller
values so they take up only 1 byte in the ringbuf, only 1 byte for the
opcode in the bytecode, and makes room for more events.

Also add a couple of new event types that need to be implemented (to avoid
re-numbering later).

And rename _COMPLETE and _STATUS to _DONE for consistency.

In the future the "trigger" keyword argument can be reinstated by requiring
the user to compute the bitmask, eg:

    ble.irq(handler, 1 << _IRQ_SCAN_RESULT | 1 << _IRQ_SCAN_DONE)
This commit is contained in:
Jim Mussared 2020-05-11 21:20:07 +10:00 committed by Damien George
parent 02cc4462b7
commit e6881f0829
7 changed files with 92 additions and 83 deletions

View File

@ -11,8 +11,8 @@ from ble_advertising import advertising_payload
from micropython import const
_IRQ_CENTRAL_CONNECT = const(1 << 0)
_IRQ_CENTRAL_DISCONNECT = const(1 << 1)
_IRQ_CENTRAL_CONNECT = const(1)
_IRQ_CENTRAL_DISCONNECT = const(2)
# org.bluetooth.service.environmental_sensing
_ENV_SENSE_UUID = bluetooth.UUID(0x181A)

View File

@ -10,22 +10,25 @@ from ble_advertising import decode_services, decode_name
from micropython import const
_IRQ_CENTRAL_CONNECT = const(1 << 0)
_IRQ_CENTRAL_DISCONNECT = const(1 << 1)
_IRQ_GATTS_WRITE = const(1 << 2)
_IRQ_GATTS_READ_REQUEST = const(1 << 3)
_IRQ_SCAN_RESULT = const(1 << 4)
_IRQ_SCAN_COMPLETE = const(1 << 5)
_IRQ_PERIPHERAL_CONNECT = const(1 << 6)
_IRQ_PERIPHERAL_DISCONNECT = const(1 << 7)
_IRQ_GATTC_SERVICE_RESULT = const(1 << 8)
_IRQ_GATTC_CHARACTERISTIC_RESULT = const(1 << 9)
_IRQ_GATTC_DESCRIPTOR_RESULT = const(1 << 10)
_IRQ_GATTC_READ_RESULT = const(1 << 11)
_IRQ_GATTC_WRITE_STATUS = const(1 << 12)
_IRQ_GATTC_NOTIFY = const(1 << 13)
_IRQ_GATTC_INDICATE = const(1 << 14)
_IRQ_ALL = const(0xFFFF)
_IRQ_CENTRAL_CONNECT = const(1)
_IRQ_CENTRAL_DISCONNECT = const(2)
_IRQ_GATTS_WRITE = const(3)
_IRQ_GATTS_READ_REQUEST = const(4)
_IRQ_SCAN_RESULT = const(5)
_IRQ_SCAN_DONE = const(6)
_IRQ_PERIPHERAL_CONNECT = const(7)
_IRQ_PERIPHERAL_DISCONNECT = const(8)
_IRQ_GATTC_SERVICE_RESULT = const(9)
_IRQ_GATTC_SERVICE_DONE = const(10)
_IRQ_GATTC_CHARACTERISTIC_RESULT = const(11)
_IRQ_GATTC_CHARACTERISTIC_DONE = const(12)
_IRQ_GATTC_DESCRIPTOR_RESULT = const(13)
_IRQ_GATTC_DESCRIPTOR_DONE = const(14)
_IRQ_GATTC_READ_RESULT = const(15)
_IRQ_GATTC_READ_DONE = const(16)
_IRQ_GATTC_WRITE_DONE = const(17)
_IRQ_GATTC_NOTIFY = const(18)
_IRQ_GATTC_INDICATE = const(19)
_ADV_IND = const(0x00)
_ADV_DIRECT_IND = const(0x01)
@ -93,7 +96,7 @@ class BLETemperatureCentral:
self._name = decode_name(adv_data) or "?"
self._ble.gap_scan(None)
elif event == _IRQ_SCAN_COMPLETE:
elif event == _IRQ_SCAN_DONE:
if self._scan_callback:
if self._addr:
# Found a device during the scan (and the scan was explicitly stopped).

View File

@ -5,9 +5,9 @@ from ble_advertising import advertising_payload
from micropython import const
_IRQ_CENTRAL_CONNECT = const(1 << 0)
_IRQ_CENTRAL_DISCONNECT = const(1 << 1)
_IRQ_GATTS_WRITE = const(1 << 2)
_IRQ_CENTRAL_CONNECT = const(1)
_IRQ_CENTRAL_DISCONNECT = const(2)
_IRQ_GATTS_WRITE = const(3)
_UART_UUID = bluetooth.UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
_UART_TX = (

View File

@ -4,7 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2018 Ayke van Laethem
* Copyright (c) 2019 Jim Mussared
* Copyright (c) 2019-2020 Jim Mussared
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -57,7 +57,6 @@ STATIC const mp_obj_type_t bluetooth_uuid_type;
typedef struct {
mp_obj_base_t base;
mp_obj_t irq_handler;
uint16_t irq_trigger;
bool irq_scheduled;
mp_obj_t irq_data_tuple;
uint8_t irq_data_addr_bytes[6];
@ -249,7 +248,6 @@ STATIC mp_obj_t bluetooth_ble_make_new(const mp_obj_type_t *type, size_t n_args,
o->base.type = &bluetooth_ble_type;
o->irq_handler = mp_const_none;
o->irq_trigger = 0;
// Pre-allocate the event data tuple to prevent needing to allocate in the IRQ handler.
o->irq_data_tuple = mp_obj_new_tuple(MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN, NULL);
@ -372,10 +370,9 @@ STATIC mp_obj_t bluetooth_ble_config(size_t n_args, const mp_obj_t *args, mp_map
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bluetooth_ble_config_obj, 1, bluetooth_ble_config);
STATIC mp_obj_t bluetooth_ble_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_handler, ARG_trigger };
enum { ARG_handler };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_handler, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_trigger, MP_ARG_INT, {.u_int = MP_BLUETOOTH_IRQ_ALL} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
@ -388,7 +385,6 @@ STATIC mp_obj_t bluetooth_ble_irq(size_t n_args, const mp_obj_t *pos_args, mp_ma
MICROPY_PY_BLUETOOTH_ENTER
mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
o->irq_handler = callback;
o->irq_trigger = args[ARG_trigger].u_int;
MICROPY_PY_BLUETOOTH_EXIT
return mp_const_none;
@ -854,7 +850,7 @@ STATIC mp_obj_t bluetooth_ble_invoke_irq(mp_obj_t none_in) {
for (;;) {
MICROPY_PY_BLUETOOTH_ENTER
mp_int_t event = event = ringbuf_get16(&o->ringbuf);
mp_int_t event = ringbuf_get(&o->ringbuf);
if (event < 0) {
// Nothing available in ringbuf.
MICROPY_PY_BLUETOOTH_EXIT
@ -878,7 +874,7 @@ STATIC mp_obj_t bluetooth_ble_invoke_irq(mp_obj_t none_in) {
} else if (event == MP_BLUETOOTH_IRQ_SCAN_RESULT) {
// addr_type, addr, adv_type, rssi, adv_data
ringbuf_extract(&o->ringbuf, data_tuple, 0, 1, &o->irq_data_addr, 2, NULL, &o->irq_data_data);
} else if (event == MP_BLUETOOTH_IRQ_SCAN_COMPLETE) {
} else if (event == MP_BLUETOOTH_IRQ_SCAN_DONE) {
// No params required.
data_tuple->len = 0;
} else if (event == MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT) {
@ -893,7 +889,7 @@ STATIC mp_obj_t bluetooth_ble_invoke_irq(mp_obj_t none_in) {
} else if (event == MP_BLUETOOTH_IRQ_GATTC_READ_RESULT || event == MP_BLUETOOTH_IRQ_GATTC_NOTIFY || event == MP_BLUETOOTH_IRQ_GATTC_INDICATE) {
// conn_handle, value_handle, data
ringbuf_extract(&o->ringbuf, data_tuple, 2, 0, NULL, 0, NULL, &o->irq_data_data);
} else if (event == MP_BLUETOOTH_IRQ_GATTC_WRITE_STATUS) {
} else if (event == MP_BLUETOOTH_IRQ_GATTC_WRITE_DONE) {
// conn_handle, value_handle, status
ringbuf_extract(&o->ringbuf, data_tuple, 3, 0, NULL, 0, NULL, NULL);
#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
@ -915,23 +911,24 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluetooth_ble_invoke_irq_obj, bluetooth_ble_inv
// Callbacks are called in interrupt context (i.e. can't allocate), so we need to push the data
// into the ringbuf and schedule the callback via mp_sched_schedule.
STATIC bool enqueue_irq(mp_obj_bluetooth_ble_t *o, size_t len, uint16_t event) {
if (!o || !(o->irq_trigger & event) || o->irq_handler == mp_const_none) {
STATIC bool enqueue_irq(mp_obj_bluetooth_ble_t *o, size_t len, uint8_t event) {
if (!o || o->irq_handler == mp_const_none) {
return false;
}
if (ringbuf_free(&o->ringbuf) < len + 2) {
// Check if there is enough room for <event-type><payload>.
if (ringbuf_free(&o->ringbuf) < len + 1) {
// Ringbuffer doesn't have room (and is therefore non-empty).
// If this is another scan result, or the front of the ringbuffer isn't a scan result, then nothing to do.
if (event == MP_BLUETOOTH_IRQ_SCAN_RESULT || ringbuf_peek16(&o->ringbuf) != MP_BLUETOOTH_IRQ_SCAN_RESULT) {
if (event == MP_BLUETOOTH_IRQ_SCAN_RESULT || ringbuf_peek(&o->ringbuf) != MP_BLUETOOTH_IRQ_SCAN_RESULT) {
return false;
}
// Front of the queue is a scan result, remove it.
// event, addr_type, addr, adv_type, rssi
int n = 2 + 1 + 6 + 1 + 1;
int n = 1 + 1 + 6 + 1 + 1;
for (int i = 0; i < n; ++i) {
ringbuf_get(&o->ringbuf);
}
@ -943,7 +940,7 @@ STATIC bool enqueue_irq(mp_obj_bluetooth_ble_t *o, size_t len, uint16_t event) {
}
// Append this event, the caller will then append the arguments.
ringbuf_put16(&o->ringbuf, event);
ringbuf_put(&o->ringbuf, event);
return true;
}
@ -959,7 +956,7 @@ STATIC void schedule_ringbuf(mp_uint_t atomic_state) {
}
}
void mp_bluetooth_gap_on_connected_disconnected(uint16_t event, uint16_t conn_handle, uint8_t addr_type, const uint8_t *addr) {
void mp_bluetooth_gap_on_connected_disconnected(uint8_t event, uint16_t conn_handle, uint8_t addr_type, const uint8_t *addr) {
MICROPY_PY_BLUETOOTH_ENTER
mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
if (enqueue_irq(o, 2 + 1 + 6, event)) {
@ -986,7 +983,7 @@ void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle) {
void mp_bluetooth_gap_on_scan_complete(void) {
MICROPY_PY_BLUETOOTH_ENTER
mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
if (enqueue_irq(o, 0, MP_BLUETOOTH_IRQ_SCAN_COMPLETE)) {
if (enqueue_irq(o, 0, MP_BLUETOOTH_IRQ_SCAN_DONE)) {
}
schedule_ringbuf(atomic_state);
}
@ -1048,7 +1045,7 @@ void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t hand
schedule_ringbuf(atomic_state);
}
size_t mp_bluetooth_gattc_on_data_available_start(uint16_t event, uint16_t conn_handle, uint16_t value_handle, size_t data_len, mp_uint_t *atomic_state_out) {
size_t mp_bluetooth_gattc_on_data_available_start(uint8_t event, uint16_t conn_handle, uint16_t value_handle, size_t data_len, mp_uint_t *atomic_state_out) {
MICROPY_PY_BLUETOOTH_ENTER
*atomic_state_out = atomic_state;
mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
@ -1077,7 +1074,7 @@ void mp_bluetooth_gattc_on_data_available_end(mp_uint_t atomic_state) {
void mp_bluetooth_gattc_on_write_status(uint16_t conn_handle, uint16_t value_handle, uint16_t status) {
MICROPY_PY_BLUETOOTH_ENTER
mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
if (enqueue_irq(o, 2 + 2 + 2, MP_BLUETOOTH_IRQ_GATTC_WRITE_STATUS)) {
if (enqueue_irq(o, 2 + 2 + 2, MP_BLUETOOTH_IRQ_GATTC_WRITE_DONE)) {
ringbuf_put16(&o->ringbuf, conn_handle);
ringbuf_put16(&o->ringbuf, value_handle);
ringbuf_put16(&o->ringbuf, status);
@ -1092,7 +1089,7 @@ void mp_bluetooth_gattc_on_write_status(uint16_t conn_handle, uint16_t value_han
// On ESP32, for example, this is not the case.
bool mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle) {
mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
if ((o->irq_trigger & MP_BLUETOOTH_IRQ_GATTS_READ_REQUEST) && o->irq_handler != mp_const_none) {
if (o->irq_handler != mp_const_none) {
// Use pre-allocated tuple because this is a hard IRQ.
mp_obj_tuple_t *data = MP_OBJ_TO_PTR(o->irq_data_tuple);
data->items[0] = MP_OBJ_NEW_SMALL_INT(conn_handle);

View File

@ -4,7 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2018 Ayke van Laethem
* Copyright (c) 2019 Jim Mussared
* Copyright (c) 2019-2020 Jim Mussared
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -88,48 +88,50 @@
#define MP_BLUETOOTH_ADDR_RANDOM_PRIVATE_NON_RESOLVABLE (0x13) // Random private non-resolvable address. (NRF SD 0x03)
// Event codes for the IRQ handler.
// Can also be combined to pass to the trigger param to select which events you
// are interested in.
// Note this is currently stored in a uint16_t (in irq_trigger, and the event
// arg to the irq handler), so one spare value remaining.
#define MP_BLUETOOTH_IRQ_CENTRAL_CONNECT (1 << 0)
#define MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT (1 << 1)
#define MP_BLUETOOTH_IRQ_GATTS_WRITE (1 << 2)
#define MP_BLUETOOTH_IRQ_GATTS_READ_REQUEST (1 << 3)
#define MP_BLUETOOTH_IRQ_SCAN_RESULT (1 << 4)
#define MP_BLUETOOTH_IRQ_SCAN_COMPLETE (1 << 5)
#define MP_BLUETOOTH_IRQ_PERIPHERAL_CONNECT (1 << 6)
#define MP_BLUETOOTH_IRQ_PERIPHERAL_DISCONNECT (1 << 7)
#define MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT (1 << 8)
#define MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT (1 << 9)
#define MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_RESULT (1 << 10)
#define MP_BLUETOOTH_IRQ_GATTC_READ_RESULT (1 << 11)
#define MP_BLUETOOTH_IRQ_GATTC_WRITE_STATUS (1 << 12)
#define MP_BLUETOOTH_IRQ_GATTC_NOTIFY (1 << 13)
#define MP_BLUETOOTH_IRQ_GATTC_INDICATE (1 << 14)
#define MP_BLUETOOTH_IRQ_ALL (0xffff)
#define MP_BLUETOOTH_IRQ_CENTRAL_CONNECT (1)
#define MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT (2)
#define MP_BLUETOOTH_IRQ_GATTS_WRITE (3)
#define MP_BLUETOOTH_IRQ_GATTS_READ_REQUEST (4)
#define MP_BLUETOOTH_IRQ_SCAN_RESULT (5)
#define MP_BLUETOOTH_IRQ_SCAN_DONE (6)
#define MP_BLUETOOTH_IRQ_PERIPHERAL_CONNECT (7)
#define MP_BLUETOOTH_IRQ_PERIPHERAL_DISCONNECT (8)
#define MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT (9)
#define MP_BLUETOOTH_IRQ_GATTC_SERVICE_DONE (10)
#define MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT (11)
#define MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_DONE (12)
#define MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_RESULT (13)
#define MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_DONE (14)
#define MP_BLUETOOTH_IRQ_GATTC_READ_RESULT (15)
#define MP_BLUETOOTH_IRQ_GATTC_READ_DONE (16)
#define MP_BLUETOOTH_IRQ_GATTC_WRITE_DONE (17)
#define MP_BLUETOOTH_IRQ_GATTC_NOTIFY (18)
#define MP_BLUETOOTH_IRQ_GATTC_INDICATE (19)
/*
These aren't included in the module for space reasons, but can be used
in your Python code if necessary.
from micropython import const
_IRQ_CENTRAL_CONNECT = const(1 << 0)
_IRQ_CENTRAL_DISCONNECT = const(1 << 1)
_IRQ_GATTS_WRITE = const(1 << 2)
_IRQ_GATTS_READ_REQUEST = const(1 << 3)
_IRQ_SCAN_RESULT = const(1 << 4)
_IRQ_SCAN_COMPLETE = const(1 << 5)
_IRQ_PERIPHERAL_CONNECT = const(1 << 6)
_IRQ_PERIPHERAL_DISCONNECT = const(1 << 7)
_IRQ_GATTC_SERVICE_RESULT = const(1 << 8)
_IRQ_GATTC_CHARACTERISTIC_RESULT = const(1 << 9)
_IRQ_GATTC_DESCRIPTOR_RESULT = const(1 << 10)
_IRQ_GATTC_READ_RESULT = const(1 << 11)
_IRQ_GATTC_WRITE_STATUS = const(1 << 12)
_IRQ_GATTC_NOTIFY = const(1 << 13)
_IRQ_GATTC_INDICATE = const(1 << 14)
_IRQ_ALL = const(0xffff)
_IRQ_CENTRAL_CONNECT = const(1)
_IRQ_CENTRAL_DISCONNECT = const(2)
_IRQ_GATTS_WRITE = const(3)
_IRQ_GATTS_READ_REQUEST = const(4)
_IRQ_SCAN_RESULT = const(5)
_IRQ_SCAN_DONE = const(6)
_IRQ_PERIPHERAL_CONNECT = const(7)
_IRQ_PERIPHERAL_DISCONNECT = const(8)
_IRQ_GATTC_SERVICE_RESULT = const(9)
_IRQ_GATTC_SERVICE_DONE = const(10)
_IRQ_GATTC_CHARACTERISTIC_RESULT = const(11)
_IRQ_GATTC_CHARACTERISTIC_DONE = const(12)
_IRQ_GATTC_DESCRIPTOR_RESULT = const(13)
_IRQ_GATTC_DESCRIPTOR_DONE = const(14)
_IRQ_GATTC_READ_RESULT = const(15)
_IRQ_GATTC_READ_DONE = const(16)
_IRQ_GATTC_WRITE_DONE = const(17)
_IRQ_GATTC_NOTIFY = const(18)
_IRQ_GATTC_INDICATE = const(19)
*/
// Common UUID type.
@ -238,7 +240,7 @@ int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const
// API implemented by modbluetooth (called by port-specific implementations):
// Notify modbluetooth that a connection/disconnection event has occurred.
void mp_bluetooth_gap_on_connected_disconnected(uint16_t event, uint16_t conn_handle, uint8_t addr_type, const uint8_t *addr);
void mp_bluetooth_gap_on_connected_disconnected(uint8_t event, uint16_t conn_handle, uint8_t addr_type, const uint8_t *addr);
// Call this when a characteristic is written to.
void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle);
@ -267,7 +269,7 @@ void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t hand
// Notify modbluetooth that a read has completed with data (or notify/indicate data available, use `event` to disambiguate).
// Note: these functions are to be called in a group protected by MICROPY_PY_BLUETOOTH_ENTER/EXIT.
// _start returns the number of bytes to submit to the calls to _chunk, followed by a call to _end.
size_t mp_bluetooth_gattc_on_data_available_start(uint16_t event, uint16_t conn_handle, uint16_t value_handle, size_t data_len, mp_uint_t *atomic_state_out);
size_t mp_bluetooth_gattc_on_data_available_start(uint8_t event, uint16_t conn_handle, uint16_t value_handle, size_t data_len, mp_uint_t *atomic_state_out);
void mp_bluetooth_gattc_on_data_available_chunk(const uint8_t *data, size_t data_len);
void mp_bluetooth_gattc_on_data_available_end(mp_uint_t atomic_state);

View File

@ -4,7 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2019 Damien P. George
* Copyright (c) 2019 Jim Mussared
* Copyright (c) 2019-2020 Jim Mussared
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -612,7 +612,7 @@ int mp_bluetooth_gatts_set_buffer(uint16_t value_handle, size_t len, bool append
#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
STATIC void gattc_on_data_available(uint16_t event, uint16_t conn_handle, uint16_t value_handle, const struct os_mbuf *om) {
STATIC void gattc_on_data_available(uint8_t event, uint16_t conn_handle, uint16_t value_handle, const struct os_mbuf *om) {
size_t len = OS_MBUF_PKTLEN(om);
mp_uint_t atomic_state;
len = mp_bluetooth_gattc_on_data_available_start(event, conn_handle, value_handle, len, &atomic_state);

View File

@ -63,6 +63,13 @@ static inline int ringbuf_get(ringbuf_t *r) {
return v;
}
static inline int ringbuf_peek(ringbuf_t *r) {
if (r->iget == r->iput) {
return -1;
}
return r->buf[r->iget];
}
static inline int ringbuf_put(ringbuf_t *r, uint8_t v) {
uint32_t iput_new = r->iput + 1;
if (iput_new >= r->size) {