-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlc01b.c
More file actions
227 lines (198 loc) · 9.87 KB
/
lc01b.c
File metadata and controls
227 lines (198 loc) · 9.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/*******************************************************************************
* Interface to an MCP24LC01B EEPROM via I2C
*
* Resources used:
* I2C1
*
* Summary:
* The 24LC01B:
* - 1 Kbit (128 byte) capacity
* - VCC range of 2.5-5.5V
* - I2C interface - 100 or 400 kHz
* - Page writes are 8 bytes
* - Page write time of ~3ms
*
* Use 4K7 pullups for a 100kHz bus and 2K2 pullups on a 400kHz bus
* Acknowledge polling is used on all writes
* *****************************************************************************
* 02/2023 Adam Hout -Original source
* ****************************************************************************/
//#include <p24F16KA102.h>
#include <xc.h>
#include "sys.h"
#include "lc01b.h"
//EEPROM error enum from sys.h
ee_Errors_t ee_Error;
//---------------------------------------------------------------
//Send the Start bit, Control byte and Memory byte to the LC01B.
//---------------------------------------------------------------
void lc01b_SCM(uint8_t ee_addr){
//Send the start bit
I2C1CONbits.SEN = 1; //Start enable
while(I2C1CONbits.SEN); //Wait for completion
//Send the control byte
I2C1TRN = LC01B_WRITE; //Control byte; Write mode
while(I2C1STATbits.TRSTAT); //Wait for transmit to complete
while(I2C1STATbits.ACKSTAT);
//Send the memory address byte
I2C1TRN = ee_addr;
while(I2C1STATbits.TRSTAT);
while(I2C1STATbits.ACKSTAT);
}
//---------------------------------------------------------------
//Write a byte to the LC01B at the desired address
//---------------------------------------------------------------
ee_Errors_t lc01b_WriteByte(uint8_t ee_addr,uint8_t dataByte){
//Do a bounds check
if(ee_addr > LC01B_MAX_ADR)
return ERR_MEM_BOUNDS;
else{
//Address the EEPROM
lc01b_SCM(ee_addr);
//Send the data byte
I2C1TRN = dataByte;
while(I2C1STATbits.TRSTAT); //Wait for transmission to complete
while(I2C1STATbits.ACKSTAT);
//Send the stop bit
I2C1CONbits.PEN = 1; //Stop bit
while(I2C1CONbits.PEN); //Wait for stop to complete
ack_Poll();
}
return ERR_NONE;
}
//---------------------------------------------------------------
// Page writes - Up to 8 bytes in length
//---------------------------------------------------------------
ee_Errors_t lc01b_WritePage(uint8_t ee_addr,uint8_t dataLen,uint8_t *pDataBuf){
if((ee_addr + dataLen -1) > LC01B_MAX_ADR)
return ERR_MEM_BOUNDS;
else{
//Address the EEPROM
lc01b_SCM(ee_addr); //Send START, Control byte and memory address
//Write page array to the EEPROM
for(uint8_t ctr=0;ctr<dataLen;ctr++){
I2C1TRN = *pDataBuf++; //Next data byte
while(I2C1STATbits.TRSTAT);
while(I2C1STATbits.ACKSTAT); //Wait for the ACK
}
//Send the stop bit
I2C1CONbits.PEN = 1; //Stop bit
while(I2C1CONbits.PEN); //Wait for stop to complete
//Acknowledge poll
ack_Poll();
}
return ERR_NONE;
}
//---------------------------------------------------------------
//Write multi-byte length variables to the EEPROM
//---------------------------------------------------------------
ee_Errors_t lc01b_WriteObject(uint8_t ee_addr,uint8_t objLen,void *pObj){
uint8_t *pByte = pObj;
if((ee_addr + objLen - 1) > LC01B_MAX_ADR)
return ERR_MEM_BOUNDS;
else{
while(objLen--){
lc01b_WriteByte(ee_addr++,*pByte++);
}
}
return ERR_NONE;
}
//---------------------------------------------------------------
//Read a single byte from the EEPROM
//---------------------------------------------------------------
ee_Errors_t lc01b_ReadByte(uint8_t ee_addr, uint8_t *pData){
if(ee_addr > LC01B_MAX_ADR)
return ERR_MEM_BOUNDS;
else{
//Address the EEPROM
lc01b_SCM(ee_addr);
//Repeated start
I2C1CONbits.RSEN = 1;
while(I2C1CONbits.RSEN);
I2C1TRN = LC01B_READ; //Control byte; Read mode
while(I2C1STATbits.TRSTAT); //Wait for transmit to complete
while(I2C1STATbits.ACKSTAT);
//Read the EEPOM byte
I2C1CONbits.RCEN = 1; //Receive enable
while(I2C1CONbits.RCEN); //Wait for the byte to shift in
while(!I2C1STATbits.RBF); //Wait for the receive buffer flag
*pData = I2C1RCV; //Copy from the receive buffer
//Terminate the read operation
I2C1CONbits.ACKDT = 1; //Send a NACK during acknowledge
I2C1CONbits.ACKEN = 1; //Acknowledge enable
while(I2C1CONbits.ACKEN); //Wait for NACK to complete
I2C1CONbits.PEN = 1; //Stop enable
while(I2C1CONbits.PEN); //Wait for stop to complete
}
return ERR_NONE;
}
//---------------------------------------------------------------
//Read a specified number of sequential bytes beginning from
//the supplied address
//---------------------------------------------------------------
ee_Errors_t lc01b_ReadSeq(uint8_t ee_addr,uint8_t readLen,uint8_t *pDataBuf){
if((ee_addr + readLen - 1) > LC01B_MAX_ADR)
return ERR_MEM_BOUNDS;
else{
//Address the EEPROM
lc01b_SCM(ee_addr);
//Repeated start
I2C1CONbits.RSEN = 1;
while(I2C1CONbits.RSEN);
I2C1TRN = LC01B_READ; //Control byte; Read mode
while(I2C1STATbits.TRSTAT); //Wait for transmit to complete
while(I2C1STATbits.ACKSTAT);
//Read the EEPOM for the desired length
for (uint8_t ctr=0;ctr<readLen;ctr++){
I2C1CONbits.RCEN = 1; //Receive enable
while(I2C1CONbits.RCEN); //Wait for the byte to shift in
while(!I2C1STATbits.RBF); //Wait for the receive buffer flag
*pDataBuf++ = I2C1RCV; //Copy from the receive buffer
if (ctr < readLen-1){ //Don't ACK the last read
I2C1CONbits.ACKDT = 0; //Send an ACK to get next byte
I2C1CONbits.ACKEN = 1; //Acknowledge enable
while(I2C1CONbits.ACKEN); //Wait for ACK to complete
}
}
//Terminate read operation
I2C1CONbits.ACKDT = 1; //Send a NACK during acknowledge
I2C1CONbits.ACKEN = 1; //Acknowledge enable
while(I2C1CONbits.ACKEN); //Wait for NACK to complete
I2C1CONbits.PEN = 1; //Stop enable
while(I2C1CONbits.PEN); //Wait for stop to complete
}
return ERR_NONE;
}
//---------------------------------------------------------
//Read multi-byte length variables from the EEPROM
//---------------------------------------------------------
ee_Errors_t lc01b_ReadObject(uint8_t ee_addr,uint8_t objLen, void *pObj){
uint8_t *pByte = pObj;
if((ee_addr + objLen - 1) > LC01B_MAX_ADR)
return ERR_MEM_BOUNDS;
else{
while(objLen--){
lc01b_ReadByte(ee_addr++,pByte++);
}
}
return ERR_NONE;
}
//-----------------------------------------------------------
//Acknowledge poll the EEPROM until the write cycle completes
//-----------------------------------------------------------
void ack_Poll(){
do{
I2C1CONbits.SEN = 1; //Start enable
while(I2C1CONbits.SEN); //Wait for completion
I2C1TRN = LC01B_WRITE; //Control byte; Write mode
while(I2C1STATbits.TRSTAT); //Wait for transmit to complete
}while(I2C1STATbits.ACKSTAT); //Repeat until ACK'd
}
//------------------------------------------------------------
//Set the baud rate and enable I2C1
//------------------------------------------------------------
void init_I2C(uint8_t BRG){
I2C1CON = 0x0000;
I2C1BRG = BRG;
I2C1CON = 0x8000;
}