Simple program to enable me to write to a 128x64 OLED display over BLE

Dependencies:   Adafruit_GFX BLE_API mbed nRF51822 SemVer

Committer:
rosterloh84
Date:
Mon Mar 30 10:06:34 2015 +0000
Revision:
0:d89c10040630
Child:
1:9e9c52d8270a
First working version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rosterloh84 0:d89c10040630 1 /**
rosterloh84 0:d89c10040630 2 * @file
rosterloh84 0:d89c10040630 3 * @date 30 March 2015
rosterloh84 0:d89c10040630 4 * @author Richard Osterloh <richard.osterloh@gmail.com>
rosterloh84 0:d89c10040630 5 */
rosterloh84 0:d89c10040630 6
rosterloh84 0:d89c10040630 7 #include "mbed.h"
rosterloh84 0:d89c10040630 8 #include "BLEDevice.h"
rosterloh84 0:d89c10040630 9 #include "UARTService.h"
rosterloh84 0:d89c10040630 10
rosterloh84 0:d89c10040630 11 #include "Adafruit_SSD1306.h"
rosterloh84 0:d89c10040630 12
rosterloh84 0:d89c10040630 13 #define NEED_CONSOLE_OUTPUT 1 /* Set this if you need debug messages on the console;
rosterloh84 0:d89c10040630 14 * it will have an impact on code-size and power consumption. */
rosterloh84 0:d89c10040630 15
rosterloh84 0:d89c10040630 16 #if NEED_CONSOLE_OUTPUT
rosterloh84 0:d89c10040630 17 #define DEBUG(STR) { if (uartServicePtr) uartServicePtr->writeString(STR); }
rosterloh84 0:d89c10040630 18 #else
rosterloh84 0:d89c10040630 19 #define DEBUG(...) /* nothing */
rosterloh84 0:d89c10040630 20 #endif /* #if NEED_CONSOLE_OUTPUT */
rosterloh84 0:d89c10040630 21
rosterloh84 0:d89c10040630 22 BLEDevice ble;
rosterloh84 0:d89c10040630 23 DigitalOut led1(LED1);
rosterloh84 0:d89c10040630 24 DigitalOut led2(LED2);
rosterloh84 0:d89c10040630 25 DigitalOut led3(LED3);
rosterloh84 0:d89c10040630 26 DigitalOut led4(LED4);
rosterloh84 0:d89c10040630 27
rosterloh84 0:d89c10040630 28 InterruptIn btn1(BUTTON1);
rosterloh84 0:d89c10040630 29
rosterloh84 0:d89c10040630 30 DigitalOut oled_gnd(p3);
rosterloh84 0:d89c10040630 31
rosterloh84 0:d89c10040630 32 // an I2C sub-class that provides a constructed default
rosterloh84 0:d89c10040630 33 class I2CPreInit : public I2C
rosterloh84 0:d89c10040630 34 {
rosterloh84 0:d89c10040630 35 public:
rosterloh84 0:d89c10040630 36 I2CPreInit(PinName sda, PinName scl) : I2C(sda, scl)
rosterloh84 0:d89c10040630 37 {
rosterloh84 0:d89c10040630 38 oled_gnd = 0;
rosterloh84 0:d89c10040630 39 frequency(400000);
rosterloh84 0:d89c10040630 40 start();
rosterloh84 0:d89c10040630 41 };
rosterloh84 0:d89c10040630 42 };
rosterloh84 0:d89c10040630 43
rosterloh84 0:d89c10040630 44 I2CPreInit gI2C(p5, p4); // SDA, SCL
rosterloh84 0:d89c10040630 45 Adafruit_SSD1306_I2c gOled(gI2C, p2, 0x78, 64, 128); // I2C, RST, ADDRESS, WIDTH, HEIGHT
rosterloh84 0:d89c10040630 46
rosterloh84 0:d89c10040630 47 bool rxPayloadUpdated = false;
rosterloh84 0:d89c10040630 48 const static unsigned MAX_SIZEOF_RX_PAYLOAD = 20;
rosterloh84 0:d89c10040630 49 char rxPayload[MAX_SIZEOF_RX_PAYLOAD] = {0,};
rosterloh84 0:d89c10040630 50
rosterloh84 0:d89c10040630 51 UARTService *uartServicePtr;
rosterloh84 0:d89c10040630 52
rosterloh84 0:d89c10040630 53 const char *deviceName = "BLE DISPLAY";
rosterloh84 0:d89c10040630 54
rosterloh84 0:d89c10040630 55 /**
rosterloh84 0:d89c10040630 56 * Callback to write to connected client and display
rosterloh84 0:d89c10040630 57 */
rosterloh84 0:d89c10040630 58 void buttonCallback(void)
rosterloh84 0:d89c10040630 59 {
rosterloh84 0:d89c10040630 60 if(btn1) {
rosterloh84 0:d89c10040630 61 gOled.clearDisplay();
rosterloh84 0:d89c10040630 62 gOled.printf("%s", "BTN 0 released");
rosterloh84 0:d89c10040630 63 gOled.display();
rosterloh84 0:d89c10040630 64 uartServicePtr->writeString("Button 0 released\r\n");
rosterloh84 0:d89c10040630 65 } else {
rosterloh84 0:d89c10040630 66 gOled.clearDisplay();
rosterloh84 0:d89c10040630 67 gOled.printf("%s", "BTN 0 pressed");
rosterloh84 0:d89c10040630 68 gOled.display();
rosterloh84 0:d89c10040630 69 uartServicePtr->writeString("Button 0 pressed\r\n");
rosterloh84 0:d89c10040630 70 }
rosterloh84 0:d89c10040630 71 }
rosterloh84 0:d89c10040630 72
rosterloh84 0:d89c10040630 73 /**
rosterloh84 0:d89c10040630 74 * Callback when new client connects to device
rosterloh84 0:d89c10040630 75 *
rosterloh84 0:d89c10040630 76 * @param tHandle handle to this specific client
rosterloh84 0:d89c10040630 77 * @param ePeerAddrType the type of the connected clients address
rosterloh84 0:d89c10040630 78 * @param c6PeerAddr the address of the connected client
rosterloh84 0:d89c10040630 79 * @param params requested connection parameters
rosterloh84 0:d89c10040630 80 */
rosterloh84 0:d89c10040630 81 void connectionCallback(Gap::Handle_t tHandle, Gap::addr_type_t ePeerAddrType, const Gap::address_t c6PeerAddr, const Gap::ConnectionParams_t *params)
rosterloh84 0:d89c10040630 82 {
rosterloh84 0:d89c10040630 83 //DEBUG("CONNECT: Handle:%u, eType:%d, Add:%u\r\n", tHandle, ePeerAddrType, c6PeerAddr);
rosterloh84 0:d89c10040630 84 //DEBUG(" minInterval:%d, maxInterval:%d, latency:%d, timeout:%d\r\n",
rosterloh84 0:d89c10040630 85 // params->minConnectionInterval, params->maxConnectionInterval, params->slaveLatency, params->connectionSupervisionTimeout);
rosterloh84 0:d89c10040630 86 DEBUG("CONNECTED\r\n");
rosterloh84 0:d89c10040630 87 led2 = 1; led4 = 0;
rosterloh84 0:d89c10040630 88 }
rosterloh84 0:d89c10040630 89
rosterloh84 0:d89c10040630 90 /**
rosterloh84 0:d89c10040630 91 * Callback called when a client disconnects
rosterloh84 0:d89c10040630 92 *
rosterloh84 0:d89c10040630 93 * @param tHandle handle of the disconnected client
rosterloh84 0:d89c10040630 94 * @param eReason the reason they disconnected
rosterloh84 0:d89c10040630 95 */
rosterloh84 0:d89c10040630 96 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
rosterloh84 0:d89c10040630 97 {
rosterloh84 0:d89c10040630 98 DEBUG("Disconnected!\n\r");
rosterloh84 0:d89c10040630 99 DEBUG("Restarting the advertising process\n\r");
rosterloh84 0:d89c10040630 100 ble.startAdvertising();
rosterloh84 0:d89c10040630 101 led2 = 0; led4 = 1;
rosterloh84 0:d89c10040630 102 }
rosterloh84 0:d89c10040630 103
rosterloh84 0:d89c10040630 104 /**
rosterloh84 0:d89c10040630 105 * Callback called when a client writes to this device
rosterloh84 0:d89c10040630 106 *
rosterloh84 0:d89c10040630 107 * @param params all parameters related to this data
rosterloh84 0:d89c10040630 108 */
rosterloh84 0:d89c10040630 109 void onDataWritten(const GattCharacteristicWriteCBParams *params)
rosterloh84 0:d89c10040630 110 {
rosterloh84 0:d89c10040630 111 if ((uartServicePtr != NULL) && (params->charHandle == uartServicePtr->getTXCharacteristicHandle())) {
rosterloh84 0:d89c10040630 112 uint16_t bytesRead = params->len;
rosterloh84 0:d89c10040630 113 if (bytesRead < MAX_SIZEOF_RX_PAYLOAD) {
rosterloh84 0:d89c10040630 114 strncpy(rxPayload, (const char *)params->data, MAX_SIZEOF_RX_PAYLOAD - 1);
rosterloh84 0:d89c10040630 115 rxPayload[bytesRead] = '\0';
rosterloh84 0:d89c10040630 116 rxPayloadUpdated = true;
rosterloh84 0:d89c10040630 117 ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), params->data, bytesRead);
rosterloh84 0:d89c10040630 118 }
rosterloh84 0:d89c10040630 119 }
rosterloh84 0:d89c10040630 120 }
rosterloh84 0:d89c10040630 121
rosterloh84 0:d89c10040630 122 void periodicCallback(void)
rosterloh84 0:d89c10040630 123 {
rosterloh84 0:d89c10040630 124 led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
rosterloh84 0:d89c10040630 125 }
rosterloh84 0:d89c10040630 126
rosterloh84 0:d89c10040630 127 int main(void)
rosterloh84 0:d89c10040630 128 {
rosterloh84 0:d89c10040630 129 led1 = 1; led2 = 1; led3 = 1; led4 = 1;
rosterloh84 0:d89c10040630 130 Ticker ticker;
rosterloh84 0:d89c10040630 131 ticker.attach(periodicCallback, 1);
rosterloh84 0:d89c10040630 132 btn1.fall(buttonCallback);
rosterloh84 0:d89c10040630 133 btn1.rise(buttonCallback);
rosterloh84 0:d89c10040630 134
rosterloh84 0:d89c10040630 135 DEBUG("Initialising the nRF51822\n\r");
rosterloh84 0:d89c10040630 136 ble.init();
rosterloh84 0:d89c10040630 137 ble.onConnection(connectionCallback);
rosterloh84 0:d89c10040630 138 ble.onDisconnection(disconnectionCallback);
rosterloh84 0:d89c10040630 139 ble.onDataWritten(onDataWritten);
rosterloh84 0:d89c10040630 140
rosterloh84 0:d89c10040630 141 /* setup advertising */
rosterloh84 0:d89c10040630 142 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
rosterloh84 0:d89c10040630 143 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
rosterloh84 0:d89c10040630 144 ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (const uint8_t *)deviceName, strlen(deviceName));
rosterloh84 0:d89c10040630 145 /*ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
rosterloh84 0:d89c10040630 146 (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));*/
rosterloh84 0:d89c10040630 147
rosterloh84 0:d89c10040630 148 ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
rosterloh84 0:d89c10040630 149 ble.startAdvertising();
rosterloh84 0:d89c10040630 150
rosterloh84 0:d89c10040630 151 UARTService uartService(ble);
rosterloh84 0:d89c10040630 152 uartServicePtr = &uartService;
rosterloh84 0:d89c10040630 153
rosterloh84 0:d89c10040630 154 while (true) {
rosterloh84 0:d89c10040630 155 if (rxPayloadUpdated) {
rosterloh84 0:d89c10040630 156 gOled.clearDisplay();
rosterloh84 0:d89c10040630 157 gOled.printf("%s", rxPayload);
rosterloh84 0:d89c10040630 158 gOled.display();
rosterloh84 0:d89c10040630 159
rosterloh84 0:d89c10040630 160 rxPayloadUpdated = false;
rosterloh84 0:d89c10040630 161 }
rosterloh84 0:d89c10040630 162
rosterloh84 0:d89c10040630 163 ble.waitForEvent();
rosterloh84 0:d89c10040630 164 }
rosterloh84 0:d89c10040630 165 }
rosterloh84 0:d89c10040630 166