Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: Hexi_Buttons_Example Hexi_Click_Relay-v2_Example Hexi_Click_Relay-v3_Example Hexi_Catch-the-dot_Game ... more
Revision 0:c2d52562f36b, committed 2016-09-19
- Comitter:
- cotigac
- Date:
- Mon Sep 19 02:46:28 2016 +0000
- Child:
- 1:f6f9b24aea57
- Commit message:
- Initial version of KW40Z library for Hexiwear
Changed in this revision
| Hexi_KW40Z.cpp | Show annotated file Show diff for this revision Revisions of this file |
| Hexi_KW40Z.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Hexi_KW40Z.cpp Mon Sep 19 02:46:28 2016 +0000
@@ -0,0 +1,395 @@
+/** BLE KW40Z Driver for Hexiwear
+ * This file contains BLE and Touch Buttons driver functionality for Hexiwear
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * Neither the name of NXP, nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * visit: http://www.mikroe.com and http://www.nxp.com
+ *
+ * get support at: http://www.mikroe.com/forum and https://community.nxp.com
+ *
+ * Project HEXIWEAR, 2015
+ */
+
+#include "Hexi_KW40Z.h"
+
+#if defined (LIB_DEBUG)
+RawSerial pc(USBTX, USBRX); // tx, rx
+#endif
+
+KW40Z::KW40Z(PinName txPin,PinName rxPin) : device(txPin, rxPin), mainThread(&KW40Z::mainStarter, this, osPriorityNormal,1024), rxThread(&KW40Z::rxStarter, this, osPriorityNormal,1024)
+{
+#if defined (LIB_DEBUG)
+ pc.baud(115200);
+ pc.printf("Initializing\r\n");
+#endif
+
+ device.baud(230400);
+ device.format(8, Serial::None, 2);
+
+ rxBuff = (uint8_t*)&hostInterface_rxPacket;
+ kw40z_Cbs = NULL;
+ //memset(&hexiwear_kw40version,0,sizeof(hexiwear_version_t));
+
+ /* intialization finalized, signal to start the threads */
+ mainThread.signal_set(START_THREAD);
+ rxThread.signal_set(START_THREAD);
+}
+
+KW40Z::~KW40Z(void)
+{
+}
+
+void KW40Z::attach(kw40z_callbacks_t * callbacks)
+{
+ kw40z_Cbs = callbacks;
+}
+
+void KW40Z::rxStarter(void const *p) {
+ KW40Z *instance = (KW40Z*)p;
+ instance->rxTask();
+}
+
+void KW40Z::mainStarter(void const *p) {
+ KW40Z *instance = (KW40Z*)p;
+ instance->mainTask();
+}
+
+void KW40Z::GetVersion()
+{
+ hostInterface_packet_t txPacket = {0};
+
+ txPacket.start1 = gHostInterface_startByte1,
+ txPacket.start2 = gHostInterface_startByte2,
+ txPacket.type = packetType_buildVersion,
+ txPacket.length = 3,
+ txPacket.data[0] = HEXIWEAR_VERSION_MAJOR;
+ txPacket.data[1] = HEXIWEAR_VERSION_MINOR;
+ txPacket.data[2] = HEXIWEAR_VERSION_PATCH;
+ txPacket.data[3] = gHostInterface_trailerByte;
+
+ SendPacket(&txPacket, false);
+}
+
+void KW40Z::SendPacket(hostInterface_packet_t * txPacket, bool confirmRequested)
+{
+ uint8_t retries = 0;
+ confirmReceived = false;
+
+ do
+ {
+ char * txBuff = (char *)txPacket;
+ uint8_t length = txPacket->length + gHostInterface_headerSize + 1;
+
+ if(confirmRequested == true)
+ {
+ txPacket->start2 |= 0x01;
+ }
+
+ for(uint8_t i = 0; i < length; i++)
+ {
+ device.putc(*txBuff);
+ txBuff++;
+ }
+
+#if defined (LIB_DEBUG)
+ DebugPrintTxPacket(txPacket);
+#endif
+
+ retries++;
+
+ #if defined (gHostInterface_RxConfirmationEnable)
+ if((confirmRequested == true) && (confirmReceived == false))
+ {
+ Thread::wait(gHostInterface_retransmitTimeout);
+ }
+ #endif
+ }
+ while((confirmRequested == true) &&
+ (confirmReceived == false) &&
+ (retries < gHostInterface_retransmitCount));
+}
+
+void KW40Z::mainTask(void)
+{
+ mainThread.signal_wait(START_THREAD);
+
+#if defined (LIB_DEBUG)
+ pc.printf("MainTask Stared\r\n");
+#endif
+
+ while(1)
+ {
+ osEvent evt = queue.get();
+ if (evt.status == osEventMessage)
+ {
+ hostInterface_packet_t *rxPacket = (hostInterface_packet_t*)evt.value.p;
+ ProcessReceivedPacket(rxPacket);
+ mpool.free(rxPacket);
+ }
+ }
+}
+
+void KW40Z::rxTask(void)
+{
+ rxThread.signal_wait(START_THREAD);
+
+#if defined (LIB_DEBUG)
+ pc.printf("RxTask Stared\r\n");
+#endif
+
+ while(1)
+ {
+ if(device.readable())
+ {
+ *rxBuff++ = device.getc();
+ ProcessBuffer();
+
+ /* check for buffer overflow */
+ if(rxBuff >= ((uint8_t*)&hostInterface_rxPacket + sizeof(hostInterface_rxPacket)))
+ {
+ rxBuff = (uint8_t*)&hostInterface_rxPacket;
+ }
+ }
+ }
+}
+
+#if defined (LIB_DEBUG)
+void KW40Z::DebugPrintTxPacket(hostInterface_packet_t * txPacket)
+{
+ char * txBuff = (char *)txPacket;
+ uint8_t length = txPacket->length + gHostInterface_headerSize + 1;
+
+ pc.printf("Tx: ");
+ for(uint8_t i = 0; i < length; i++)
+ {
+ pc.printf("%02X ",*txBuff);
+ txBuff++;
+ }
+ pc.printf("\r\n");
+}
+
+void KW40Z::DebugPrintRxPacket()
+{
+ pc.printf("RX: ");
+ for(uint8_t * i = (uint8_t*)&hostInterface_rxPacket; i<rxBuff; i++)
+ {
+ pc.printf("%02X ",*i);
+ }
+ pc.printf("\r\n");
+}
+#endif
+
+void KW40Z::ProcessBuffer()
+{
+ /* check if header has been received */
+ if(rxBuff > ((uint8_t*)&hostInterface_rxPacket + gHostInterface_headerSize))
+ {
+ /* check packet header */
+ if((gHostInterface_startByte1 != hostInterface_rxPacket.start1)||
+ (gHostInterface_startByte2 != (hostInterface_rxPacket.start2 & 0xFE))||
+ (hostInterface_rxPacket.length > gHostInterface_dataSize))
+ {
+#if defined (LIB_DEBUG)
+ DebugPrintRxPacket();
+ pc.printf("check header failed\r\n");
+#endif
+
+ SearchStartByte();
+ }
+ else
+ {
+ /* check data length */
+ if(rxBuff > ((uint8_t*)&hostInterface_rxPacket + gHostInterface_headerSize + hostInterface_rxPacket.length))
+ {
+ /* check trailer byte */
+ if(gHostInterface_trailerByte != hostInterface_rxPacket.data[hostInterface_rxPacket.length])
+ {
+#if defined (LIB_DEBUG)
+ DebugPrintRxPacket();
+ pc.printf("trailer byte failed\r\n");
+#endif
+
+ SearchStartByte();
+ }
+ else
+ {
+
+ #if defined (gHostInterface_RxConfirmationEnable)
+ if(hostInterface_rxPacket.type == packetType_OK)
+ {
+ confirmReceived = true;
+ }
+ #endif
+
+ /* send message to main task */
+ hostInterface_packet_t *rxPacket = mpool.alloc();
+ memcpy(rxPacket, &hostInterface_rxPacket, sizeof(hostInterface_packet_t));
+ queue.put(rxPacket);
+
+#if defined (LIB_DEBUG)
+ DebugPrintRxPacket();
+#endif
+ /* reset buffer position */
+ rxBuff = (uint8_t*)&hostInterface_rxPacket;
+ }
+ }
+ }
+ }
+}
+
+void KW40Z::SearchStartByte()
+{
+ bool found = false;
+ uint8_t * rdIdx = (uint8_t*)&hostInterface_rxPacket + 1;
+
+ while(rdIdx < rxBuff)
+ {
+ if(*rdIdx == gHostInterface_startByte1)
+ {
+ uint32_t len = rxBuff - rdIdx;
+
+ memcpy(&hostInterface_rxPacket,rdIdx,len);
+ rxBuff -= len;
+ found = true;
+
+#if defined (LIB_DEBUG)
+ pc.printf("moving ");
+#endif
+ break;
+ }
+ rdIdx++;
+ }
+
+ if(!found)
+ {
+ /* reset buffer position */
+ rxBuff = (uint8_t*)&hostInterface_rxPacket;
+ }
+
+#if defined (LIB_DEBUG)
+ pc.printf("search done\r\n");
+ DebugPrintRxPacket();
+#endif
+}
+
+void KW40Z::SendPacketOK()
+{
+ hostInterface_packet_t txPacket = {0};
+
+ txPacket.start1 = gHostInterface_startByte1,
+ txPacket.start2 = gHostInterface_startByte2,
+ txPacket.type = packetType_OK,
+ txPacket.length = 0,
+ txPacket.data[0] = gHostInterface_trailerByte;
+
+ SendPacket(&txPacket, false);
+}
+
+void KW40Z::ConfirmPacketOK()
+{
+}
+
+void KW40Z::ProcessReceivedPacket(hostInterface_packet_t * rxPacket)
+{
+#if defined (LIB_DEBUG)
+ pc.printf("packet found %d\r\n", rxPacket->type);
+#endif
+
+#ifdef gHostInterface_TxConfirmationEnable
+ // acknowledge the packet reception
+ if ( 1 == ( rxPacket->start2 & 0x01 ) )
+ {
+ SendPacketOK();
+ }
+#endif
+
+ switch(rxPacket->type)
+ {
+ /* button presses */
+ case packetType_pressUp:
+ case packetType_pressDown:
+ case packetType_pressLeft:
+ case packetType_pressRight:
+ case packetType_slide:
+ if((kw40z_Cbs != NULL) && (kw40z_Cbs->buttons != NULL))
+ {
+ kw40z_Cbs->buttons((hexi_buttons_t)(rxPacket->type));
+ }
+ break;
+
+ /* Alert Service */
+ case packetType_alertIn:
+ if((kw40z_Cbs != NULL) && (kw40z_Cbs->alert != NULL))
+ {
+ kw40z_Cbs->alert(&rxPacket->data[0], rxPacket->length);
+ }
+ break;
+
+ /* Passkey for pairing received */
+ case packetType_passDisplay:
+ if((kw40z_Cbs != NULL) && (kw40z_Cbs->passkey != NULL))
+ {
+ kw40z_Cbs->passkey(&rxPacket->data[0]);
+ }
+ break;
+
+ /* OTAP messages */
+ case packetType_otapCompleted:
+ case packetType_otapFailed:
+ break;
+
+ /* TSI Status */
+ case packetType_buttonsGroupSendActive:
+ break;
+
+ /* Advertisement Mode Info */
+ case packetType_advModeSend:
+ break;
+
+ /* Link State */
+ case packetType_linkStateSend:
+ break;
+
+ /* ANCS Service Notification Received */
+ case packetType_notification:
+ if((kw40z_Cbs != NULL) && (kw40z_Cbs->notifications != NULL))
+ {
+ kw40z_Cbs->notifications(rxPacket->data[0],rxPacket->data[1]);
+ }
+ break;
+
+ /* Build version */
+ case packetType_buildVersion:
+ break;
+
+ case packetType_OK:
+ /* do nothing, the flag is set in the RxTask */
+ break;
+
+ default:
+ break;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Hexi_KW40Z.h Mon Sep 19 02:46:28 2016 +0000
@@ -0,0 +1,225 @@
+/** BLE KW40Z Driver for Hexiwear
+ * This file contains BLE and Touch Buttons driver functionality for Hexiwear
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * Neither the name of NXP, nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * visit: http://www.mikroe.com and http://www.nxp.com
+ *
+ * get support at: http://www.mikroe.com/forum and https://community.nxp.com
+ *
+ * Project HEXIWEAR, 2015
+ */
+
+#ifndef HG_HEXI_KW40Z
+#define HG_HEXI_KW40Z
+
+#include "mbed.h"
+#include "rtos.h"
+
+//#define LIB_DEBUG 1
+
+#define START_THREAD 1
+
+#define gHostInterface_startByte1 0x55
+#define gHostInterface_startByte2 0xAA
+#define gHostInterface_trailerByte 0x45
+
+#define gHostInterface_dataSize 23
+#define gHostInterface_headerSize 4
+
+#define gHostInterface_retransmitCount 3
+#define gHostInterface_retransmitTimeout 100
+
+#define gHostInterface_TxConfirmationEnable 1 // send confirmation when receive packet
+#define gHostInterface_RxConfirmationEnable 1 // wait on confirmation from remote side (do retransmit)
+
+/** HEXIWEAR firmware version */
+#define HEXIWEAR_VERSION_PATCH ( 2 )
+#define HEXIWEAR_VERSION_MINOR ( 0 )
+#define HEXIWEAR_VERSION_MAJOR ( 1 )
+
+/** packet types */
+typedef enum
+{
+ packetType_pressUp = 0, /**< touch press up */
+ packetType_pressDown = 1, /**< touch press down */
+ packetType_pressLeft = 2, /**< touch press left */
+ packetType_pressRight = 3, /**< touch press right */
+ packetType_slide = 4, /**< touch slide */
+
+ packetType_batteryLevel = 5, /**< battery Service */
+
+ packetType_accel = 6, /**< motion service */
+ packetType_ambiLight = 7, /**< weather service */
+ packetType_pressure = 8, /**< weather service */
+
+
+ packetType_gyro = 9, /**< motion service */
+ packetType_temperature = 10, /**< weather service */
+ packetType_humidity = 11, /**< weather service */
+ packetType_magnet = 12, /**< motion service */
+
+ packetType_heartRate = 13, /**< health service */
+ packetType_steps = 14, /**< health service */
+ packetType_calories = 15, /**< health service */
+
+ /* Alert Service */
+ packetType_alertIn = 16, /**< incoming alerts */
+ packetType_alertOut = 17, /**< outcoming alerts */
+
+ packetType_passDisplay = 18, /**< key display type */
+
+ /* OTAP procedure types */
+ packetType_otapKW40Started = 19,
+ packetType_otapMK64Started = 20,
+ packetType_otapCompleted = 21,
+ packetType_otapFailed = 22,
+
+ /* active buttons types */
+ packetType_buttonsGroupToggleActive = 23,
+ packetType_buttonsGroupGetActive = 24,
+ packetType_buttonsGroupSendActive = 25,
+
+ /* Turn off/on bluetooth advertising */
+ packetType_advModeGet = 26,
+ packetType_advModeSend = 27,
+ packetType_advModeToggle = 28,
+
+ packetType_appMode = 29, /**< app mode service */
+
+ /* Link State */
+ packetType_linkStateGet = 30, /**< connected */
+ packetType_linkStateSend = 31, /**< disconnected */
+
+ packetType_notification = 32, /**< notifications */
+
+ packetType_buildVersion = 33, /**< build version */
+
+ packetType_sleepON = 34, /**< sleep ON */
+ packetType_sleepOFF = 35, /**< sleep OFF */
+
+ packetType_OK = 255 /**< OK packet */
+} hostInterface_packetType_t;
+
+/** data-packet structure */
+typedef struct
+{
+ /* NOTE: Size of struct must be multiplier of 4! */
+ uint8_t start1;
+ uint8_t start2;
+ hostInterface_packetType_t type;
+ uint8_t length;
+ uint8_t data[gHostInterface_dataSize + 1];
+} hostInterface_packet_t;
+
+/** incoming alert types */
+typedef enum
+{
+ alertIn_type_notification = 1,
+ alertIn_type_settings = 2,
+ alertIn_type_timeUpdate = 3,
+} hostInterface_alertIn_type_t;
+
+typedef enum
+{
+ pressUp = 0, /**< touch press up */
+ pressDown = 1, /**< touch press down */
+ pressLeft = 2, /**< touch press left */
+ pressRight = 3, /**< touch press right */
+ slide = 4, /**< touch slide */
+} hexi_buttons_t;
+
+typedef struct
+{
+ void (*buttons)(hexi_buttons_t button);
+ void (*alert)(uint8_t *data, uint8_t length);
+ void (*passkey)(uint8_t *data);
+ void (*notifications)(uint8_t eventId, uint8_t categoryId);
+} kw40z_callbacks_t;
+
+typedef struct name
+{
+ uint8_t ver_patchNumber;
+ uint8_t ver_minorNumber;
+ uint8_t ver_majorNumber;
+
+} hexiwear_version_t;
+
+class KW40Z{
+
+public:
+
+ /**
+ * Create a Hexiwear BLE KW40Z Driver connected to the UART pins
+ *
+ * @param txPin UART TX pin
+ * @param rxPin UART RX pin
+ */
+ KW40Z(PinName txPin,PinName rxPin);
+
+ /**
+ * Destroy the Hexiwear instance
+ */
+ ~KW40Z();
+
+ void attach(kw40z_callbacks_t * callbacks);
+ void GetVersion();
+
+private:
+ RawSerial device;
+ Thread mainThread;
+ Thread rxThread;
+
+ hostInterface_packet_t hostInterface_rxPacket;
+ hostInterface_packet_t hostInterface_txPacket;
+
+ kw40z_callbacks_t * kw40z_Cbs;
+ uint8_t * rxBuff;
+ bool confirmReceived;
+
+ MemoryPool<hostInterface_packet_t, 16> mpool;
+ Queue<hostInterface_packet_t, 16> queue;
+
+ void mainTask(void);
+ void rxTask(void);
+
+ void ProcessBuffer();
+ void ProcessReceivedPacket(hostInterface_packet_t * rxPacket);
+ void SendPacket(hostInterface_packet_t * txPacket, bool confirmRequested);
+ void SearchStartByte();
+ void SendPacketOK();
+ void ConfirmPacketOK();
+
+#if defined (LIB_DEBUG)
+ void DebugPrintRxPacket();
+ void DebugPrintTxPacket(hostInterface_packet_t * txPacket);
+#endif
+
+ static void rxStarter(void const *p);
+ static void mainStarter(void const *p);
+};
+
+#endif
\ No newline at end of file