Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
### Added
- Add `__AVR__` to defines when compiling
- Support for mock EEPROM (but only if board supports it)

### Changed
- Move repository from https://github.com/ianfixes/arduino_ci to https://github.com/Arduino-CI/arduino_ci
Expand Down
37 changes: 37 additions & 0 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -581,3 +581,40 @@ unittest(spi) {
assertEqual("LMNOe", String(inBuf));
}
```

### EEPROM

`EEPROM` is a global with a simple API to read and write bytes to persistent memory (like a tiny hard disk) given an `int` location. Since the Arduino core already provides this as a global, and the core API is sufficient for basic testing (read/write), there is no direct tie to the `GODMODE` API. (If you need more, such as a log of intermediate values, enter a feature request.)

```C++
unittest(eeprom)
{
uint8_t a;
// size
assertEqual(EEPROM_SIZE, EEPROM.length());
// initial values
a = EEPROM.read(0);
assertEqual(255, a);
// write and read
EEPROM.write(0, 24);
a = EEPROM.read(0);
assertEqual(24, a);
// update
EEPROM.write(1, 14);
EEPROM.update(1, 22);
a = EEPROM.read(1);
assertEqual(22, a);
// put and get
const float f1 = 0.025f;
float f2 = 0.0f;
EEPROM.put(5, f1);
assertEqual(0.0f, f2);
EEPROM.get(5, f2);
assertEqual(0.025f, f2);
// array access
int val = 10;
EEPROM[2] = val;
a = EEPROM[2];
assertEqual(10, a);
}
```
78 changes: 78 additions & 0 deletions SampleProjects/TestSomething/test/eeprom.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include <ArduinoUnitTests.h>
#include <Arduino.h>

// Only run EEPROM tests if there is hardware support!
#if defined(EEPROM_SIZE) || (defined(E2END) && E2END)
#include <EEPROM.h>

GodmodeState* state = GODMODE();
unittest_setup()
{
state->reset();
}

unittest(length)
{
assertEqual(EEPROM_SIZE, EEPROM.length());
}

unittest(firstRead)
{
uint8_t a = EEPROM.read(0);
assertEqual(255, a);
}

unittest(writeRead)
{
EEPROM.write(0, 24);
uint8_t a = EEPROM.read(0);
assertEqual(24, a);

EEPROM.write(0, 128);
a = EEPROM.read(0);
assertEqual(128, a);

EEPROM.write(0, 256);
a = EEPROM.read(0);
assertEqual(0, a);

int addr = EEPROM_SIZE / 2;
EEPROM.write(addr, 63);
a = EEPROM.read(addr);
assertEqual(63, a);

addr = EEPROM_SIZE - 1;
EEPROM.write(addr, 188);
a = EEPROM.read(addr);
assertEqual(188, a);
}

unittest(updateWrite)
{
EEPROM.write(1, 14);
EEPROM.update(1, 22);
uint8_t a = EEPROM.read(1);
assertEqual(22, a);
}

unittest(putGet)
{
const float f1 = 0.025f;
float f2 = 0.0f;
EEPROM.put(5, f1);
assertEqual(0.0f, f2);
EEPROM.get(5, f2);
assertEqual(0.025f, f2);
}

unittest(array)
{
int val = 10;
EEPROM[2] = val;
uint8_t a = EEPROM[2];
assertEqual(10, a);
}

#endif

unittest_main()
166 changes: 166 additions & 0 deletions cpp/arduino/EEPROM.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/*
EEPROM.h - EEPROM library
Original Copyright (c) 2006 David A. Mellis. All right reserved.
New version by Christopher Andrews 2015.
Copy of https://github.com/arduino/ArduinoCore-megaavr/blob/c8a1dd996c783777ec46167cfd8ad3fd2e6df185/libraries/EEPROM/src/EEPROM.h
modified by James Foster in 2020 to work with Arduino CI.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef EEPROM_h
#define EEPROM_h

#include <inttypes.h>
#include <avr/io.h>

// different EEPROM implementations have different macros that leak out
#if !defined(EEPROM_SIZE) && defined(E2END) && (E2END)
#define EEPROM_SIZE (E2END + 1)
#endif

// Does the current board have EEPROM?
#ifndef EEPROM_SIZE
// In lieu of an "EEPROM.h not found" error for unsupported boards
#error "EEPROM library not available for your board"
#endif

// On a real device this would be in hardware, but we have a mock board!
static uint8_t eeprom[EEPROM_SIZE];
inline uint8_t eeprom_read_byte( uint8_t* index ) { return eeprom[(unsigned long) index % EEPROM_SIZE]; }
inline void eeprom_write_byte( uint8_t* index, uint8_t value ) { eeprom[(unsigned long) index % EEPROM_SIZE] = value; }

// Everything following is from the original (referenced above)

/***
EERef class.
This object references an EEPROM cell.
Its purpose is to mimic a typical byte of RAM, however its storage is the EEPROM.
This class has an overhead of two bytes, similar to storing a pointer to an EEPROM cell.
***/

struct EERef{

EERef( const int index )
: index( index ) {}

//Access/read members.
uint8_t operator*() const { return eeprom_read_byte( (uint8_t*) index ); }
operator uint8_t() const { return **this; }

//Assignment/write members.
EERef &operator=( const EERef &ref ) { return *this = *ref; }
EERef &operator=( uint8_t in ) { return eeprom_write_byte( (uint8_t*) index, in ), *this; }
EERef &operator +=( uint8_t in ) { return *this = **this + in; }
EERef &operator -=( uint8_t in ) { return *this = **this - in; }
EERef &operator *=( uint8_t in ) { return *this = **this * in; }
EERef &operator /=( uint8_t in ) { return *this = **this / in; }
EERef &operator ^=( uint8_t in ) { return *this = **this ^ in; }
EERef &operator %=( uint8_t in ) { return *this = **this % in; }
EERef &operator &=( uint8_t in ) { return *this = **this & in; }
EERef &operator |=( uint8_t in ) { return *this = **this | in; }
EERef &operator <<=( uint8_t in ) { return *this = **this << in; }
EERef &operator >>=( uint8_t in ) { return *this = **this >> in; }

EERef &update( uint8_t in ) { return in != *this ? *this = in : *this; }

/** Prefix increment/decrement **/
EERef& operator++() { return *this += 1; }
EERef& operator--() { return *this -= 1; }

/** Postfix increment/decrement **/
uint8_t operator++ (int){
uint8_t ret = **this;
return ++(*this), ret;
}

uint8_t operator-- (int){
uint8_t ret = **this;
return --(*this), ret;
}

int index; //Index of current EEPROM cell.
};

/***
EEPtr class.
This object is a bidirectional pointer to EEPROM cells represented by EERef objects.
Just like a normal pointer type, this can be dereferenced and repositioned using
increment/decrement operators.
***/

struct EEPtr{

EEPtr( const int index )
: index( index ) {}

operator int() const { return index; }
EEPtr &operator=( int in ) { return index = in, *this; }

//Iterator functionality.
bool operator!=( const EEPtr &ptr ) { return index != ptr.index; }
EERef operator*() { return index; }

/** Prefix & Postfix increment/decrement **/
EEPtr& operator++() { return ++index, *this; }
EEPtr& operator--() { return --index, *this; }
EEPtr operator++ (int) { return index++; }
EEPtr operator-- (int) { return index--; }

int index; //Index of current EEPROM cell.
};

/***
EEPROMClass class.
This object represents the entire EEPROM space.
It wraps the functionality of EEPtr and EERef into a basic interface.
This class is also 100% backwards compatible with earlier Arduino core releases.
***/

struct EEPROMClass{

//Basic user access methods.
EERef operator[]( const int idx ) { return idx; }
uint8_t read( int idx ) { return EERef( idx ); }
void write( int idx, uint8_t val ) { (EERef( idx )) = val; }
void update( int idx, uint8_t val ) { EERef( idx ).update( val ); }

//STL and C++11 iteration capability.
EEPtr begin() { return 0x00; }
EEPtr end() { return length(); } //Standards requires this to be the item after the last valid entry. The returned pointer is invalid.
uint16_t length() { return EEPROM_SIZE; }

//Functionality to 'get' and 'put' objects to and from EEPROM.
template< typename T > T &get( int idx, T &t ){
EEPtr e = idx;
uint8_t *ptr = (uint8_t*) &t;
for( int count = sizeof(T) ; count ; --count, ++e ) *ptr++ = *e;
return t;
}

template< typename T > const T &put( int idx, const T &t ){
EEPtr e = idx;
const uint8_t *ptr = (const uint8_t*) &t;
for( int count = sizeof(T) ; count ; --count, ++e ) (*e).update( *ptr++ );
return t;
}
};

static EEPROMClass EEPROM;
#endif
8 changes: 8 additions & 0 deletions cpp/arduino/Godmode.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <avr/io.h>
#include "WString.h"
#include "PinHistory.h"
#include "EEPROM.h"

// random
void randomSeed(unsigned long seed);
Expand Down Expand Up @@ -87,12 +88,19 @@ class GodmodeState {
spi.readDelayMicros = 0;
}

void resetEEPROM() {
for(int i = 0; i < EEPROM.length(); ++i){
EEPROM.update(i, 255);
}
}

void reset() {
resetClock();
resetPins();
resetInterrupts();
resetPorts();
resetSPI();
resetEEPROM();
seed = 1;
}

Expand Down