mirror of
https://bitbucket.org/myhomie/mycorerepository.git
synced 2025-12-06 09:41:19 +00:00
200 lines
4.9 KiB
C++
200 lines
4.9 KiB
C++
#include "Arduino.h"
|
|
#include "RfidDb.h"
|
|
|
|
// Magic number to verify RFID database in EEPROM
|
|
#define RFID_DB_MAGIC 0x75
|
|
|
|
// returns the EEPROM location of the number of items in the database
|
|
#define countOffset() (_eepromOffset + 1)
|
|
|
|
// returns the EEPROM location of the first id in the database
|
|
#define firstIdOffset() (countOffset() + 1)
|
|
|
|
// returns the EEPROM location of the Ith id in the database
|
|
#define idOffset(I) (firstIdOffset() + ((I) * sizeof(uint32_t)))
|
|
|
|
// returns the EEPROM location of the first name in the database
|
|
#define firstNameOffset() (idOffset(_maxSize))
|
|
|
|
// returns the EEPROM location of the Ith name in the database
|
|
#define nameOffset(I) (firstNameOffset() + (I) * _maxNameLength)
|
|
|
|
RfidDb::RfidDb(uint8_t maxSize, uint16_t eepromOffset) {
|
|
init(maxSize, eepromOffset, 0);
|
|
}
|
|
|
|
RfidDb::RfidDb(uint8_t maxSize, uint16_t eepromOffset, uint8_t maxNameLength) {
|
|
init(maxSize, eepromOffset, maxNameLength);
|
|
}
|
|
|
|
void RfidDb::begin() {
|
|
if (!hasMagic()) {
|
|
initDb();
|
|
}
|
|
}
|
|
|
|
uint8_t RfidDb::maxSize() {
|
|
return _maxSize;
|
|
}
|
|
|
|
uint8_t RfidDb::maxNameLength() {
|
|
return _maxNameLength;
|
|
}
|
|
|
|
uint8_t RfidDb::count() {
|
|
return EEPROM.read(countOffset());
|
|
}
|
|
|
|
bool RfidDb::insert(uint32_t id) {
|
|
return insert(id, "");
|
|
}
|
|
|
|
bool RfidDb::insert(uint32_t id, const char* name) {
|
|
// if already exists in the database, we update the name
|
|
int16_t pos = posOf(id);
|
|
if (pos != -1) {
|
|
writeName(pos, name);
|
|
return true;
|
|
}
|
|
uint8_t c = count();
|
|
// no room in database, return false
|
|
if (c >= _maxSize) {
|
|
return false;
|
|
}
|
|
// we know there is room for the id, write in last position and update count
|
|
writeId(c, id);
|
|
writeName(c, name);
|
|
EEPROM.write(countOffset(), c + 1);
|
|
return true;
|
|
}
|
|
|
|
void RfidDb::remove(uint32_t id) {
|
|
uint8_t originalCount = count();
|
|
if (originalCount == 0) {
|
|
return;
|
|
}
|
|
int16_t posToRemove = posOf(id);
|
|
if (posToRemove == -1) {
|
|
return;
|
|
}
|
|
uint8_t newCount = originalCount - 1;
|
|
if (newCount > 0 || newCount == posToRemove) {
|
|
uint32_t idToMove = getId(newCount);
|
|
writeId(posToRemove, idToMove);
|
|
copyName(newCount, posToRemove);
|
|
}
|
|
EEPROM.write(countOffset(), newCount);
|
|
}
|
|
|
|
bool RfidDb::getId(uint8_t pos, uint32_t &id) {
|
|
if (pos >= count()) {
|
|
return false;
|
|
}
|
|
id = getId(pos);
|
|
return true;
|
|
}
|
|
|
|
bool RfidDb::getName(uint8_t pos, char* name) {
|
|
if (pos >= count() || _maxNameLength == 0) {
|
|
return false;
|
|
}
|
|
uint16_t base = nameOffset(pos);
|
|
for (int i = 0; i < _maxNameLength; i++) {
|
|
name[i] = EEPROM.read(base + i);
|
|
if (name[i] == '\0') {
|
|
break;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool RfidDb::contains(uint32_t id) {
|
|
return posOf(id) != -1;
|
|
}
|
|
|
|
bool RfidDb::contains24(uint32_t id) {
|
|
return posOf24(id) != -1;
|
|
}
|
|
|
|
// Returns the position of the given id in the database or -1 if the id is
|
|
// not in the database
|
|
int16_t RfidDb::posOf(uint32_t id) {
|
|
return posOf(id, 0xFFFFFFFF);
|
|
}
|
|
|
|
// Returns the position of the given id in the database when compared on the
|
|
// low 24 bits of the id.
|
|
int16_t RfidDb::posOf24(uint32_t id) {
|
|
return posOf(id, 0x00FFFFFF);
|
|
}
|
|
|
|
// Returns the position of the given id when compared with ids in the datbase
|
|
// after both the database id and the given id are bit masked with the given
|
|
// mask
|
|
int16_t RfidDb::posOf(uint32_t id, uint32_t mask) {
|
|
uint32_t maskedId = id & mask;
|
|
for (uint8_t i = 0, n = count(); i < n; i++) {
|
|
if (maskedId == (getId(i) & mask)) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// Returns the id at the given position
|
|
uint32_t RfidDb::getId(uint8_t pos) {
|
|
uint32_t id;
|
|
EEPROM.get(idOffset(pos), id);
|
|
return id;
|
|
}
|
|
|
|
// Writes an id to the database at a given position
|
|
inline void RfidDb::writeId(uint8_t pos, uint32_t id) {
|
|
EEPROM.put(idOffset(pos), id);
|
|
}
|
|
|
|
// Writes a name to the database at a given position
|
|
void RfidDb::writeName(uint8_t pos, const char* name) {
|
|
if (_maxNameLength > 0) {
|
|
uint8_t base = nameOffset(pos);
|
|
for (int i = 0; i < _maxNameLength - 1; i++) {
|
|
EEPROM.write(base + i, name[i]);
|
|
}
|
|
// Ensure we null terminate
|
|
EEPROM.write(base + _maxNameLength - 1, '\0');
|
|
}
|
|
}
|
|
|
|
void RfidDb::copyName(uint8_t srcPos, uint8_t destPos) {
|
|
if (_maxNameLength > 0) {
|
|
uint16_t srcbase = nameOffset(srcPos);
|
|
uint16_t destBase = nameOffset(destPos);
|
|
for (int i = 0; i < _maxNameLength; i++) {
|
|
char c = EEPROM.read(srcbase + i);
|
|
EEPROM.write(destBase + i, c);
|
|
if (c == '\0') {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Returns whether the EEPROM location at the EEPROM base address
|
|
// contains the magic number
|
|
bool RfidDb::hasMagic() {
|
|
return EEPROM.read(_eepromOffset) == RFID_DB_MAGIC;
|
|
}
|
|
|
|
// Initialises the database by writing the magic number to the base
|
|
// EEPROM address, followed by a zero count.
|
|
void RfidDb::initDb() {
|
|
EEPROM.write(_eepromOffset, RFID_DB_MAGIC);
|
|
EEPROM.write(countOffset(), 0);
|
|
}
|
|
|
|
void RfidDb::init(uint8_t maxSize, uint16_t eepromOffset, uint8_t maxNameLength) {
|
|
_maxSize = maxSize;
|
|
_eepromOffset = eepromOffset;
|
|
_maxNameLength = maxNameLength;
|
|
}
|