1 //////////////////////////////////////////////////////////////////////////////
2 // Lynx 3wire EEPROM Class //
3 //////////////////////////////////////////////////////////////////////////////
4
5 #define EEPROM_CPP
6
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include "system.h"
11 #include "eeprom.h"
12
CEEPROM()13 CEEPROM::CEEPROM()
14 {
15 type=0;
16 *filename=0;
17 memset(romdata, 0xff, sizeof(romdata));
18
19 Reset();
20 }
21
Reset(void)22 void CEEPROM::Reset(void)
23 {
24 busy_count=0;
25 state=EE_NONE;
26 readdata=0;
27
28 data=0;
29 addr=0;
30 sendbits=0;
31 readonly=true;
32
33 counter=0;
34 iodir=0;
35 iodat=0;
36
37 mAUDIN_ext=0;
38 }
39
~CEEPROM()40 CEEPROM::~CEEPROM()
41 {
42 }
43
Load(void)44 void CEEPROM::Load(void)
45 {
46 if(!Available()) return;
47 FILE *fe;
48 if((fe=fopen(filename,"rb"))!=NULL){
49 printf("EEPROM LOAD %s\n",filename);
50 fread(romdata,1,1024,fe);
51 fclose(fe);
52 }
53 }
54
Save(void)55 void CEEPROM::Save(void)
56 {
57 if(!Available()) return;
58 FILE *fe;
59 if((fe=fopen(filename,"wb+"))!=NULL){
60 printf("EEPROM SAVE %s\n",filename);
61 fwrite(romdata,1,Size(),fe);
62 fclose(fe);
63 }
64 }
65
ContextSave(LSS_FILE * fp)66 bool CEEPROM::ContextSave(LSS_FILE *fp)
67 {
68 if(!lss_printf(fp,"CEEPROM::ContextSave")) return 0;
69
70 if(!lss_write(&busy_count,sizeof(ULONG),1,fp)) return 0;
71 if(!lss_write(&state,sizeof(ULONG),1,fp)) return 0;
72 if(!lss_write(&readdata,sizeof(UWORD),1,fp)) return 0;
73
74 if(!lss_write(&data,sizeof(ULONG),1,fp)) return 0;
75 if(!lss_write(&addr,sizeof(UWORD),1,fp)) return 0;
76 if(!lss_write(&sendbits,sizeof(ULONG),1,fp)) return 0;
77 if(!lss_write(&readonly,sizeof(UBYTE),1,fp)) return 0;
78
79 if(!lss_write(&counter,sizeof(UWORD),1,fp)) return 0;
80 if(!lss_write(&iodir,sizeof(UBYTE),1,fp)) return 0;
81 if(!lss_write(&iodat,sizeof(UBYTE),1,fp)) return 0;
82 if(!lss_write(&mAUDIN_ext,sizeof(UBYTE),1,fp)) return 0;
83
84 if(!lss_write(&romdata,sizeof(UWORD),1024,fp)) return 0;
85 return 1;
86 }
87
ContextLoad(LSS_FILE * fp)88 bool CEEPROM::ContextLoad(LSS_FILE *fp)
89 {
90 char teststr[100]="XXXXXXXXXXXXXXXXXXXX";
91 if(!lss_read(teststr,sizeof(char),20,fp)) return 0;
92 teststr[20]=0;
93 if(strcmp(teststr,"CEEPROM::ContextSave")!=0) return 0;
94
95 if(!lss_read(&busy_count,sizeof(ULONG),1,fp)) return 0;
96 if(!lss_read(&state,sizeof(ULONG),1,fp)) return 0;
97 if(!lss_read(&readdata,sizeof(UWORD),1,fp)) return 0;
98
99 if(!lss_read(&data,sizeof(ULONG),1,fp)) return 0;
100 if(!lss_read(&addr,sizeof(UWORD),1,fp)) return 0;
101 if(!lss_read(&sendbits,sizeof(ULONG),1,fp)) return 0;
102 if(!lss_read(&readonly,sizeof(UBYTE),1,fp)) return 0;
103
104 if(!lss_read(&counter,sizeof(UWORD),1,fp)) return 0;
105 if(!lss_read(&iodir,sizeof(UBYTE),1,fp)) return 0;
106 if(!lss_read(&iodat,sizeof(UBYTE),1,fp)) return 0;
107 if(!lss_read(&mAUDIN_ext,sizeof(UBYTE),1,fp)) return 0;
108
109 if(!lss_read(&romdata,sizeof(UWORD),1024,fp)) return 0;
110 return 1;
111 }
112
SetEEPROMType(UBYTE b)113 void CEEPROM::SetEEPROMType(UBYTE b)
114 {
115 type=b;
116 printf("\nEEPROM: ");
117 switch(b&0x7) {
118 case 1: // 93C46 , 8 bit mode
119 ADDR_MASK = 0x7F;
120 CMD_BITS = 10;
121 ADDR_BITS = 7;
122 printf("93C46 ");
123 break;
124 case 2: // 93C56 , 8 bit mode
125 ADDR_MASK = 0xFF;
126 CMD_BITS = 12;
127 ADDR_BITS = 9;
128 printf("93C56 ");
129 break;
130 case 3: // 93C66 , 8 bit mode
131 ADDR_MASK = 0x1FF;
132 CMD_BITS = 12;
133 ADDR_BITS = 9;
134 printf("93C66 ");
135 break;
136 case 4: // 93C76 , 8 bit mode
137 ADDR_MASK = 0x3FF;
138 CMD_BITS = 14;
139 ADDR_BITS = 11;
140 printf("93C76 ");
141 break;
142 case 5: // 93C86 , 8 bit mode
143 ADDR_MASK = 0x7FF;
144 CMD_BITS = 14;
145 ADDR_BITS = 11;
146 printf("93C86 ");
147 break;
148 case 0: // NONE, fallthrou
149 default:
150 ADDR_MASK = 0;
151 CMD_BITS = 1;
152 ADDR_BITS = 1;
153 printf("none ");
154 break;
155 }
156 if(b&0x80) { // 8 bit access
157 DONE_MASK = 0x100;
158 printf("8 bit\n");
159 } else { // 16 bit access
160 ADDR_MASK>>=1;
161 CMD_BITS--;
162 ADDR_BITS--;
163 DONE_MASK = 0x10000;
164 printf("16 bit\n");
165 }
166 }
167
Size(void)168 int CEEPROM::Size(void)
169 {
170 int m=ADDR_MASK+1;
171 if(type&0x80) return m; else return m*2;
172 }
173
ProcessEepromBusy(void)174 void CEEPROM::ProcessEepromBusy(void)
175 {
176 if(state==EE_BUSY || state==EE_NONE) {
177 if(busy_count<2) {
178 busy_count++;
179 readdata=0x0000;// RDY
180 mAUDIN_ext=0;
181 } else {
182 readdata=0xFFFF;// RDY
183 mAUDIN_ext=1;
184 state=EE_WAIT;
185 }
186 // printf("(%d)",busy_count);
187 }
188 }
189
ProcessEepromCounter(UWORD cnt)190 void CEEPROM::ProcessEepromCounter(UWORD cnt)
191 {
192 // Update if either counter strobed or AUDIN changed
193 UpdateEeprom( cnt);
194 }
195
ProcessEepromIO(UBYTE iodir_loc,UBYTE iodat_loc)196 void CEEPROM::ProcessEepromIO(UBYTE iodir_loc,UBYTE iodat_loc)
197 {
198 // Update if either counter strobed or AUDIN changed
199 iodat=iodat_loc;
200 iodir=iodir_loc;
201 }
202
UpdateEeprom(UWORD cnt)203 void CEEPROM::UpdateEeprom(UWORD cnt)
204 {
205 // Update if either counter strobed or AUDIN changed
206 bool CLKp, CLKn;
207 CLKp=counter&0x02;
208 counter=cnt;
209 CLKn=counter&0x02;
210
211 if( CLKp!=CLKn && CLKn) { // Rising edge
212 bool CS, DI;
213 mAUDIN_ext=(readdata&(DONE_MASK>>1)) ? 1 : 0 ;
214 readdata<<=1;
215 CS=cnt&0x80;
216 DI=false;
217 if(iodir&0x10) {
218 DI=iodat&0x10;
219 }
220 if(!CS) state=EE_NONE;
221 switch(state) {
222 case EE_NONE:
223 data=0;
224 if( CS) {
225 if(DI && (iodir&0x10)) {
226 //if( state!=EE_START) printf("EE Start...\n");
227 mAUDIN_ext=0;
228 state=EE_START;
229 data=0;
230 sendbits=CMD_BITS-1;
231 } else if(!(iodir&0x10)) {
232 state=EE_BUSY;
233 //printf("BUSY\n");
234 readdata=0x0000;// RDY
235 mAUDIN_ext=0;
236 busy_count=0;
237 }
238 }
239 break;
240 case EE_START:
241 data<<=1;
242 if(DI) data++;
243 sendbits--;
244 if( sendbits>0) break;
245
246 state=EE_NONE;
247 // if(data!=(0xFFFF&((ADDR_MASK<<2)|0x3))) printf("EE Byte $%02X .. ",(int)data);
248 addr=data&ADDR_MASK;
249 switch(data>>ADDR_BITS) {
250 case 0x3:
251 if(!readonly) {
252 // printf("ERASE ADD $%02X RO %d\n",(int)addr,readonly);
253 romdata[addr]=0xFFFF;
254 }
255 break;
256 case 0x2:
257 if(type&0x80) readdata=((unsigned char *)romdata)[addr]; else readdata=romdata[addr];
258 mAUDIN_ext=0;
259 // printf("Read ADD $%02X $%04X\n",(int)addr,readdata);
260 state=EE_WAIT;
261 break;
262 case 0x1:
263 // printf("Write ADD $%02X RO %d\n",(int)addr,readonly);
264 data=0x1;
265 state=EE_DATA;
266 break;
267 case 0x00:
268 if((data>>(ADDR_BITS-2))==0x0) {
269 // printf("EWDS\n");
270 readonly=true;
271 break;
272 };
273 if((data>>(ADDR_BITS-2))==0x3) {
274 // printf("EWEN\n");
275 readonly=false;
276 break;
277 };
278 if((data>>(ADDR_BITS-2))==0x1) {
279 // printf("WRAL\n");
280 break;
281 };
282 if((data>>(ADDR_BITS-2))==0x2) {
283 // printf("ERAL\n");
284 break;
285 };
286 // falltrhou
287 default:
288 // printf("Unknown $%03X\n",(int)data);
289 break;
290 }
291 break;
292 case EE_DATA:
293 data<<=1;
294 if(DI) data++;
295 if(data&DONE_MASK) {
296 state=EE_NONE;
297 // printf("EE Written Data $%04X ",(unsigned int)data&0xFFFF);
298 if(readonly) {
299 // printf("WRITE PROT!\n");
300 } else {
301 if(type &0x80){
302 ((unsigned char *)romdata)[addr]=(data&0xFF);
303 } else {
304 romdata[addr]=(data&0xFFFF);
305 }
306 // printf("done\n");
307 }
308 busy_count=0;
309 readdata=0x0000;// RDY
310 mAUDIN_ext=0;
311 state=EE_WAIT;
312 }
313 break;
314 case EE_WAIT:
315 // printf(".%d.",mAUDIN_ext);
316 break;
317 }
318 }
319 }
320