The field version of the solarnano grid on the ionQubes
Fork of SolarNanoGridv3 by
Battery/Battery.cpp
- Committer:
- epgmdm
- Date:
- 2016-06-08
- Revision:
- 11:87ab310924f0
- Parent:
- 10:30c9e8df0032
- Child:
- 12:d9b13f31206d
File content as of revision 11:87ab310924f0:
/** *@section DESCRIPTION * mbed SolarNanogrid Library * Battery extends SolarNanoGrid. * Battery interacts with the lockers. * The ID must NOT 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 "Battery.c" */ #include "Battery.h" #define FUNCNAME "BATTERY" #include "defs.h" // ------------------------------------------------------------------------ // Constructors // ------------------------------------------------------------------------ Battery::Battery(FILE* fp, Serial *pc) : SolarNanoGrid(fp,pc){ DBG("Initialize class"); // ***** Variable initialisation ***** // Public variable initialisation maxChargeRate=0.0; // Charge rate in amps // Protected variables initialisation count=0; sizeRead=0; fileLength=0; filePointer=0; fileLeft=0; sdBuffPnt=0; /** * Open channel address of the locker */ openAddr=0; /** * Private channel address of the locker */ privateAddr=0; countSD=0; // Protected flags: * checkedIn=0; flagGetTime=0; flagNextFile=0; flagSendFileName=0; flagSendFileSize=0; flagSendFile=0; flagSendFileDone=0; // Protected interrupts button=NULL; txWatch=NULL; delay=NULL; //Private variables initialisation maxRT=false; // ***** End of variables initialisation ***** // No other information needed from the config file fclose(fp); // // Setup variables // txFileName = (char*) calloc(80, 1); fullTxFilePath = (char*) calloc(80, 1); logDir = (char*) calloc(20, 1); sdBuffer = (char*) calloc(SDBUFFERSIZE, 1); // // Setup NRF // privateAddr = ((long long)communityID <<16)+ (id &0XFFFF); openAddr = privateAddr & 0xFFFFFFFF00; DBG("Channel %x Address %llx Address Locker %llx", chan, privateAddr, openAddr); spiNRF(); nrf->quickTxSetup(chan, openAddr); nrf->setRadio(0x01, 0x03); // 2MB/S 0dB nrf->setTxRetry(0x0F, 0x0F); nrfFlush(); DBG("Nrf Details:"); #ifdef DEBUG nrf->printDetails(); #endif // // Setup logging directories // sprintf(logDir, "/sd/data/%02X%04X", (communityID&0XFF),(id&0XFFFF)); DBG(" Log directory %s", logDir); spiSD(); mkdir("/sd/data", 777); mkdir(logDir, 777); DBG(" made"); // // Setup interrupts // button = new InterruptIn(SW2); button->fall(this, &Battery::intButton); nrfInt = new InterruptIn(PTC18); nrfInt->fall(this, &Battery::intNrf); // attach nrf interrupt. txWatch = new Ticker (); txWatch->attach(this,&Battery::retransmit,10.01); delay = new Timeout(); loop(); } // ------------------------------------------------------------------------ // Interrupt routines // ------------------------------------------------------------------------ /** * When the button is pressed transmit something */ void Battery::intButton(){ if (!maxRT){ *ce = 1; if(checkedIn==0){ checkIn(); } else{ flagNextFile = 1; } } } /** * Called when the nrf creates an interrupt. * */ void Battery::intNrf(){ // DBG("NRF Interrupt Started."); int pipe=0; int status=0; int width=0; // //Get status and pipe // spiNRF(); status = nrf->checkStatus(); pipe = (status >> 1); pipe = (pipe & 0x0007); // // Check if max RT is reached // if (((status >>MAX_RT)& 01) ==1) { maxRT=true; DBG("MAX RT flag is set.PTB20= %d status=%x",*ce,status); *ce = 0; DBG("PTB20= %d status=%x",*ce,status); nrf->clearStatus(); *ledRed=0; } // // Check if data received // if (((status >>RX_DR)& 01) ==1) { // Received a packet width= nrf->getRxData(dataRx); dataRx[width]='\0'; if (dataRx[0]!='S'){ DBG("intNrf>D[p=%1d]=<%2s> ",pipe,dataRx); } maxRT=false; *ce = 1; nrf->clearStatus(); switch (dataRx[0]) { case ('C'):{ doCheckIn(); flagNextFile = 1; break;} case ('D'):{ flag = &flagSendFileName; delay->detach(); delay->attach(this, &Battery::setFlag, 1.5); break;} case ('F'):{ flag = &flagSendFileSize; countSD = 0; delay->detach(); delay->attach(this, &Battery::setFlag, 1.50); break;} case ('S'):{ flag = &flagSendFile; delay->detach(); // printf("%d\n\r",countSD%16); //delay->attach(this, &Battery::setFlag, 0.05); if (countSD % (SDBUFFERSIZE/32) == 0) { delay->attach(this, &Battery::setFlag, 1.5); // wait to write to SD card } else { delay->attach_us(this, &Battery::setFlag, 800); } countSD++; break;} case ('T'):{ time_t now; sscanf (&dataRx[2],"%x",&now ); set_time(now); now= time(NULL); struct tm * timeInf = localtime(&now); DBG ("Time is now: %04d-%02d-%02d %02d:%02d:%02d \n\r",timeInf->tm_year+1900,timeInf->tm_mon+1,timeInf->tm_mday,timeInf->tm_hour, timeInf->tm_min,timeInf->tm_sec); break;} } } if (((status >>TX_DS)& 01) ==1) { // maxRT=false; nrf->flushTx(); nrf->flushRx(); //DBG(" TX_DS"); } *ledBlue = !*ledBlue; *ledRed = !maxRT; } /** * Transmits the data and sets up a call back to check data sent 30s later. */ /** * Checks to see if transmit failed and then retransmit * */ void Battery::retransmit(){ if (maxRT) { DBG("Retransmit"); *ledRed=1; *ce = 1; maxRT=false; nrf->clearStatus(); nrf->flushRx(); nrf->retransmitData(); } } // ------------------------------------------------------------------------ // Main routines // ------------------------------------------------------------------------ /** * Checks in the Battery to the locker * Transmits "C ID" * */ void Battery::checkIn() { sprintf(dataTx, "C %04X", (int) (id&0XFFFF)); DBG("Check into locker [%s]", dataTx); spiNRF(); nrf->transmitData(dataTx, strlen(dataTx)); } /** * Checks in the Battery to the locker * Acknowledge received. * Changes the TX pipe address. * */ void Battery::doCheckIn() { nrf->setTxAddress(privateAddr); checkedIn = 1; DBG("Checked into locker"); DBG("Nrf Details:"); #ifdef DEBUG nrf->printDetails(); #endif } /** * Checks in the Battery to the locker * Acknowledge received. * Changes the TX pipe address. * */ void Battery::doCheckOut() { nrf->setTxAddress(openAddr); checkedIn = 0; DBG("Checked out of locker"); DBG("Nrf Details:"); #ifdef DEBUG nrf->printDetails(); #endif } /** * Slow routines for Battery */ void Battery::loop() { while (1) { *ledGreen = !checkedIn; if (flagGetTime) { flagGetTime=0; getTime(); } if (flagNextFile) { flagNextFile = 0; getTime(); nextFileToTx(); if (fileLength>0){ INFO("Sending file %s.",txFileName) sendDirName(); } else { INFO("No more files to send.") } } if (flagSendFileName) { flagSendFileName = 0; sendFileName(); } if (flagSendFileSize) { flagSendFileSize = 0; sendFileSize(); } if (flagSendFile) { flagSendFile = 0; sendFile(); } if (flagSendFileDone) { flagSendFileDone = 0; sendFileDone(); INFO("File sent <%s>",txFileName); flag = &flagNextFile; delay->detach(); delay->attach(this, &Battery::setFlag, 2.5); } __WFI(); } } /** * sends a request for time update. */ void Battery::getTime() { DBG("getTime"); nrf->transmitData("T ",2); } /** * Selects the next file to transmit * Uses /sd/lastFileTx.txt to store the lst file transmitted */ void Battery::nextFileToTx() { DBG("> nextTxFile"); char lastFileName[64]; char fileName[64]; char fn[40]; unsigned int txLength; sdBuffPnt=0;// Tells sendFile to read from SD the first time. fileLength = 0; strcpy(txFileName, ""); spiSD(); // Read in last file name FILE *fp = fopen("/sd/lastFileTx.txt", "r"); if (fp != NULL) { if (fscanf(fp, "%s %u", lastFileName, &txLength) != 2) { sprintf(lastFileName, "a"); } fclose(fp); } else { sprintf(lastFileName, "a"); } DBG("nextFileToTx>Last Filename=%s len=%u",lastFileName,txLength); // Open directory and read files DIR *dp; struct dirent *dirp; spiSD(); dp = opendir(logDir); if (dp == NULL) { DBG("nextTxFile logdir %s is NULL", logDir); } else //read all directory and file names in current directory into filename vector while ((dirp = readdir(dp)) != NULL) { DBG("nextFileToTx> WHILE lst [%s] dir [%s] %d",lastFileName, dirp->d_name,strcmp(lastFileName, dirp->d_name)); if (strcmp(lastFileName, dirp->d_name) < 0) { strcpy(fileName, dirp->d_name); sprintf(txFileName, "%s/%s", logDir, dirp->d_name); fp = fopen(txFileName, "r"); fseek(fp, 0L, SEEK_END); fileLength = ftell(fp); fclose(fp); DBG("CHOSEN %s old %s ", fileName, lastFileName ); break; } if (strcmp(lastFileName, dirp->d_name) == 0) { strcpy(fileName, dirp->d_name); sprintf(fn, "%s/%s", logDir, dirp->d_name); fp = fopen(fn, "r"); fseek(fp, 0L, SEEK_END); fileLength = ftell(fp); fclose(fp); if (txLength < fileLength) { sprintf(txFileName, "%s/%s", logDir, dirp->d_name); DBG("More to send is %s old %u new %u ", fileName, txLength,fileLength ); break; } } // test filename and if greater than last read then choose. } closedir(dp); if (strlen(txFileName) > 0) { strcpy(txFileName, fileName); sprintf(fullTxFilePath, "%s/%s", logDir, txFileName); fileLeft = fileLength; } else { fileLength =0; } DBG("nextTxFile> Next is [%s] length %d", txFileName, fileLength); } /** * Sends the directory name, allows the otherside to create. */ void Battery::sendDirName() { sprintf(dataTx, "D %s", logDir); DBG("send Dir Name [%s].\n\r", dataTx); spiNRF(); nrf->transmitData(dataTx, strlen(dataTx)); } /** * Sends the file name, if fileLength >0 */ void Battery::sendFileName() { // delay->detach(); if (fileLength < 1) { return; } sprintf(dataTx, "F %20s", txFileName); DBG("send File Name [%s] \n\r", dataTx); spiNRF(); nrf->transmitData(dataTx, strlen(dataTx)); } /** * Sends the file length to the locker - this is also the cue that the following bytes are the file. */ void Battery::sendFileSize() { if (fileLength < 1) { return; } filePointer = 0; sprintf(dataTx, "S %X", fileLength); DBG("send File size [%s]", dataTx); spiNRF(); nrf->transmitData(dataTx, strlen(dataTx)); } /** * Sends the file length to the locker - this is also the cue that the following bytes are the file. */ void Battery::sendFile() { // printf("send File [%s] at %d %d\n\r",fullTxFilePath,fileLength, fileLeft ); // if (fileLength < 1) { // INFO("File Sent"); // sdBuffPnt=0; // return; // } if (sdBuffPnt>=SDBUFFERSIZE){ sdBuffPnt=0; } if (sdBuffPnt == 0) { spiSD(); FILE *fp = fopen(fullTxFilePath, "rb"); if (fp == NULL) { spiNRF(); INFO("sendFile> File %s not found for reading",fullTxFilePath); return; } spiSD(); fseek(fp, fileLength - fileLeft, SEEK_SET); sizeRead = fread(sdBuffer, 1,SDBUFFERSIZE, fp); fileLeft -= sizeRead; fclose(fp); // printf("File %s %d \n\r",fullTxFilePath,sizeRead); spiNRF(); } if ((count++) % 256 ==0) { DBG("W %d %d", fileLeft, sizeRead); } int size=32; if (sizeRead<32){ size=sizeRead; } if ((fileLeft==0)&&(sizeRead==0)){ sdBuffPnt=0; flagSendFileDone=1; DBG("Done sending"); }else{ sizeRead -= size; nrf->transmitData(&(sdBuffer[sdBuffPnt]), size); sdBuffPnt+=size; } } /** * Update the last file sent file */ void Battery::sendFileDone() { if (strlen(txFileName)>0){ spiSD(); FILE *fp = fopen("/sd/lastFileTx.txt", "w"); if (fp != NULL) { fprintf(fp, "%s %u \n", txFileName, fileLength); fclose(fp); DBG("sendFileDone> updated lastFileTx.txt %s %u ", txFileName, fileLength); }else{ INFO("sendFileDone> Cannot update file lastFiletx.txt"); } spiNRF(); } } /** * Sets the value pointed to by flag to 1. */ void Battery::setFlag() { if (flag != NULL) { *flag = 1; } flag = NULL; }