Smart-Home am Beispiel der Präsenzerkennung im Raum Projektarbeit Lennart Heimbs, Johannes Krug, Sebastian Dohle und Kevin Holzschuh bei Prof. Oliver Hofmann SS2019
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

extEEPROM.cpp 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*-----------------------------------------------------------------------------*
  2. * extEEPROM.cpp - Arduino library to support external I2C EEPROMs. *
  3. * *
  4. * This library will work with most I2C serial EEPROM chips between 2k bits *
  5. * and 2048k bits (2M bits) in size. Multiple EEPROMs on the bus are supported *
  6. * as a single address space. I/O across block, page and device boundaries *
  7. * is supported. Certain assumptions are made regarding the EEPROM *
  8. * device addressing. These assumptions should be true for most EEPROMs *
  9. * but there are exceptions, so read the datasheet and know your hardware. *
  10. * *
  11. * The library should also work for EEPROMs smaller than 2k bits, assuming *
  12. * that there is only one EEPROM on the bus and also that the user is careful *
  13. * to not exceed the maximum address for the EEPROM. *
  14. * *
  15. * Library tested with: *
  16. * Microchip 24AA02E48 (2k bit) *
  17. * 24xx32 (32k bit, thanks to Richard M) *
  18. * Microchip 24LC256 (256k bit) *
  19. * Microchip 24FC1026 (1M bit, thanks to Gabriele B on the Arduino forum) *
  20. * ST Micro M24M02 (2M bit) *
  21. * *
  22. * Library will NOT work with Microchip 24xx1025 as its control byte does not *
  23. * conform to the following assumptions. *
  24. * *
  25. * Device addressing assumptions: *
  26. * 1. The I2C address sequence consists of a control byte followed by one *
  27. * address byte (for EEPROMs <= 16k bits) or two address bytes (for *
  28. * EEPROMs > 16k bits). *
  29. * 2. The three least-significant bits in the control byte (excluding the R/W *
  30. * bit) comprise the three most-significant bits for the entire address *
  31. * space, i.e. all chips on the bus. As such, these may be chip-select *
  32. * bits or block-select bits (for individual chips that have an internal *
  33. * block organization), or a combination of both (in which case the *
  34. * block-select bits must be of lesser significance than the chip-select *
  35. * bits). *
  36. * 3. Regardless of the number of bits needed to address the entire address *
  37. * space, the three most-significant bits always go in the control byte. *
  38. * Depending on EEPROM device size, this may result in one or more of the *
  39. * most significant bits in the I2C address bytes being unused (or "don't *
  40. * care"). *
  41. * 4. An EEPROM contains an integral number of pages. *
  42. * *
  43. * To use the extEEPROM library, the Arduino Wire library must also *
  44. * be included. *
  45. * *
  46. * Jack Christensen 23Mar2013 v1 *
  47. * 29Mar2013 v2 - Updated to span page boundaries (and therefore also *
  48. * device boundaries, assuming an integral number of pages per device) *
  49. * 08Jul2014 v3 - Generalized for 2kb - 2Mb EEPROMs. *
  50. * *
  51. * Paolo Paolucci 22-10-2015 v3.1 *
  52. * 09-01-2016 v3.2 Add update function. *
  53. * *
  54. * External EEPROM Library by Jack Christensen is licensed under CC BY-SA 4.0, *
  55. * http://creativecommons.org/licenses/by-sa/4.0/ *
  56. *-----------------------------------------------------------------------------*/
  57. #include "extEEPROM.h"
  58. // workaround, BUFFER_LENGTH is not defined in Wire.h for SAMD controllers
  59. #ifndef BUFFER_LENGTH
  60. #define BUFFER_LENGTH 32
  61. #endif
  62. // Constructor.
  63. // - deviceCapacity is the capacity of a single EEPROM device in
  64. // kilobits (kb) and should be one of the values defined in the
  65. // eeprom_size_t enumeration in the extEEPROM.h file. (Most
  66. // EEPROM manufacturers use kbits in their part numbers.)
  67. // - nDevice is the number of EEPROM devices on the I2C bus (all must
  68. // be identical).
  69. // - pageSize is the EEPROM's page size in bytes.
  70. // - eepromAddr is the EEPROM's I2C address and defaults to 0x50 which is common.
  71. extEEPROM::extEEPROM(eeprom_size_t deviceCapacity, byte nDevice, unsigned int pageSize,
  72. uint8_t eepromAddr)
  73. {
  74. communication = NULL;
  75. _dvcCapacity = deviceCapacity;
  76. _nDevice = nDevice;
  77. _pageSize = pageSize;
  78. _eepromAddr = eepromAddr;
  79. _totalCapacity = _nDevice * _dvcCapacity * 1024UL / 8;
  80. _nAddrBytes = deviceCapacity > kbits_16 ? 2 :
  81. 1; //two address bytes needed for eeproms > 16kbits
  82. //determine the bitshift needed to isolate the chip select bits from the address to put into the control byte
  83. uint16_t kb = _dvcCapacity;
  84. if ( kb <= kbits_16 ) {
  85. _csShift = 8;
  86. } else if ( kb >= kbits_512 ) {
  87. _csShift = 16;
  88. } else {
  89. kb >>= 6;
  90. _csShift = 12;
  91. while ( kb >= 1 ) {
  92. ++_csShift;
  93. kb >>= 1;
  94. }
  95. }
  96. }
  97. //initialize the I2C bus and do a dummy write (no data sent)
  98. //to the device so that the caller can determine whether it is responding.
  99. //when using a 400kHz bus speed and there are multiple I2C devices on the
  100. //bus (other than EEPROM), call extEEPROM::begin() after any initialization
  101. //calls for the other devices to ensure the intended I2C clock speed is set.
  102. byte extEEPROM::begin(twiClockFreq_t twiFreq, TwoWire *_comm)
  103. {
  104. communication = _comm;
  105. communication->begin();
  106. communication->setClock(twiFreq);
  107. communication->beginTransmission(_eepromAddr);
  108. if (_nAddrBytes == 2) {
  109. communication->write((byte)0); //high addr byte
  110. }
  111. communication->write((byte)0); //low addr byte
  112. return communication->endTransmission();
  113. }
  114. //Write bytes to external EEPROM.
  115. //If the I/O would extend past the top of the EEPROM address space,
  116. //a status of EEPROM_ADDR_ERR is returned. For I2C errors, the status
  117. //from the Arduino Wire library is passed back through to the caller.
  118. byte extEEPROM::write(unsigned long addr, byte *values, unsigned int nBytes)
  119. {
  120. uint8_t txStatus = 0; //transmit status
  121. if (addr + nBytes > _totalCapacity) { //will this write go past the top of the EEPROM?
  122. return EEPROM_ADDR_ERR; //yes, tell the caller
  123. }
  124. while (nBytes > 0) {
  125. const uint16_t nPage = _pageSize - ( addr & (_pageSize - 1) );
  126. //find min(nBytes, nPage, BUFFER_LENGTH) -- BUFFER_LENGTH is defined in the Wire library.
  127. uint16_t nWrite = nBytes < nPage ? nBytes : nPage;
  128. nWrite = BUFFER_LENGTH - _nAddrBytes < nWrite ? BUFFER_LENGTH - _nAddrBytes : nWrite;
  129. const uint8_t ctrlByte = _eepromAddr | (byte) (addr >> _csShift);
  130. communication->beginTransmission(ctrlByte);
  131. if (_nAddrBytes == 2) {
  132. communication->write( (byte) (addr >> 8) ); //high addr byte
  133. }
  134. communication->write( (byte) addr ); //low addr byte
  135. communication->write(values, nWrite);
  136. txStatus = communication->endTransmission();
  137. if (txStatus != 0) {
  138. return txStatus;
  139. }
  140. //wait up to 50ms for the write to complete
  141. for (uint8_t i=100; i; --i) {
  142. delayMicroseconds(500); //no point in waiting too fast
  143. communication->beginTransmission(ctrlByte);
  144. if (_nAddrBytes == 2) {
  145. communication->write((byte)0); //high addr byte
  146. }
  147. communication->write((byte)0); //low addr byte
  148. txStatus = communication->endTransmission();
  149. if (txStatus == 0) {
  150. break;
  151. }
  152. }
  153. if (txStatus != 0) {
  154. return txStatus;
  155. }
  156. addr += nWrite; //increment the EEPROM address
  157. values += nWrite; //increment the input data pointer
  158. nBytes -= nWrite; //decrement the number of bytes left to write
  159. }
  160. return txStatus;
  161. }
  162. //Read bytes from external EEPROM.
  163. //If the I/O would extend past the top of the EEPROM address space,
  164. //a status of EEPROM_ADDR_ERR is returned. For I2C errors, the status
  165. //from the Arduino Wire library is passed back through to the caller.
  166. byte extEEPROM::read(unsigned long addr, byte *values, unsigned int nBytes)
  167. {
  168. if (addr + nBytes > _totalCapacity) { //will this read take us past the top of the EEPROM?
  169. return EEPROM_ADDR_ERR; //yes, tell the caller
  170. }
  171. while (nBytes > 0) {
  172. const uint16_t nPage = _pageSize - ( addr & (_pageSize - 1) );
  173. uint16_t nRead = nBytes < nPage ? nBytes : nPage;
  174. nRead = BUFFER_LENGTH < nRead ? BUFFER_LENGTH : nRead;
  175. byte ctrlByte = _eepromAddr | (byte) (addr >> _csShift);
  176. communication->beginTransmission(ctrlByte);
  177. if (_nAddrBytes == 2) {
  178. communication->write( (byte) (addr >> 8) ); //high addr byte
  179. }
  180. communication->write( (byte) addr ); //low addr byte
  181. const byte rxStatus = communication->endTransmission();
  182. if (rxStatus != 0) {
  183. return rxStatus; //read error
  184. }
  185. communication->requestFrom(ctrlByte, nRead);
  186. for (byte i=0; i<nRead; i++) {
  187. values[i] = communication->read();
  188. }
  189. addr += nRead; //increment the EEPROM address
  190. values += nRead; //increment the input data pointer
  191. nBytes -= nRead; //decrement the number of bytes left to write
  192. }
  193. return 0;
  194. }
  195. //Write a single byte to external EEPROM.
  196. //If the I/O would extend past the top of the EEPROM address space,
  197. //a status of EEPROM_ADDR_ERR is returned. For I2C errors, the status
  198. //from the Arduino Wire library is passed back through to the caller.
  199. byte extEEPROM::write(unsigned long addr, byte value)
  200. {
  201. return write(addr, &value, 1);
  202. }
  203. //Read a single byte from external EEPROM.
  204. //If the I/O would extend past the top of the EEPROM address space,
  205. //a status of EEPROM_ADDR_ERR is returned. For I2C errors, the status
  206. //from the Arduino Wire library is passed back through to the caller.
  207. //To distinguish error values from valid data, error values are returned as negative numbers.
  208. int extEEPROM::read(unsigned long addr)
  209. {
  210. uint8_t data;
  211. int ret;
  212. ret = read(addr, &data, 1);
  213. return ret == 0 ? data : -ret;
  214. }
  215. //Update bytes to external EEPROM.
  216. //For I2C errors, the status from the Arduino Wire library is passed back through to the caller.
  217. byte extEEPROM::update(unsigned long addr, byte *values, unsigned int nBytes)
  218. {
  219. for (unsigned int i = 0; i < nBytes; i++) {
  220. const uint8_t newValue = values[i];
  221. if (newValue != read(addr + i)) {
  222. write(addr + i, newValue);
  223. }
  224. }
  225. return true;
  226. }
  227. //Update a single byte to external EEPROM.
  228. //For I2C errors, the status from the Arduino Wire library is passed back through to the caller.
  229. byte extEEPROM::update(unsigned long addr, byte value)
  230. {
  231. return (value != read(addr) ? write(addr, &value, 1) : 0);
  232. }
  233. //For I2C errors, the status from the Arduino Wire library is passed back through to the caller.
  234. unsigned long extEEPROM::length( void )
  235. {
  236. return _totalCapacity * 8;
  237. }