The field version of the solarnano grid on the ionQubes
Fork of SolarNanoGridv3 by
Locker/Locker.cpp
- Committer:
- defrost
- Date:
- 2016-09-06
- Revision:
- 36:a5620262f296
- Parent:
- 28:e85a86fc8b59
File content as of revision 36:a5620262f296:
/** *@section DESCRIPTION * mbed SolarNanogrid Library * Locker extends SolarNanoGrid. * Locker interacts with the batteries. * The ID must end in 00. *@section LICENSE * Copyright (c) 2016, Malcolm McCulloch * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * @file "Locker.c" */ #include "Locker.h" #define FUNCNAME "LOCKER" #include "defs.h" Locker::Locker(FILE* fp,Serial *pc) : SolarNanoGrid(fp,pc) { DBG("Initialize class locker"); // ***** variables initialization ***** // Protected variables: * /** * Open channel address of the locker */ openAddr=0; /** * Channel address for Utility */ addrUtil=0; /** * Array of battery states */ sdBuffPnt=0; battQP=0; // Battery queue pointer pipeQP=0; // pipe q pointer (Add 2) pipe = 0; width = 0; now=0; lastRxTme=0; maxCharge=1.0; // flags flagRotate=false; flagNrf=0; flagOneSecond=0; // ***** end of varibale initialization ***** // No other information needed from the config file fclose(fp); DBG("Close file"); battIn = (char *) calloc(256, 1); battPipes = (char *) calloc(6, 1); for (int i = 0; i < 4; i++) { dirNames[i] = (char *) calloc(32, 1); fileNames[i] = (char *) calloc(32, 1); } temp = (char *) calloc(64, 1); timeValue = (char *) calloc(32, 1); maxChargeValue= (char *) calloc(32, 1); sdBuffer = (char *) calloc(SDBUFFERSIZE,1); doOneSecond(); // // Setup NRF // openAddr = ((long long) communityID << 16) + (id & 0XFFFF); addrUtil = (openAddr & 0XFFFFFF0000) | 0xFE00; DBG(" Channel:%x, Address %llx Util Address %llx", chan, openAddr, addrUtil); setAsRX(addrUtil); nrf->setRxAddress(openAddr, 1); //Default battery pipe address 1 DBG("Nrf Details:"); #ifdef DEBUG nrf->printDetails(); #endif // //Pods // pods[0]=new DigitalOut(PTE24,0); pods[1]=new DigitalOut(PTE25,0); pods[2]=new DigitalOut(PTD1,0); pods[3]=new DigitalOut(PTD3,0); pods[4]=new DigitalOut(PTD2,0); pods[5]=new DigitalOut(PTD0,0); pods[6]=new DigitalOut(PTC4,0); pods[7]=new DigitalOut(PTE26,0); pods[8]=new DigitalOut(PTC5,0); pods[9]=new DigitalOut(PTC7,0); pods[10]=new DigitalOut(PTC0,0); pods[11]=new DigitalOut(PTC9,0); pods[12]=new DigitalOut(PTC8,0); pods[13]=new DigitalOut(PTC1,0); pods[14]=new DigitalOut(PTB19,0); pods[15]=new DigitalOut(PTB18,0); // // Interrupts // nrfInt = new InterruptIn(PTC18); nrfInt->fall(this, &Locker::intNrf); // attach nrf interrupt. button = new InterruptIn(SW2); button->fall(this, &Locker::intButton); rxWatch = new Ticker(); rxWatch->attach(this, &Locker::intRxClean, 30.14151); oneSecond = new Ticker(); oneSecond->attach(this, &Locker::intOneSecond, 1.0); loop(); } // Protected // ------------------------------------------------------------------------ // Interrupt routines // ------------------------------------------------------------------------ void Locker::intOneSecond() { flagOneSecond = 1; } void Locker::doOneSecond() { now = time(NULL); sprintf(timeValue, "T %x", now); sprintf(maxChargeValue,"M %4.2f",maxCharge); *ledGreen = !*ledGreen; // DBG("One second: %s", timeValue); } /** * called when the nrf creates an interrupt. * */ void Locker::intNrf() { int bID = 0; int status = 0; // //Get status and pipe // spiNRF(); status = nrf->checkStatus(); pipe = (status >> 1); pipe = (pipe & 0x0007); // // Check if data received // if (((status >> RX_DR) & 01) == 1) { // Received a packet // Get the data width = nrf->getRxData(dataRx); dataRx[width] = '\0'; //Process the acknowledge if ((pipe>=2)&&(battIn[battPipes[pipe - 2]] == SENDING)) { // A file is being transferred. nrf->acknowledgeData("S ", 2, pipe); flagNrf = 1; DBG("A file is being transferred"); } else if (dataRx[0] == 'T') { // Sends the time - this is updated in doOneSecond() nrf->acknowledgeData(timeValue, strlen(timeValue), pipe); DBG("Send Time in acknowledge"); } else if (dataRx[0] == 'M') { // Sends the maxCharge value - this is updated in doOneSecond() nrf->acknowledgeData(maxChargeValue, strlen(maxChargeValue), pipe); DBG("Sent maxCharge: %s in acknowledge", maxChargeValue); } else { nrf->acknowledgeData(dataRx, 2, pipe); DBG("intNrf>%s %x",dataRx,bID); } if (pipe == 1) { // Open channel DBG("intNrf>Pipe 1 %s",dataRx); if (dataRx[0] == 'C') { //Request for check in int battID; sscanf(&dataRx[2], "%x", &battID); bID = battID & 0x00ff; if (battIn[bID] == CHECKED_OUT) { battIn[bID] = CHECKED_IN; DBG("intNrf>Check in %d", bID); } else { WARN("Battery %04X is already checked in.", battID); } flagRotate = 1; } else if (dataRx[0] == 'b') { //Battery drop off // DBG("intNrf>User check in %s",dataRx); sscanf (&dataRx[2], "%x %x", &userIDDrop, &numBatDrop); int pod = (userIDDrop&0XF0)>>4; if (dataRx[1] == 'd') { turnPodOn(pod,1); *ledRed=0; } if (dataRx[1] == 'p') { turnPodOn(pod,0); *ledRed=1; } } } else if (pipe>1) { if (dataRx[0] == 'O') { //Request for check out int battID; sscanf(&dataRx[2], "%x", &battID); bID = battID & 0x00ff; battIn[bID] = CHECKED_OUT; DBG("intNrf>Check out %d", bID); flagRotate = 1; } flagNrf = 1; } lastRxTme = now; } DBG("intNRF> int rx"); nrf->clearStatus(); *ledBlue = !*ledBlue; } /** * Responds to the received signals from Master and Batteries */ void Locker::doNrf() { //DBG("doNrf>>"); // Now check which pipe if (pipe>1) { //A battery int bID = battPipes[pipe]; // get battery ID from pipe. int p = pipe-2; if (battIn[battPipes[p]] == SENDING) { saveFile(p,dataRx,width); } else { switch (dataRx[0]) { case ('D'): { // Directory name. *ce = 0; sscanf (&dataRx[2],"%s",&(dirNames[p][0])); spiSD(); DBG("doNrf>>>Making dir %s:",dirNames[p]); int ok = mkdir(dirNames[p],777); spiNRF(); DBG("doNrf>>>Directory name[%d] = <%s> OK=%d",p,dirNames[p],ok); *ce = 1; break; } case ('F'): { // File name *ce = 0; strncpy(&fileNames[p][0],&dataRx[2],30); // sscanf (&dataRx[2],"%20s",&fileNames[p][0]); sprintf(temp,"%s/%s",dirNames[p],fileNames[p]); DBG("doNrf>>> Creating File name<%s>",temp); spiSD(); // Make sure file is created and reset FILE *fp = fopen(temp,"wb"); fclose(fp); spiNRF(); DBG("doNrf>>>File name[%d] = <%s>",p,fileNames[p]); *ce = 1; break; } case ('S'): { // File name battIn[battPipes[p]] = SENDING; sscanf (&dataRx[2],"%x",&lengthFile[p]); sdBuffPnt=0; // set buffer to start DBG("doNrf>>>File Length[%d] = <%u>",p,lengthFile[p]); break; } } } } } /** * When the button is pressed print status */ void Locker::intButton() { DBG("int Button"); intRxClean(); } /** * Cleans the receiver */ void Locker::intRxClean() { if (now - lastRxTme>60) { nrfFlush(); wait(0.01); nrfFlush(); DBG("intRxClean < status=%x", nrf->checkStatus()); } } // Loop through slow routines void Locker::loop(void) { while (1) { if (flagRotate == 1) { flagRotate = 0; DBG("R"); doRotate(); } if (flagNrf == 1) { flagNrf = 0; doNrf(); } if (flagOneSecond == 1) { flagOneSecond = 0; doOneSecond(); } __WFI(); }; } /** * Rotates one battery the ON_AIR batteries. */ void Locker::doRotate() { DBG("Rotate"); // Select battery for (int b = 0; b < 255; b++, battQP++) { battQP %= 256; //INFO(" Bat %d stat %d",battQP,battIn[battQP]); if (battIn[battQP] == CHECKED_IN) { pipeQP = (pipeQP) % 4; for (int p = 0; p < 4; p++) { // Select pipe if ((battPipes[pipeQP] == 0) && (battIn[battPipes[pipeQP]] != SENDING)) { // Remove existing battery from pipes and place back in queue if (battIn[battPipes[pipeQP]] == ON_AIR) { battIn[battPipes[pipeQP]] = CHECKED_IN; } battPipes[pipeQP] = battQP; // New battery in battIn[battQP] = ON_AIR; // int address = (addrBattery & 0XFFFFFF00)|battQP; long long address = openAddr | battQP; nrf->setRxAddress(address, pipeQP + 2); nrf->setPwrDown(); nrf->setPwrUp(); DBG("=====> Rotate battQ %d pipeQ %d Addr %llX", battQP, pipeQP, address); DBG("Nrf Details:"); #ifdef DEBUG nrf->printDetails(); #endif break; }; pipeQP = (pipeQP + 1) % 4; } break; } } } /** * Take the info and saves to a file via a buffer. **/ void Locker::saveFile (int p,char *data, int width) { *ledRed=!*ledRed; memcpy (&sdBuffer[sdBuffPnt],data,width); sdBuffPnt += width; lengthFile[p] -= width; //INFO("%d",lengthFile[p]); if ( lengthFile[p] <=0) { flushSDBuffer(p); sdBuffPnt=0; // reset for next one battIn[battPipes[p]] = ON_AIR; INFO("saveFile> File saved: %s/%s ",dirNames[p], fileNames[p]); *ledRed=1; return; } if (sdBuffPnt >= SDBUFFERSIZE) { DBG("Left %u",lengthFile[p]); flushSDBuffer(p); sdBuffPnt=0; } } /** * writes the sdbuffer to file */ void Locker::flushSDBuffer(int p) { //INFO("z"); Timer t; t.start(); strcpy(temp,dirNames[p]); strcat(temp,"/"); strcat(temp,fileNames[p]); //DBG("SD W %s",temp); spiSD(); FILE *fp = fopen(temp,"ab"); if (fp!=NULL) { fwrite(sdBuffer,1,sdBuffPnt,fp); sdBuffPnt=0; fclose(fp); } else { ; } spiNRF(); t.stop(); DBG("flush> Timer = %d ms %d us",t.read_ms(), t.read_us()) } ///** // * Set NRF as RX // */ //void Locker::setAsRX(){ // // spiNRF(); // nrf->quickRxSetup(chan, addrUtil); // Pipe 0 // // nrf->setRadio(0x01, 0x03); // 2MB/S 0dB // nrfFlush(); //} // ///** // * Set NRF as TX // */ //void Locker::setAsTX(){ // spiNRF(); // //} /** * Turns a pod power on */ void Locker::turnPodOn(int pod,int on) { DBG("Pod %d on %d",pod,on); pods[pod]->write(on); }