PokittoLib is the library needed for programming the Pokitto DIY game console (www.pokitto.com)
Dependents: YATTT sd_map_test cPong SnowDemo ... more
PokittoCookie.cpp
00001 /**************************************************************************/ 00002 /*! 00003 @file PokittoCookie.cpp 00004 @author Jonne Valola 00005 00006 @section LICENSE 00007 00008 Software License Agreement (BSD License) 00009 00010 Copyright (c) 2018, Jonne Valola 00011 All rights reserved. 00012 00013 Redistribution and use in source and binary forms, with or without 00014 modification, are permitted provided that the following conditions are met: 00015 1. Redistributions of source code must retain the above copyright 00016 notice, this list of conditions and the following disclaimer. 00017 2. Redistributions in binary form must reproduce the above copyright 00018 notice, this list of conditions and the following disclaimer in the 00019 documentation and/or other materials provided with the distribution. 00020 3. Neither the name of the copyright holders nor the 00021 names of its contributors may be used to endorse or promote products 00022 derived from this software without specific prior written permission. 00023 00024 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY 00025 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00026 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00027 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 00028 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00029 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00030 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00031 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00032 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00033 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 */ 00035 /**************************************************************************/ 00036 00037 #include "Pokitto_settings.h " 00038 #include "Pokitto.h " 00039 #include "PokittoCookie.h " 00040 00041 #ifndef POK_SIM 00042 #else 00043 #include "PokittoSimulator.h" 00044 #endif 00045 00046 using namespace Pokitto; 00047 00048 //char Cookie::_key[SBKEYSIZE]; 00049 //char Cookie::_keyorder; 00050 //bool Cookie::_status; 00051 00052 #define HARDCODEDOFFSET 25 //bypasses Cookie parent instance general data (that does not need to be saved in EEPROM) 00053 00054 Cookie::Cookie() { 00055 _status = false; 00056 _keyorder = SBINVALIDSLOT; 00057 } 00058 00059 int Cookie::initialize() { 00060 //initialize is called from begin() and can be called several times during program run 00061 int datasize = _datasize; 00062 // check if key already exists 00063 _keyorder = exists(_key); 00064 if (_keyorder < SBMAXKEYS) { 00065 // key already exists 00066 // check amount of existing storage reserved for cookie 00067 datasize -= getAssignedBlocks()*SBBLOCKSIZE; 00068 if (datasize<=0) { 00069 // the size of data matches the size requested 00070 // therefore retrieve data from storage 00071 _status = true; //were good to go 00072 loadCookie(); 00073 } else { 00074 // if that does not cover the whole size (maybe a newer version of program, who knows) 00075 // then do not load but reserve more blocks and store a new version 00076 while (datasize>0) { 00077 if(reserveBlock()) datasize -= SBBLOCKSIZE; 00078 else return SBNOTENOUGHBLOCKSFREE; //no space to allocate 00079 } 00080 _status = true; //were good to go 00081 eraseKeytableEntry(_keyorder); 00082 writeKeyToKeytable(_key,_keyorder); // write the key in the key table in EEPROM 00083 saveCookie(); 00084 } 00085 } else { 00086 // new key needed 00087 // check if we have free keyslots 00088 _keyorder = getFreeKeytableSlot(); 00089 if (_keyorder>=SBMAXKEYS) return SBNOMOREKEYS; //no space for key 00090 // check if we have free storage blocks 00091 if (getFreeBlocks()*SBBLOCKSIZE<datasize) return SBNOTENOUGHBLOCKSFREE; //no space to allocate 00092 while (datasize>0) { 00093 //reserve enough blocks for the data until all data can fit 00094 if(reserveBlock()) datasize -= SBBLOCKSIZE; 00095 else return SBNOTENOUGHBLOCKSFREE; //no space to allocate 00096 } 00097 } 00098 _status = true; //were good to go 00099 eraseKeytableEntry(_keyorder); 00100 writeKeyToKeytable(_key,_keyorder); // write the key in the key table in EEPROM 00101 return 0; 00102 } 00103 00104 int Cookie::begin(const char* idkey, int datasize, char* ptr) { 00105 _status=false; 00106 _datasize=datasize-HARDCODEDOFFSET;// warning! hardcoded! sizeof(this); //do not include the data of the parent Cookie instance 00107 _pointer = ptr + HARDCODEDOFFSET;// warning! hardcoded! sizeof(this); //point to the beginning of the inherited instance 00108 char _idkey[8]; 00109 // make _idkey exactly 8 readable characters long 00110 for (int t = 0 ; t < 8 ; t++) _idkey[t]=' '; 00111 for (int t = 0 ; t < 8 ; t++) {if (idkey[t]==0) break; _idkey[t]=idkey[t];} 00112 // clean Keytable of keys with no storage 00113 cleanKeytable(); 00114 memcpy(_key, _idkey, SBKEYSIZE); //store name of key 00115 initialize(); 00116 return 0; //success 00117 } 00118 00119 bool Cookie::saveCookie() { 00120 if (!_status || !_pointer) return false; //return if not initialized 00121 char* p = _pointer; 00122 _head=0; 00123 _block=0; 00124 _block=findMyNextBlock(); 00125 for (int i=0; i<_datasize; i++) writeQueue(*p++); 00126 #if POK_ENABLE_SOUND 00127 Pokitto::soundInit(true); //re-init sound 00128 #endif 00129 return true; 00130 } 00131 00132 bool Cookie::loadCookie() { 00133 if (!_status || !_pointer) return false; 00134 char* p = _pointer; 00135 _head=0; 00136 _block=0; 00137 _block=findMyNextBlock(); 00138 for (int i=0; i<_datasize; i++) *p++ = readQueue(); 00139 return true; 00140 } 00141 00142 void Cookie::deleteCookie() { 00143 if (!_status) return; 00144 // free all blocks held by Cookie 00145 for (int i=0; i<SBMAXBLOCKS; i++) { 00146 if (isMyBlock(i)) freeBlock(i); 00147 } 00148 // erase Cookie entry from keytable 00149 eraseKeytableEntry(_keyorder); 00150 // set status to deleted 00151 _status = false; 00152 } 00153 00154 int Cookie::exists(const char* idkey) { 00155 for (int i=0; i< SBMAXKEYS; i++) { 00156 00157 if(eeprom_read_byte((uint16_t*)(i*SBKEYSIZE))==idkey[0]) { 00158 int total=0; 00159 for (int j=0; j<SBKEYSIZE;j++) { 00160 if(eeprom_read_byte((uint16_t*)(i*SBKEYSIZE+j))==idkey[j]) total++; 00161 } 00162 if (total==SBKEYSIZE) return i; // return the keyslot number where key exists 00163 } 00164 00165 } 00166 return SBINVALIDSLOT; //not found 00167 } 00168 00169 int Cookie::getFreeKeytableSlot() { 00170 int freeslot=SBINVALIDSLOT; 00171 for (int i=0; i<SBMAXKEYS; i++) { 00172 00173 if (eeprom_read_byte((uint16_t*)(i*SBKEYSIZE))==0) {freeslot=i; break;} 00174 00175 } 00176 return freeslot; 00177 } 00178 00179 int Cookie::getAssignedBlocks() { 00180 int assignedblocks=0; 00181 for (int i=0;i<SBMAXBLOCKS;i++) { 00182 if (isMyBlock(i)) assignedblocks++; 00183 } 00184 return assignedblocks; 00185 } 00186 00187 int Cookie::getFreeBlocks() { 00188 int freeblocks=0; 00189 for (int i=0;i<SBMAXBLOCKS;i++) { 00190 if (isFreeBlock(i)) freeblocks++; 00191 } 00192 return freeblocks; 00193 } 00194 00195 bool Cookie::isFreeBlock(int n) { 00196 if (n>=SBMAXBLOCKS) return false; 00197 00198 if (!(eeprom_read_byte((uint16_t*)(SBMAXKEYS*SBKEYSIZE+n))&0x80)) return true; //highest bit 0, its free 00199 00200 return false; //its not free 00201 } 00202 00203 bool Cookie::isMyBlock(int n) { 00204 if (n>=SBMAXBLOCKS) return false; 00205 if (isFreeBlock(n)) return false; //"free" blocks can not be "reserved" at the same time! 00206 00207 char temp; int address; 00208 address = (SBMAXKEYS*SBKEYSIZE+n); 00209 temp = eeprom_read_byte((uint16_t*)address); 00210 if ((temp&0x7F) ==_keyorder) return true; 00211 00212 return false; //its not your block 00213 } 00214 00215 bool Cookie::blockIsOwnedBy(int n, int k) { 00216 if (n>=SBMAXBLOCKS) return false; 00217 if (k>=SBMAXKEYS) return false; 00218 if (isFreeBlock(n)) return false; //"free" blocks can not be "owned" by anyone 00219 00220 char temp; int address; 00221 address = (SBMAXKEYS*SBKEYSIZE+n); 00222 temp = eeprom_read_byte((uint16_t*)address); 00223 if ((temp&0x7F) == k) return true; 00224 00225 return false; //its not your block 00226 } 00227 00228 void Cookie::writeKeyToKeytable(const char* key, int slot) { 00229 for (int i=0; i<SBKEYSIZE; i++) { 00230 00231 if (key[i]) eeprom_write_byte((uint16_t*)(slot*SBKEYSIZE+i),key[i]); 00232 else eeprom_write_byte((uint16_t*)(slot*SBKEYSIZE+i),0); 00233 00234 } 00235 } 00236 00237 void Cookie::readKeytableEntry(int n, char* answer) { 00238 answer[8]=0; 00239 if (n >= SBMAXKEYS) n=SBMAXKEYS-1; 00240 for (int i=0; i<SBKEYSIZE; i++) { 00241 00242 answer[i] = eeprom_read_byte((uint16_t*)(n*SBKEYSIZE+i)); 00243 00244 } 00245 } 00246 00247 char Cookie::getBlockTableEntry(int n) { 00248 if (n>=SBMAXBLOCKS) return 0x80; // out of bounds will return a reserved block marker 00249 00250 return eeprom_read_byte((uint16_t*)(SBKEYSIZE*SBMAXKEYS+n)); 00251 00252 return 0x80; 00253 } 00254 00255 void Cookie::readBlock(int n, char* data) { 00256 for (int i=0; i<SBBLOCKSIZE; i++) { 00257 data[i]=0; 00258 00259 if (n < SBMAXBLOCKS) data[i] = eeprom_read_byte((uint16_t*)(SBKEYSIZE*SBMAXKEYS+SBMAXBLOCKS+n*SBBLOCKSIZE+i)); 00260 00261 } 00262 } 00263 00264 void Cookie::formatKeytable() { 00265 for (int j=0; j<SBMAXKEYS; j++) { 00266 for (int i=0; i<SBKEYSIZE; i++) { 00267 00268 eeprom_write_byte((uint16_t*)(j*SBKEYSIZE+i),0); 00269 00270 } 00271 } 00272 } 00273 00274 void Cookie::freeBlock(int n) { 00275 if (n >= SBMAXBLOCKS) return; //out of bounds 00276 00277 // delete entry from blocktable 00278 eeprom_write_byte((uint16_t*)(SBKEYSIZE*SBMAXKEYS+n),0); 00279 00280 for (int i=0; i<SBBLOCKSIZE;i++) { 00281 00282 // wipe data in the block 00283 eeprom_write_byte((uint16_t*)(SBKEYSIZE*SBMAXKEYS+SBMAXBLOCKS+n*SBBLOCKSIZE+i),0); 00284 00285 } 00286 } 00287 00288 bool Cookie::reserveBlock() { 00289 for (int i=0; i<SBMAXBLOCKS;i++) { 00290 00291 // reserve block from blocktable 00292 if (isFreeBlock(i)) { 00293 //free block found, mark it for us in the blocktable 00294 eeprom_write_byte((uint16_t*)(SBKEYSIZE*SBMAXKEYS+i),_keyorder | 0x80); 00295 return true; 00296 } 00297 00298 } 00299 return false; // no free block found 00300 } 00301 00302 void Cookie::eraseKeytableEntry(int n) { 00303 if (n >= SBMAXKEYS) n=SBMAXKEYS-1; 00304 for (int i=0; i<SBKEYSIZE; i++) { 00305 00306 eeprom_write_byte((uint16_t*)(n*SBKEYSIZE+i),0); 00307 00308 } 00309 } 00310 00311 void Cookie::cleanKeytable() { 00312 //Remove any keys without blocks 00313 for (int entry=0; entry<SBMAXKEYS; entry++) { 00314 if (eeprom_read_byte((uint16_t*)(entry*SBKEYSIZE))) { 00315 bool isEmpty=true; 00316 for (int block=0; block<SBMAXBLOCKS; block++) if (blockIsOwnedBy(block,entry)) {isEmpty=false;break;} 00317 //this entry has no blocks reserved, so lets clean it from the keytable 00318 if (isEmpty) eraseKeytableEntry(entry); 00319 } 00320 } 00321 for (int block=0;block<SBMAXBLOCKS;block++) { 00322 int blockentry = eeprom_read_byte((uint16_t*)(SBMAXKEYS*SBKEYSIZE+block)); 00323 if (blockentry&0x80) { 00324 blockentry &= 0x7F; 00325 bool isEmpty=true; 00326 for (int key=0;key<SBMAXKEYS;key++) { 00327 if (eeprom_read_byte((uint16_t*)(key*SBKEYSIZE))) {isEmpty=false;break;} 00328 } 00329 if (isEmpty) eeprom_write_byte((uint16_t*)(SBMAXKEYS*SBKEYSIZE+block),0); 00330 } 00331 } 00332 } 00333 00334 char Cookie::readQueue() { 00335 char data=0; 00336 00337 int address; 00338 address = SBMAXKEYS*SBKEYSIZE+SBMAXBLOCKS+SBBLOCKSIZE*_block+_head%SBBLOCKSIZE; 00339 data=eeprom_read_byte((uint16_t*)address); 00340 00341 _head++; 00342 if (_head%SBBLOCKSIZE==0 && _head) { 00343 _block++; 00344 _block=findMyNextBlock(); 00345 } 00346 return data; 00347 } 00348 00349 void Cookie::writeQueue(char data) { 00350 00351 eeprom_write_byte((uint16_t*)(SBMAXKEYS*SBKEYSIZE+SBMAXBLOCKS+SBBLOCKSIZE*_block+_head%SBBLOCKSIZE),data); 00352 00353 _head++; 00354 if (_head%SBBLOCKSIZE==0 && _head) { 00355 _block++; 00356 _block=findMyNextBlock(); 00357 } 00358 } 00359 00360 int Cookie::findMyNextBlock() { 00361 if (!_status) return SBINVALIDBLOCK; 00362 for (int i=_block; i<SBMAXBLOCKS;i++) if (isMyBlock(i)) return i; 00363 return SBINVALIDBLOCK; 00364 } 00365 00366 00367
Generated on Tue Jul 12 2022 11:20:35 by 1.7.2