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: Hexiwear HexiwearFinal HexiwearFinal1
Fork of Hexi_KW40Z by
Hexi_KW40Z.cpp
- Committer:
- Jashebes
- Date:
- 2018-04-30
- Revision:
- 13:c36aa84374e8
- Parent:
- 1:f6f9b24aea57
File content as of revision 13:c36aa84374e8:
/** 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;
/* initialize callbacks */
buttonUpCb = NULL;
buttonDownCb = NULL;
buttonLeftCb = NULL;
buttonRightCb = NULL;
buttonSlideCb = NULL;
alertCb = NULL;
passkeyCb = NULL;
notificationsCb = NULL;
/* intialization finalized, signal to start the threads */
mainThread.signal_set(START_THREAD);
rxThread.signal_set(START_THREAD);
}
KW40Z::~KW40Z(void)
{
}
void KW40Z::attach_buttonUp(button_t btnFct)
{
buttonUpCb = btnFct;
}
void KW40Z::attach_buttonDown(button_t btnFct)
{
buttonDownCb = btnFct;
}
void KW40Z::attach_buttonLeft(button_t btnFct)
{
buttonLeftCb = btnFct;
}
void KW40Z::attach_buttonRight(button_t btnFct)
{
buttonRightCb = btnFct;
}
void KW40Z::attach_buttonSlide(button_t btnFct)
{
buttonSlideCb = btnFct;
}
void KW40Z::attach_alert(alert_t alertFct)
{
alertCb = alertFct;
}
void KW40Z::attach_passkey(passkey_t passkeyFct)
{
passkeyCb = passkeyFct;
}
void KW40Z::attach_notifications(notifications_t notFct)
{
notificationsCb = notFct;
}
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:
if(buttonUpCb != NULL) buttonUpCb();
break;
case packetType_pressDown:
if(buttonDownCb != NULL) buttonDownCb();
break;
case packetType_pressLeft:
if(buttonLeftCb != NULL) buttonLeftCb();
break;
case packetType_pressRight:
if(buttonRightCb != NULL) buttonRightCb();
break;
case packetType_slide:
if(buttonSlideCb != NULL) buttonSlideCb();
break;
/* Alert Service */
case packetType_alertIn:
if(alertCb != NULL) alertCb(&rxPacket->data[0], rxPacket->length);
break;
/* Passkey for pairing received */
case packetType_passDisplay:
if(passkeyCb != NULL) passkeyCb(&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(notificationsCb != NULL) notificationsCb(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;
}
}
