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 }