Simple program to enable me to write to a 128x64 OLED display over BLE
Dependencies: Adafruit_GFX BLE_API mbed nRF51822 SemVer
Diff: main.cpp
- Revision:
- 0:d89c10040630
- Child:
- 1:9e9c52d8270a
diff -r 000000000000 -r d89c10040630 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Mar 30 10:06:34 2015 +0000 @@ -0,0 +1,166 @@ +/** + * @file + * @date 30 March 2015 + * @author Richard Osterloh <richard.osterloh@gmail.com> + */ + +#include "mbed.h" +#include "BLEDevice.h" +#include "UARTService.h" + +#include "Adafruit_SSD1306.h" + +#define NEED_CONSOLE_OUTPUT 1 /* Set this if you need debug messages on the console; + * it will have an impact on code-size and power consumption. */ + +#if NEED_CONSOLE_OUTPUT +#define DEBUG(STR) { if (uartServicePtr) uartServicePtr->writeString(STR); } +#else +#define DEBUG(...) /* nothing */ +#endif /* #if NEED_CONSOLE_OUTPUT */ + +BLEDevice ble; +DigitalOut led1(LED1); +DigitalOut led2(LED2); +DigitalOut led3(LED3); +DigitalOut led4(LED4); + +InterruptIn btn1(BUTTON1); + +DigitalOut oled_gnd(p3); + +// an I2C sub-class that provides a constructed default +class I2CPreInit : public I2C +{ +public: + I2CPreInit(PinName sda, PinName scl) : I2C(sda, scl) + { + oled_gnd = 0; + frequency(400000); + start(); + }; +}; + +I2CPreInit gI2C(p5, p4); // SDA, SCL +Adafruit_SSD1306_I2c gOled(gI2C, p2, 0x78, 64, 128); // I2C, RST, ADDRESS, WIDTH, HEIGHT + +bool rxPayloadUpdated = false; +const static unsigned MAX_SIZEOF_RX_PAYLOAD = 20; +char rxPayload[MAX_SIZEOF_RX_PAYLOAD] = {0,}; + +UARTService *uartServicePtr; + +const char *deviceName = "BLE DISPLAY"; + +/** + * Callback to write to connected client and display + */ +void buttonCallback(void) +{ + if(btn1) { + gOled.clearDisplay(); + gOled.printf("%s", "BTN 0 released"); + gOled.display(); + uartServicePtr->writeString("Button 0 released\r\n"); + } else { + gOled.clearDisplay(); + gOled.printf("%s", "BTN 0 pressed"); + gOled.display(); + uartServicePtr->writeString("Button 0 pressed\r\n"); + } +} + +/** + * Callback when new client connects to device + * + * @param tHandle handle to this specific client + * @param ePeerAddrType the type of the connected clients address + * @param c6PeerAddr the address of the connected client + * @param params requested connection parameters + */ +void connectionCallback(Gap::Handle_t tHandle, Gap::addr_type_t ePeerAddrType, const Gap::address_t c6PeerAddr, const Gap::ConnectionParams_t *params) +{ + //DEBUG("CONNECT: Handle:%u, eType:%d, Add:%u\r\n", tHandle, ePeerAddrType, c6PeerAddr); + //DEBUG(" minInterval:%d, maxInterval:%d, latency:%d, timeout:%d\r\n", + // params->minConnectionInterval, params->maxConnectionInterval, params->slaveLatency, params->connectionSupervisionTimeout); + DEBUG("CONNECTED\r\n"); + led2 = 1; led4 = 0; +} + +/** + * Callback called when a client disconnects + * + * @param tHandle handle of the disconnected client + * @param eReason the reason they disconnected + */ +void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) +{ + DEBUG("Disconnected!\n\r"); + DEBUG("Restarting the advertising process\n\r"); + ble.startAdvertising(); + led2 = 0; led4 = 1; +} + +/** + * Callback called when a client writes to this device + * + * @param params all parameters related to this data + */ +void onDataWritten(const GattCharacteristicWriteCBParams *params) +{ + if ((uartServicePtr != NULL) && (params->charHandle == uartServicePtr->getTXCharacteristicHandle())) { + uint16_t bytesRead = params->len; + if (bytesRead < MAX_SIZEOF_RX_PAYLOAD) { + strncpy(rxPayload, (const char *)params->data, MAX_SIZEOF_RX_PAYLOAD - 1); + rxPayload[bytesRead] = '\0'; + rxPayloadUpdated = true; + ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), params->data, bytesRead); + } + } +} + +void periodicCallback(void) +{ + led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */ +} + +int main(void) +{ + led1 = 1; led2 = 1; led3 = 1; led4 = 1; + Ticker ticker; + ticker.attach(periodicCallback, 1); + btn1.fall(buttonCallback); + btn1.rise(buttonCallback); + + DEBUG("Initialising the nRF51822\n\r"); + ble.init(); + ble.onConnection(connectionCallback); + ble.onDisconnection(disconnectionCallback); + ble.onDataWritten(onDataWritten); + + /* setup advertising */ + ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); + ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); + ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (const uint8_t *)deviceName, strlen(deviceName)); + /*ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, + (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));*/ + + ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */ + ble.startAdvertising(); + + UARTService uartService(ble); + uartServicePtr = &uartService; + + while (true) { + if (rxPayloadUpdated) { + gOled.clearDisplay(); + gOled.printf("%s", rxPayload); + gOled.display(); + + rxPayloadUpdated = false; + } + + ble.waitForEvent(); + } +} +