Skip to content
This repository was archived by the owner on Aug 19, 2023. It is now read-only.

Commit bc4103a

Browse files
committed
Added Adafruit SPI FRAM rewrite
1 parent b4956e1 commit bc4103a

File tree

3 files changed

+282
-0
lines changed

3 files changed

+282
-0
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
//
2+
// Nexus_FRAM_SPI.h
3+
//
4+
5+
#include <Arduino.h>
6+
#include <SPI.h>
7+
8+
namespace Nexus {
9+
10+
//
11+
// class SPI_Base
12+
//
13+
14+
// Bit-banging implementation
15+
16+
template<uint8_t CS_Pin, uint8_t CLK_Pin, uint8_t MISO_Pin, uint8_t MOSI_Pin>
17+
class SPI_Base {
18+
19+
public:
20+
21+
void initialize()
22+
{
23+
pinMode(CLK_Pin, OUTPUT);
24+
pinMode(MOSI_Pin, OUTPUT);
25+
pinMode(MISO_Pin, INPUT);
26+
}
27+
28+
uint8_t transfer(uint8_t data)
29+
{
30+
uint8_t reply = 0;
31+
32+
for (int i = 7; i >= 0; --i)
33+
{
34+
reply <<= 1;
35+
36+
digitalWrite(CLK_Pin, LOW);
37+
digitalWrite(MOSI_Pin, data & (1 << i));
38+
digitalWrite(CLK_Pin, HIGH);
39+
40+
if (digitalRead(MISO_Pin))
41+
reply |= 1;
42+
}
43+
44+
return reply;
45+
}
46+
47+
};
48+
49+
// Hardware SPI specialization
50+
51+
template<uint8_t CS_Pin>
52+
class SPI_Base<CS_Pin, -1, -1, -1> {
53+
54+
public:
55+
56+
void initialize()
57+
{
58+
SPI.begin();
59+
60+
#ifdef __SAM3X8E__
61+
SPI.setClockDivider (9); // 9.3 MHz
62+
#else
63+
SPI.setClockDivider (SPI_CLOCK_DIV2); // 8 MHz
64+
#endif
65+
66+
SPI.setDataMode(SPI_MODE0);
67+
}
68+
69+
uint8_t transfer(uint8_t byte)
70+
{
71+
return SPI.transfer(byte);
72+
};
73+
74+
};
75+
76+
//
77+
// class FRAM_SPI
78+
//
79+
80+
template<uint8_t CS_Pin, uint8_t CLK_Pin = -1, uint8_t MISO_Pin = -1, uint8_t MOSI_Pin = -1>
81+
class FRAM_SPI : public SPI_Base<CS_Pin, CLK_Pin, MISO_Pin, MOSI_Pin> {
82+
83+
public:
84+
85+
enum Opcodes
86+
{
87+
Opcode_WREN = 0b0110, /* Write Enable Latch */
88+
Opcode_WRDI = 0b0100, /* Reset Write Enable Latch */
89+
Opcode_RDSR = 0b0101, /* Read Status Register */
90+
Opcode_WRSR = 0b0001, /* Write Status Register */
91+
Opcode_READ = 0b0011, /* Read Memory */
92+
Opcode_WRITE = 0b0010, /* Write Memory */
93+
Opcode_RDID = 0b10011111 /* Read Device ID */
94+
};
95+
96+
FRAM_SPI() : SPI_Base<CS_Pin, CLK_Pin, MISO_Pin, MOSI_Pin>(),
97+
_initialized(false)
98+
{ }
99+
100+
// Initialize pins and SPI
101+
102+
void begin();
103+
104+
// Read and write to memory
105+
106+
void write(uint16_t addr, uint8_t data);
107+
uint8_t read(uint16_t addr);
108+
109+
// Get the device identifier
110+
111+
void getDeviceID(uint8_t *mfgID, uint16_t *prodID);
112+
113+
// Get and set the status register
114+
115+
uint8_t getStatusRegister();
116+
void setStatusRegister(uint8_t reg);
117+
118+
private:
119+
120+
bool _initialized;
121+
122+
};
123+
124+
}
125+
126+
#include "Nexus_FRAM_SPI.hpp"
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
//
2+
// Nexus_FRAM_SPI.cpp
3+
//
4+
5+
namespace Nexus {
6+
7+
//
8+
// class FRAM_SPI
9+
//
10+
11+
// Initialize pins and SPI
12+
13+
template<uint8_t CS_Pin, uint8_t CLK_Pin, uint8_t MISO_Pin, uint8_t MOSI_Pin>
14+
void FRAM_SPI<CS_Pin, CLK_Pin, MISO_Pin, MOSI_Pin>::begin()
15+
{
16+
pinMode(CS_Pin, OUTPUT);
17+
digitalWrite(CS_Pin, HIGH);
18+
19+
this->initialize();
20+
21+
uint8_t mfgID; uint16_t prodID;
22+
getDeviceID(&mfgID, &prodID);
23+
24+
if (mfgID != 0x04 || prodID != 0x0302)
25+
{
26+
return false;
27+
}
28+
29+
return _initialized = true;
30+
}
31+
32+
// Read and write to memory
33+
34+
template<uint8_t CS_Pin, uint8_t CLK_Pin, uint8_t MISO_Pin, uint8_t MOSI_Pin>
35+
void FRAM_SPI<CS_Pin, CLK_Pin, MISO_Pin, MOSI_Pin>::write(uint16_t addr, uint8_t data)
36+
{
37+
digitalWrite(CS_Pin, LOW);
38+
39+
this->transfer(Opcode_WRITE);
40+
this->transfer(highByte(addr)); // (uint8_t)(addr >> 8 & 0xFF)
41+
this->transfer(lowByte(addr)); // (uint8_t)(addr >> 0 & 0xFF)
42+
this->transfer(data);
43+
44+
digitalWrite(CS_Pin, HIGH);
45+
}
46+
47+
template<uint8_t CS_Pin, uint8_t CLK_Pin, uint8_t MISO_Pin, uint8_t MOSI_Pin>
48+
uint8_t FRAM_SPI<CS_Pin, CLK_Pin, MISO_Pin, MOSI_Pin>::read(uint16_t addr)
49+
{
50+
digitalWrite(CS_Pin, LOW);
51+
52+
this->transfer(Opcode_READ);
53+
this->transfer(highByte(addr));
54+
this->transfer(lowByte(addr));
55+
uint8_t data = this->transfer(0);
56+
57+
digitalWrite(CS_Pin, HIGH);
58+
59+
return data;
60+
}
61+
62+
// Get the device identifier
63+
64+
template<uint8_t CS_Pin, uint8_t CLK_Pin, uint8_t MISO_Pin, uint8_t MOSI_Pin>
65+
void FRAM_SPI<CS_Pin, CLK_Pin, MISO_Pin, MOSI_Pin>::getDeviceID(uint8_t *mfgID, uint16_t *prodID)
66+
{
67+
uint8_t array[4], results;
68+
69+
digitalWrite(CS_Pin, LOW);
70+
71+
this->transfer(Opcode_RDID);
72+
array[0] = this->transfer(0);
73+
array[1] = this->transfer(0);
74+
array[2] = this->transfer(0);
75+
array[3] = this->transfer(0);
76+
77+
digitalWrite(CS_Pin, HIGH);
78+
79+
*mfgID = (array[0]);
80+
*prodID = (array[2] << 8) + array[3];
81+
}
82+
83+
// Get and set the status register
84+
85+
template<uint8_t CS_Pin, uint8_t CLK_Pin, uint8_t MISO_Pin, uint8_t MOSI_Pin>
86+
uint8_t FRAM_SPI<CS_Pin, CLK_Pin, MISO_Pin, MOSI_Pin>::getStatusRegister()
87+
{
88+
uint8_t reg = 0;
89+
90+
digitalWrite(CS_Pin, LOW);
91+
92+
this->transfer(Opcode_RDSR);
93+
reg = this->transfer(0);
94+
95+
digitalWrite(CS_Pin, HIGH);
96+
97+
return reg;
98+
}
99+
100+
template<uint8_t CS_Pin, uint8_t CLK_Pin, uint8_t MISO_Pin, uint8_t MOSI_Pin>
101+
void FRAM_SPI<CS_Pin, CLK_Pin, MISO_Pin, MOSI_Pin>::setStatusRegister(uint8_t reg)
102+
{
103+
digitalWrite(CS_Pin, LOW);
104+
105+
this->transfer(Opcode_WRSR);
106+
this->transfer(reg);
107+
108+
digitalWrite(CS_Pin, HIGH);
109+
}
110+
111+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include <Nexus_FRAM_SPI.h>
2+
#include <SPI.h>
3+
4+
class RAM_Disk {
5+
public:
6+
void write(int16_t addr, uint8_t data) { }
7+
uint8_t read(int16_t addr) { }
8+
bool read(int16_t addr, void *data, size_t size) { }
9+
};
10+
11+
template<typename API>
12+
class Store {
13+
14+
public:
15+
16+
template<typename Data>
17+
void put(uint16_t key, Data data) { api.write(key, data); }
18+
19+
template<typename Data>
20+
Data find(uint16_t key, Data data = Data())
21+
{
22+
return api.read(key, &data, sizeof(Data)), data;
23+
}
24+
25+
private:
26+
27+
API api;
28+
29+
};
30+
31+
class Contact {
32+
};
33+
34+
Store<RAM_Disk> ramDisk;
35+
36+
void setup() {
37+
// put your setup code here, to run once:
38+
39+
Contact contact = ramDisk.find<Contact>(100);
40+
}
41+
42+
void loop() {
43+
// put your main code here, to run repeatedly:
44+
45+
}

0 commit comments

Comments
 (0)