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