Inmiddels een werkende Virtual Memory controller gereed. Werkt prima met I2C ic's. Volgende week krijg ik 2 x SPI 128kb x8 bit ic's binnen. Dan kan ik verder. Op dit moment werkt het met 2 x Adafruit 32kbx8bit FRAM modules.
Er zijn 2 classes.
a) I2CMemory controller:
I2CMemoryController.h
/*
Name: I2CChipController.h
Created: 24-12-2018 12:36:00
Author: nico verduin
Brief: Controller to handle I2C FRAM IC's
*/
#ifndef I2CMEMORYCONTROLLER_H_
#define I2CMEMORYCONTROLLER_H_
// includes
#include <Arduino.h>
#include <Wire.h>
// opcodes used for reading and writing
enum {
READ,
WRITE
};
class I2CMemoryController {
protected:
uint32_t capacity; // contains the capacity of chip memory
char thisI2CAddress; // I2C address of the chip
// functions
public:
I2CMemoryController(uint8_t);
void init();
void processOperation(uint8_t , uint32_t , uint32_t, char *);
uint32_t getCapacity();
};
#endif /* I2C_CHIPCONTROLLER_H_ */
I2CMemoryController.cpp
/*
Name: I2CMemoryController.h
Created: 24-12-2018 12:36:00
Author: nico verduin
Brief: Controller to handle I2C FRAM IC's
*/
#include "I2CMemoryController.h"
/**
* @name I2CMemoryController
* @param uint8_t I2C address of chip
* @brief Constructor
*/
I2CMemoryController::I2CMemoryController(uint8_t address) {
// save this chip's address
thisI2CAddress = address;
// initialize other parameters
capacity = 0;
}
/**
* @name init
* @brief Initializes the chip by determining how much memory the chip
* contains.
*/
void I2CMemoryController::init() {
// determine memory capacity of the chip
// put a 0x00 on address 0
Wire.beginTransmission(thisI2CAddress);
Wire.write(0);
Wire.write(0);
Wire.write(0x00);
Wire.endTransmission();
// now put on every power of 2 address an 0xFF
// we can handle a max of 2 GigaBytes
uint32_t i = 1;
// once i = 0 we have looped through 2 Gigabytes address space
while (i != 0){
// write our 0xFF
Wire.beginTransmission(thisI2CAddress);
Wire.write(i >> 8);
Wire.write(i & 0xFF);
Wire.write(0xFF);
Wire.endTransmission();
// assuming the memory capacity is a factor of 2^n, we will reach a loop
// around to address 0. So if we have written a 0xFF on address 0x0000,
// i contains the max capacity of the chip. And we are done searching for
// the capacity
Wire.beginTransmission(thisI2CAddress);
Wire.write(0x00);
Wire.write(0x00);
Wire.endTransmission();
// ask for our byte
Wire.requestFrom(thisI2CAddress, 1, true);
uint8_t result = Wire.read();
// check if wrap around
if (result == 0xFF) {
// save capacity
capacity = i;
// if there is no chip, Wire returns a 0xFF. This will happen
// on the first value of i (which is 1). Thus we need to
// subtract 1 from the capacity to return 0 bytes capacity
if (capacity == 1) {
// no chip recognized on this address
capacity = 0;
}
// loop is finished
break;
}
// i * 2
i = i << 1;
}
}
/**
* processOperation
* @param opcode operation type (READ or WRITE)
* @param char * pointer to where data is read from or sent to
* @brief reads or write a block from/to chip to/from local
* memory
*/
void I2CMemoryController::processOperation( uint8_t opcode,
uint32_t addressPtr,
uint32_t blockSize,
char * ptr) {
char bufferCtr = 0; // max 32 bytes counter
// process the whole block within this chip
while (blockSize != 0UL) {
// if the buffer is empty we need to setup the chip
if (bufferCtr == 0UL) {
// setup start address
Wire.beginTransmission(thisI2CAddress);
// set our address within the chip
Wire.write(addressPtr >> 8);
Wire.write(addressPtr & 0xFF);
// determine the size of our I2C buffer to use
if (opcode == READ) {
if (blockSize > BUFFER_LENGTH) {
bufferCtr = BUFFER_LENGTH;
} else {
bufferCtr = blockSize;
}
// close transmission
Wire.endTransmission();
// ask for our bytes.
Wire.requestFrom(thisI2CAddress, bufferCtr, true);
}
// for Writing we are already using 2 bytes of the buffer
// for the memory address
if (opcode == WRITE) {
if (blockSize > (BUFFER_LENGTH - 2)) {
bufferCtr = BUFFER_LENGTH - 2;
} else {
bufferCtr = blockSize;
}
}
}
// decrease total to transfer bytes in advance and increase
// address Pointer
blockSize -= bufferCtr;
addressPtr += bufferCtr;
// process bufferCnt number of bytes
while (bufferCtr != 0UL){
if (opcode == READ){
if (Wire.available()) {
*ptr = Wire.read();
ptr++;
bufferCtr--;
}
}
if (opcode == WRITE){
Wire.write(*ptr);
ptr++;
bufferCtr--;
}
}
// I2C command at end of writing
if (opcode == WRITE){
// close transmission
Wire.endTransmission();
}
}
}
/*
* @name getCapacity
* @return uint32_t capacity of the chip
* @brief returns the chip memory capacity
*/
uint32_t I2CMemoryController::getCapacity() {
return capacity;
}