MHVLib
20111011
An efficiency oriented runtime library for AVR microcontrollers
|
00001 /* Copyright (c) 2011, Make, Hack, Void Inc 00002 * All rights reserved. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions are met: 00006 * * Redistributions of source code must retain the above copyright 00007 * notice, this list of conditions and the following disclaimer. 00008 * * Redistributions in binary form must reproduce the above copyright 00009 * notice, this list of conditions and the following disclaimer in the 00010 * documentation and/or other materials provided with the distribution. 00011 * * Neither the name of the Make, Hack, Void nor the 00012 * names of its contributors may be used to endorse or promote products 00013 * derived from this software without specific prior written permission. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00016 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00017 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00018 * DISCLAIMED. IN NO EVENT SHALL MAKE, HACK, VOID BE LIABLE FOR ANY 00019 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00020 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00021 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00022 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00023 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00024 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00025 */ 00026 00027 #include <stddef.h> 00028 #include <MHV_EEPROM.h> 00029 00033 MHV_EEPROM::MHV_EEPROM() { 00034 _writeAddress = 0; 00035 _writeBuffer = NULL; 00036 _bytesWritten = 0; 00037 _bytesToWrite = 0; 00038 _doneCallback = NULL; 00039 _doneCallbackData = NULL; 00040 } 00041 00047 int16_t MHV_EEPROM::read(uint16_t address) { 00048 if ((EECR & _BV(EEPE)) || !_lock.obtain()) { 00049 return MHV_EEPROM_BUSY; 00050 } 00051 00052 EEAR = address; 00053 EECR |= _BV(EERE); 00054 00055 int16_t val = (int16_t)EEDR; 00056 _lock.release(); 00057 00058 return val; 00059 } 00060 00066 uint8_t MHV_EEPROM::busyRead(uint16_t address) { 00067 int16_t ret; 00068 00069 while (MHV_EEPROM_BUSY == (ret = read(address))) {} 00070 return ret; 00071 } 00072 00079 int8_t MHV_EEPROM::read(void *buffer, uint16_t address, uint16_t length) { 00080 if ((EECR & _BV(EEPE)) || !_lock.obtain()) { 00081 return MHV_EEPROM_BUSY; 00082 } 00083 00084 uint8_t *buf = (uint8_t *)buffer; 00085 00086 for (uint16_t i = 0; i < length; i++) { 00087 EEAR = address + i; 00088 EECR |= _BV(EERE); 00089 buf[i] = EEDR; 00090 } 00091 00092 _lock.release(); 00093 00094 return 0; 00095 } 00096 00103 void MHV_EEPROM::busyRead(void *buffer, uint16_t address, uint16_t length) { 00104 while (MHV_EEPROM_BUSY == (read(buffer, address, length))) {} 00105 } 00106 00113 int8_t MHV_EEPROM::write(uint16_t address, uint8_t data) { 00114 if ((EECR & _BV(EEPE)) || !_lock.obtain()) { 00115 return MHV_EEPROM_BUSY; 00116 } 00117 00118 EEAR = address; 00119 EEDR = data; 00120 EECR = _BV(EEMPE); 00121 EECR = _BV(EEMPE) | _BV(EEPE); 00122 00123 _lock.release(); 00124 00125 return 0; 00126 } 00127 00134 int8_t MHV_EEPROM::busyWrite(void *buffer, uint16_t address, uint16_t length) { 00135 uint8_t *buf = (uint8_t *)buffer; 00136 00137 if ((EECR & _BV(EEPE)) || !_lock.obtain()) { 00138 return MHV_EEPROM_BUSY; 00139 } 00140 00141 for (uint16_t i = 0; i < length; i++) { 00142 EEAR = address + i; 00143 EEDR = buf[i]; 00144 EECR = _BV(EEMPE); 00145 EECR = _BV(EEMPE) | _BV(EEPE); 00146 00147 while (EECR & _BV(EEPE)) {} 00148 } 00149 00150 _lock.release(); 00151 00152 return 0; 00153 } 00154 00155 00164 int8_t MHV_EEPROM::write(void *buffer, uint16_t address, uint16_t length, 00165 void (*doneCallback)(void *buffer, void *data), 00166 void *doneCallbackData) { 00167 if ((EECR & _BV(EEPE)) || !_lock.obtain()) { 00168 return MHV_EEPROM_BUSY; 00169 } 00170 00171 _writeAddress = address; 00172 _writeBuffer = (uint8_t *)buffer; 00173 _bytesWritten = 0; 00174 _bytesToWrite = length; 00175 _doneCallback = doneCallback; 00176 _doneCallbackData = doneCallbackData; 00177 00178 // Start the first write 00179 EEAR = address; 00180 EEDR = ((uint8_t *)buffer)[0]; 00181 EECR = _BV(EEMPE); 00182 00183 // Enable the ready interrupt, further writes will continue in the interrupt handler 00184 EECR = _BV(EEMPE) | _BV(EEPE) | _BV(EERIE); 00185 00186 return 0; 00187 } 00188 00192 void MHV_EEPROM::writeInterrupt() { 00193 if (++_bytesWritten == _bytesToWrite) { 00194 // Done 00195 EECR = 0; 00196 _lock.release(); 00197 00198 if (_doneCallback) { 00199 _doneCallback(_writeBuffer, _doneCallbackData); 00200 } 00201 00202 return; 00203 } 00204 00205 EEAR = _writeAddress + _bytesWritten; 00206 EEDR = _writeBuffer[_bytesWritten]; 00207 EECR = _BV(EEMPE); 00208 // Enable the ready interrupt, further writes will continue in the interrupt handler 00209 EECR = _BV(EEMPE) | _BV(EEPE) | _BV(EERIE); 00210 } 00211 00216 bool MHV_EEPROM::isBusy() { 00217 if ((EECR & _BV(EEPE)) || _lock.check()) { 00218 return MHV_EEPROM_BUSY; 00219 } 00220 00221 return false; 00222 }