From fad3038b035db90c59f297891835d37fd97b79c5 Mon Sep 17 00:00:00 2001 From: Brian Cully Date: Thu, 13 Jun 2019 18:00:42 -0400 Subject: Initial commit. --- nrf52/Makefile | 22 +++++++++++ nrf52/Makefile.feather-52832 | 10 +++++ nrf52/Makefile.feather-52840 | 10 +++++ nrf52/i2c_ring_buffer.cpp | 24 +++++++++++ nrf52/i2c_ring_buffer.h | 21 ++++++++++ nrf52/log.h | 17 ++++++++ nrf52/nrf52.ino | 94 ++++++++++++++++++++++++++++++++++++++++++++ nrf52/state_machine.cpp | 79 +++++++++++++++++++++++++++++++++++++ nrf52/state_machine.h | 28 +++++++++++++ 9 files changed, 305 insertions(+) create mode 100644 nrf52/Makefile create mode 100644 nrf52/Makefile.feather-52832 create mode 100644 nrf52/Makefile.feather-52840 create mode 100644 nrf52/i2c_ring_buffer.cpp create mode 100644 nrf52/i2c_ring_buffer.h create mode 100644 nrf52/log.h create mode 100644 nrf52/nrf52.ino create mode 100644 nrf52/state_machine.cpp create mode 100644 nrf52/state_machine.h (limited to 'nrf52') diff --git a/nrf52/Makefile b/nrf52/Makefile new file mode 100644 index 0000000..fdb47ee --- /dev/null +++ b/nrf52/Makefile @@ -0,0 +1,22 @@ +include ../Makefile.common +#include Makefile.feather-52840 +include Makefile.feather-52832 + +SERIALPORT = $(shell ../find-serial-port $(USBVID) $(USBPID) || echo 'cant-find-serial-port') + +APP = nrf52 + +all: $(BUILDDIR)/$(APP).ino.zip + +flash: $(BUILDDIR)/$(APP).ino.zip $(SERIALPORT) + adafruit-nrfutil dfu serial --package $(BUILDDIR)/$(APP).ino.zip -p $(SERIALPORT) -b 115200 -sb -t 1200 + +console: + screen $(SERIALPORT) 115200 + +# Deps +nrf52.ino: i2c_ring_buffer.cpp state_machine.cpp log.h ../common/i2c_message.h + +i2c_ring_buffer.cpp: i2c_ring_buffer.h + +state_machine.cpp: state_machine.h diff --git a/nrf52/Makefile.feather-52832 b/nrf52/Makefile.feather-52832 new file mode 100644 index 0000000..c2dff2b --- /dev/null +++ b/nrf52/Makefile.feather-52832 @@ -0,0 +1,10 @@ +# -*- mode: Makefile -*- + +VENDOR = adafruit +PLATFORM = nrf52 +BOARD = feather52832 + +EXTRAPREFS = -prefs "build.sd_flags=-DS132" -prefs "build.sd_name=s132" -prefs "build.sd_version=6.1.1" -prefs "build.sd_fwid=0x00B7" + +USBVID = 10c4 +USBPID = ea60 diff --git a/nrf52/Makefile.feather-52840 b/nrf52/Makefile.feather-52840 new file mode 100644 index 0000000..81d7245 --- /dev/null +++ b/nrf52/Makefile.feather-52840 @@ -0,0 +1,10 @@ +# -*- mode: Makefile -*- + +VENDOR = adafruit +PLATFORM = nrf52 +BOARD = feather52840 + +EXTRAPREFS = -prefs "build.sd_name=s140" -prefs "build.sd_version=6.1.1" -prefs "build.sd_fwid=0x00B6" + +USBVID = 239a +USBPID = '0029|8029' diff --git a/nrf52/i2c_ring_buffer.cpp b/nrf52/i2c_ring_buffer.cpp new file mode 100644 index 0000000..0f215f2 --- /dev/null +++ b/nrf52/i2c_ring_buffer.cpp @@ -0,0 +1,24 @@ +#include "i2c_ring_buffer.h" + +#include + +I2CRingBuffer::I2CRingBuffer(): head(0), tail(0) {} + +bool I2CRingBuffer::read(uint8_t *v) { + ATOMIC() { + if (this->head == this->tail) { + return false; + } + + *v = this->buf[this->head]; + this->head = (this->head + 1) % RINGBUFLEN; + return true; + } +} + +void I2CRingBuffer::write(uint8_t v) { + ATOMIC() { + this->buf[this->tail] = v; + this->tail = (this->tail + 1) % RINGBUFLEN; + } +} diff --git a/nrf52/i2c_ring_buffer.h b/nrf52/i2c_ring_buffer.h new file mode 100644 index 0000000..a274798 --- /dev/null +++ b/nrf52/i2c_ring_buffer.h @@ -0,0 +1,21 @@ +#ifndef I2C_RING_BUFFER_H +#define I2C_RING_BUFFER_H + +#include + +#define RINGBUFLEN 256 + +class I2CRingBuffer { +public: + I2CRingBuffer(); + + bool read(uint8_t *); + void write(uint8_t); + +private: + volatile uint8_t buf[RINGBUFLEN]; + volatile uint8_t head; + volatile uint8_t tail; +}; + +#endif diff --git a/nrf52/log.h b/nrf52/log.h new file mode 100644 index 0000000..b78fec0 --- /dev/null +++ b/nrf52/log.h @@ -0,0 +1,17 @@ +#ifndef LOG_H +#define LOG_H + +#define DEBUG 0 +#if DEBUG +#define dbgPrint(...) Serial.print(__VA_ARGS__) +#define dbgPrintf(...) Serial.printf(__VA_ARGS__) +#define dbgPrintln(...) Serial.println(__VA_ARGS__) +#define dbgWrite(...) Serial.write(__VA_ARGS__) +#else +#define dbgPrint(...) +#define dbgPrintf(...) +#define dbgPrintln(...) +#define dbgWrite(...) +#endif + +#endif diff --git a/nrf52/nrf52.ino b/nrf52/nrf52.ino new file mode 100644 index 0000000..1b4ac3c --- /dev/null +++ b/nrf52/nrf52.ino @@ -0,0 +1,94 @@ +// -*- mode: c++ -*- +#include "i2c_message.h" +#include "i2c_ring_buffer.h" +#include "log.h" +#include "state_machine.h" + +#include +#include + +BLEDis bledis; +BLEHidAdafruit blehid; + +I2CRingBuffer rb; +StateMachine fsm(&blehid); + +void setup() { + pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, HIGH); + + pinMode(PIN_WIRE_SDA, INPUT_PULLUP); + pinMode(PIN_WIRE_SCL, INPUT_PULLUP); + + Serial.begin(115200); + Serial.println("usb2btle booting."); + + Wire.begin(BTLE_WIREADDR); + Wire.onReceive(wireDataReceived); + + Bluefruit.begin(); + Bluefruit.setTxPower(4); + Bluefruit.setName("usb2btle"); + + // Configure and Start Device Information Service + bledis.setManufacturer("Kublai Khansulting"); + bledis.setModel("devel-nrf52832-trinketm0"); + bledis.begin(); + + /* Start BLE HID + * Note: Apple requires BLE device must have min connection interval >= 20m + * ( The smaller the connection interval the faster we could send data). + * However for HID and MIDI device, Apple could accept min connection interval + * up to 11.25 ms. Therefore BLEHidAdafruit::begin() will try to set the min and max + * connection interval to 11.25 ms and 15 ms respectively for best performance. + */ + blehid.begin(); + blehid.setKeyboardLedCallback(setKeyboardLED); + + startAdv(); + + digitalWrite(LED_BUILTIN, LOW); +} + +void startAdv(void) +{ + Serial.println("Advertising HID."); + + Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE); + Bluefruit.Advertising.addTxPower(); + Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_KEYBOARD); + Bluefruit.Advertising.addService(blehid); + Bluefruit.Advertising.addName(); + Bluefruit.Advertising.restartOnDisconnect(true); + Bluefruit.Advertising.setInterval(32, 244); + Bluefruit.Advertising.setFastTimeout(30); + Bluefruit.Advertising.start(0); +} + +void loop() { + waitForEvent(); + + uint8_t v; + while (rb.read(&v)) { + dbgPrintf("got byte on rb: %02x\r\n", v); + fsm.byteReceived(v); + } +} + +void wireDataReceived(int numBytes) { + dbgPrintf("wireDataReceived: %u\r\n", numBytes); + for (int i = 0; i < numBytes; i++) { + rb.write(Wire.read()); + } +} + +void setKeyboardLED(uint16_t conn_handle, uint8_t led_bitmap) { + (void) conn_handle; + + // light up Red Led if any bits is set + if (led_bitmap) { + ledOn(LED_RED); + } else { + ledOff(LED_RED); + } +} diff --git a/nrf52/state_machine.cpp b/nrf52/state_machine.cpp new file mode 100644 index 0000000..15e38b9 --- /dev/null +++ b/nrf52/state_machine.cpp @@ -0,0 +1,79 @@ +#include "state_machine.h" + +#include "i2c_message.h" +#include "log.h" + +#include + +StateMachine::StateMachine(BLEHidAdafruit *blehid): currentState(WAIT_FOR_TYPE), blehid(blehid) {} + +void StateMachine::byteReceived(uint8_t inByte) { + dbgPrint("inByte="); + dbgPrintln(inByte); + + switch (this->currentState) { + case WAIT_FOR_TYPE: + switch (inByte) { + case KBD: + digitalWrite(LED_BUILTIN, HIGH); + this->msgType = KBD; + break; + + case DBG: + dbgPrint("T-M0: "); + this->msgType = DBG; + break; + + default: + this->msgType = INVALID; + Serial.printf("Invalid message type: %ud.\r\n", inByte); + } + + this->currentState = WAIT_FOR_LEN; + break; + + case WAIT_FOR_LEN: + dbgPrintf("msg len: %u\r\n", inByte); + this->msgLen = inByte; + this->msgCount = 0; + + if (this->msgLen == 0) { + this->currentState = WAIT_FOR_TYPE; + } else { + this->currentState = WAIT_FOR_DATA; + } + break; + + case WAIT_FOR_DATA: + dbgPrintf("data: %02x\r\n", inByte); + switch (this->msgType) { + case KBD: + this->message[this->msgCount++ % sizeof(this->message)] = inByte; + break; + + case DBG: + dbgPrint(inByte); + break; + } + + if (this->msgCount == this->msgLen) { + switch (this->msgType) { + case KBD: + dbgPrintln("sending kbd report"); + this->blehid->keyboardReport(this->message[0], &this->message[2]); + digitalWrite(LED_BUILTIN, LOW); + break; + + case DBG: + dbgPrintln(); + break; + } + this->currentState = WAIT_FOR_TYPE; + } + break; + + default: + Serial.printf("Invalid message state: %ud.\r\n", this->currentState); + break; + } +} diff --git a/nrf52/state_machine.h b/nrf52/state_machine.h new file mode 100644 index 0000000..d972926 --- /dev/null +++ b/nrf52/state_machine.h @@ -0,0 +1,28 @@ +#ifndef STATE_MACHINE_H +#define STATE_MACHINE_H + +#include "i2c_message.h" + +#include + +#include + +#define MAX_MSG_LEN 32 + +enum state_t {WAIT_FOR_TYPE, WAIT_FOR_LEN, WAIT_FOR_DATA}; + +class StateMachine { +public: + StateMachine(BLEHidAdafruit *); + void byteReceived(uint8_t); + +private: + state_t currentState; + uint8_t message[MAX_MSG_LEN]; + uint8_t msgLen, msgCount; + i2c_message_t msgType; + + BLEHidAdafruit *blehid; +}; + +#endif -- cgit v1.2.3