Jacob Shebesh / Hexi_KW40Z

Dependents:   Hexiwear HexiwearFinal HexiwearFinal1

Fork of Hexi_KW40Z by Hexiwear

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Hexi_KW40Z.cpp Source File

Hexi_KW40Z.cpp

00001 /** BLE KW40Z Driver for Hexiwear
00002  *  This file contains BLE and Touch Buttons driver functionality for Hexiwear
00003  *
00004  * Redistribution and use in source and binary forms, with or without modification,
00005  * are permitted provided that the following conditions are met:
00006  *
00007  * Redistributions of source code must retain the above copyright notice, this list
00008  * of conditions and the following disclaimer.
00009  *
00010  * Redistributions in binary form must reproduce the above copyright notice, this
00011  * list of conditions and the following disclaimer in the documentation and/or
00012  * other materials provided with the distribution.
00013  *
00014  * Neither the name of NXP, nor the names of its
00015  * contributors may be used to endorse or promote products derived from this
00016  * software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00019  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00020  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00021  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00022  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00023  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00024  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00025  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00026  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00027  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  *
00029  * visit: http://www.mikroe.com and http://www.nxp.com
00030  *
00031  * get support at: http://www.mikroe.com/forum and https://community.nxp.com
00032  *
00033  * Project HEXIWEAR, 2015
00034  */
00035  
00036 #include "Hexi_KW40Z.h"
00037 
00038 #if defined (LIB_DEBUG) 
00039 RawSerial pc(USBTX, USBRX); // tx, rx
00040 #endif
00041  
00042 KW40Z::KW40Z(PinName txPin,PinName rxPin) : device(txPin, rxPin), mainThread(&KW40Z::mainStarter, this, osPriorityNormal,1024), rxThread(&KW40Z::rxStarter, this, osPriorityNormal,1024)
00043 {
00044 #if defined (LIB_DEBUG) 
00045     pc.baud(115200);
00046     pc.printf("Initializing\r\n");
00047 #endif
00048 
00049     device.baud(230400);
00050     device.format(8, Serial::None, 2);
00051     
00052     rxBuff = (uint8_t*)&hostInterface_rxPacket;
00053     
00054     /* initialize callbacks */
00055     buttonUpCb = NULL;
00056     buttonDownCb = NULL;
00057     buttonLeftCb = NULL;
00058     buttonRightCb = NULL;
00059     buttonSlideCb = NULL;
00060     alertCb = NULL;
00061     passkeyCb = NULL;
00062     notificationsCb = NULL;
00063     
00064     /* intialization finalized, signal to start the threads */
00065     mainThread.signal_set(START_THREAD);
00066     rxThread.signal_set(START_THREAD);
00067 }
00068 
00069 KW40Z::~KW40Z(void)
00070 {
00071 }
00072 
00073 void KW40Z::attach_buttonUp(button_t btnFct)
00074 {
00075     buttonUpCb = btnFct;
00076 }
00077 void KW40Z::attach_buttonDown(button_t btnFct)
00078 {
00079     buttonDownCb = btnFct;
00080 }
00081 
00082 void KW40Z::attach_buttonLeft(button_t btnFct)
00083 {
00084     buttonLeftCb = btnFct;
00085 }
00086 
00087 void KW40Z::attach_buttonRight(button_t btnFct)
00088 {
00089     buttonRightCb = btnFct;
00090 }
00091 
00092 void KW40Z::attach_buttonSlide(button_t btnFct)
00093 {
00094     buttonSlideCb = btnFct;
00095 }
00096 
00097 void KW40Z::attach_alert(alert_t alertFct)
00098 {
00099     alertCb = alertFct;
00100 }
00101 
00102 void KW40Z::attach_passkey(passkey_t passkeyFct)
00103 {
00104     passkeyCb = passkeyFct;
00105 }
00106 
00107 void KW40Z::attach_notifications(notifications_t notFct)
00108 {
00109     notificationsCb = notFct;
00110 }
00111 
00112 void KW40Z::rxStarter(void const *p) {
00113   KW40Z *instance = (KW40Z*)p;
00114   instance->rxTask();
00115 }
00116 
00117 void KW40Z::mainStarter(void const *p) {
00118   KW40Z *instance = (KW40Z*)p;
00119   instance->mainTask();
00120 }
00121 
00122 void KW40Z::GetVersion()
00123 {
00124     hostInterface_packet_t txPacket = {0};
00125     
00126     txPacket.start1     = gHostInterface_startByte1,
00127     txPacket.start2     = gHostInterface_startByte2,
00128     txPacket.type       = packetType_buildVersion,
00129     txPacket.length     = 3,
00130     txPacket.data[0]    = HEXIWEAR_VERSION_MAJOR;
00131     txPacket.data[1]    = HEXIWEAR_VERSION_MINOR;
00132     txPacket.data[2]    = HEXIWEAR_VERSION_PATCH;
00133     txPacket.data[3]    = gHostInterface_trailerByte;
00134     
00135     SendPacket(&txPacket, false);
00136 }
00137 
00138 void KW40Z::SendPacket(hostInterface_packet_t * txPacket, bool confirmRequested)
00139 {
00140     uint8_t retries = 0;
00141     confirmReceived = false;
00142     
00143     do
00144     {
00145         char * txBuff = (char *)txPacket;
00146         uint8_t length = txPacket->length + gHostInterface_headerSize + 1;
00147         
00148         if(confirmRequested == true)
00149         {
00150             txPacket->start2 |= 0x01;
00151         }
00152         
00153         for(uint8_t i = 0; i < length; i++)
00154         {
00155             device.putc(*txBuff);
00156             txBuff++;
00157         }
00158         
00159 #if defined (LIB_DEBUG)   
00160         DebugPrintTxPacket(txPacket);
00161 #endif
00162 
00163         retries++;
00164         
00165         #if defined (gHostInterface_RxConfirmationEnable)
00166         if((confirmRequested == true) && (confirmReceived == false))
00167         {
00168             Thread::wait(gHostInterface_retransmitTimeout);
00169         }
00170         #endif
00171     }
00172     while((confirmRequested == true) && 
00173           (confirmReceived == false) && 
00174           (retries < gHostInterface_retransmitCount));
00175 }
00176 
00177 void KW40Z::mainTask(void)
00178 {
00179     mainThread.signal_wait(START_THREAD);
00180 
00181 #if defined (LIB_DEBUG)     
00182     pc.printf("MainTask Stared\r\n");
00183 #endif
00184 
00185     while(1)
00186     {
00187         osEvent evt = queue.get();
00188         if (evt.status == osEventMessage) 
00189         {
00190             hostInterface_packet_t *rxPacket = (hostInterface_packet_t*)evt.value.p;
00191             ProcessReceivedPacket(rxPacket);
00192             mpool.free(rxPacket);
00193         }
00194     }
00195 }
00196 
00197 void KW40Z::rxTask(void)
00198 {
00199     rxThread.signal_wait(START_THREAD);
00200 
00201 #if defined (LIB_DEBUG)     
00202     pc.printf("RxTask Stared\r\n");
00203 #endif
00204 
00205     while(1)
00206     {
00207         if(device.readable()) 
00208         {   
00209             *rxBuff++ = device.getc();
00210             ProcessBuffer();
00211             
00212             /* check for buffer overflow */
00213             if(rxBuff >= ((uint8_t*)&hostInterface_rxPacket + sizeof(hostInterface_rxPacket)))
00214             {
00215                 rxBuff = (uint8_t*)&hostInterface_rxPacket;
00216             }
00217         }
00218     }
00219 }
00220 
00221 #if defined (LIB_DEBUG) 
00222 void KW40Z::DebugPrintTxPacket(hostInterface_packet_t * txPacket)
00223 {
00224     char * txBuff = (char *)txPacket;
00225     uint8_t length = txPacket->length + gHostInterface_headerSize + 1;
00226 
00227     pc.printf("Tx: ");    
00228     for(uint8_t i = 0; i < length; i++)
00229     {
00230         pc.printf("%02X ",*txBuff);
00231         txBuff++;
00232     }
00233     pc.printf("\r\n");
00234 }
00235 
00236 void KW40Z::DebugPrintRxPacket()
00237 {
00238     pc.printf("RX: ");
00239     for(uint8_t * i = (uint8_t*)&hostInterface_rxPacket; i<rxBuff; i++)
00240     {
00241         pc.printf("%02X ",*i);
00242     }
00243     pc.printf("\r\n");
00244 }
00245 #endif
00246 
00247 void KW40Z::ProcessBuffer()
00248 {    
00249     /* check if header has been received */
00250     if(rxBuff > ((uint8_t*)&hostInterface_rxPacket + gHostInterface_headerSize))
00251     {
00252         /* check packet header */
00253         if((gHostInterface_startByte1 != hostInterface_rxPacket.start1)||
00254            (gHostInterface_startByte2 != (hostInterface_rxPacket.start2 & 0xFE))||
00255            (hostInterface_rxPacket.length > gHostInterface_dataSize))
00256         {
00257 #if defined (LIB_DEBUG) 
00258             DebugPrintRxPacket();
00259             pc.printf("check header failed\r\n");
00260 #endif
00261       
00262             SearchStartByte();
00263         }
00264         else
00265         {
00266             /* check data length */
00267             if(rxBuff > ((uint8_t*)&hostInterface_rxPacket + gHostInterface_headerSize + hostInterface_rxPacket.length)) 
00268             {
00269                 /* check trailer byte */
00270                 if(gHostInterface_trailerByte != hostInterface_rxPacket.data[hostInterface_rxPacket.length])
00271                 {
00272 #if defined (LIB_DEBUG) 
00273                     DebugPrintRxPacket();
00274                     pc.printf("trailer byte failed\r\n");
00275 #endif
00276 
00277                     SearchStartByte();
00278                 }
00279                 else
00280                 {   
00281                 
00282                     #if defined (gHostInterface_RxConfirmationEnable)
00283                     if(hostInterface_rxPacket.type == packetType_OK)
00284                     {
00285                         confirmReceived = true;
00286                     }
00287                     #endif
00288                     
00289                     /* send message to main task */
00290                     hostInterface_packet_t *rxPacket = mpool.alloc();
00291                     memcpy(rxPacket, &hostInterface_rxPacket, sizeof(hostInterface_packet_t));
00292                     queue.put(rxPacket);
00293 
00294 #if defined (LIB_DEBUG)                     
00295                     DebugPrintRxPacket();
00296 #endif 
00297                     /* reset buffer position */
00298                     rxBuff = (uint8_t*)&hostInterface_rxPacket;
00299                 } 
00300             }      
00301         }
00302     }
00303 }
00304 
00305 void KW40Z::SearchStartByte()
00306 {
00307     bool found = false;
00308     uint8_t * rdIdx = (uint8_t*)&hostInterface_rxPacket + 1;
00309     
00310     while(rdIdx < rxBuff)
00311     {
00312         if(*rdIdx == gHostInterface_startByte1)
00313         {
00314             uint32_t len = rxBuff - rdIdx;
00315             
00316             memcpy(&hostInterface_rxPacket,rdIdx,len);
00317             rxBuff -= len;
00318             found = true;
00319             
00320 #if defined (LIB_DEBUG) 
00321             pc.printf("moving ");
00322 #endif
00323             break;
00324         }
00325         rdIdx++;
00326     }
00327     
00328     if(!found)
00329     {
00330         /* reset buffer position */
00331         rxBuff = (uint8_t*)&hostInterface_rxPacket;
00332     }
00333     
00334 #if defined (LIB_DEBUG) 
00335     pc.printf("search done\r\n");
00336     DebugPrintRxPacket();
00337 #endif
00338 }
00339 
00340 void KW40Z::SendPacketOK()
00341 {
00342     hostInterface_packet_t txPacket = {0};
00343     
00344     txPacket.start1     = gHostInterface_startByte1,
00345     txPacket.start2     = gHostInterface_startByte2,
00346     txPacket.type       = packetType_OK,
00347     txPacket.length     = 0,
00348     txPacket.data[0]    = gHostInterface_trailerByte;
00349     
00350     SendPacket(&txPacket, false);    
00351 }
00352 
00353 void KW40Z::ConfirmPacketOK()
00354 {
00355 }
00356 
00357 void KW40Z::ProcessReceivedPacket(hostInterface_packet_t * rxPacket)
00358 {
00359 #if defined (LIB_DEBUG) 
00360     pc.printf("packet found %d\r\n", rxPacket->type);
00361 #endif
00362 
00363 #ifdef gHostInterface_TxConfirmationEnable
00364       // acknowledge the packet reception
00365       if ( 1 == ( rxPacket->start2 & 0x01 ) )
00366       {
00367           SendPacketOK();
00368       }
00369 #endif
00370     
00371     switch(rxPacket->type)
00372     {
00373         /* button presses */
00374         case packetType_pressUp:
00375             if(buttonUpCb != NULL) buttonUpCb();
00376             break;
00377             
00378         case packetType_pressDown:
00379             if(buttonDownCb != NULL) buttonDownCb();
00380             break;
00381             
00382         case packetType_pressLeft:
00383             if(buttonLeftCb != NULL) buttonLeftCb();
00384             break;
00385             
00386         case packetType_pressRight:
00387             if(buttonRightCb != NULL) buttonRightCb();
00388             break;
00389         
00390         case packetType_slide:
00391             if(buttonSlideCb != NULL) buttonSlideCb();
00392             break;
00393     
00394         /* Alert Service */
00395         case packetType_alertIn:
00396             if(alertCb != NULL) alertCb(&rxPacket->data[0], rxPacket->length);
00397             break;
00398         
00399         /* Passkey for pairing received */
00400         case packetType_passDisplay:
00401             if(passkeyCb != NULL) passkeyCb(&rxPacket->data[0]);
00402             break;
00403             
00404         /* OTAP messages */
00405         case packetType_otapCompleted:
00406         case packetType_otapFailed:
00407             break;
00408             
00409         /* TSI Status */
00410         case packetType_buttonsGroupSendActive:
00411             break;
00412             
00413         /* Advertisement Mode Info */
00414         case packetType_advModeSend:
00415             break;
00416         
00417         /* Link State */
00418         case packetType_linkStateSend:
00419             break;
00420             
00421         /* ANCS Service Notification Received */
00422         case packetType_notification:
00423             if(notificationsCb != NULL) notificationsCb(rxPacket->data[0], rxPacket->data[1]);
00424             break;
00425             
00426         /* Build version */
00427         case packetType_buildVersion:
00428             break;
00429       
00430         case packetType_OK:
00431             /* do nothing, the flag is set in the RxTask */
00432             break;
00433     
00434         default:
00435             break;
00436     }
00437 }