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