1 #include <stdint.h>
2 #include <stdbool.h>
3 #include <string.h>
4 
5 #include "dbvz.h"
6 #include "emulator.h"
7 #include "m5XXBus.h"
8 #include "portability.h"
9 #include "flx68000.h"
10 #include "ads7846.h"
11 #include "sdCard.h"
12 #include "sed1376.h"
13 #include "audio/blip_buf.h"
14 #include "m68k/m68k.h"
15 
16 
17 #include "dbvzRegisterNames.c.h"
18 
19 
20 dbvz_chip_t dbvzChipSelects[DBVZ_CHIP_END];
21 uint8_t     dbvzReg[DBVZ_REG_SIZE];
22 uint16_t*   dbvzFramebuffer;
23 uint16_t    dbvzFramebufferWidth;
24 uint16_t    dbvzFramebufferHeight;
25 
26 static double   dbvzSysclksPerClk32;//how many SYSCLK cycles before toggling the 32.768 kHz crystal
27 static uint32_t dbvzFrameClk32s;//how many CLK32s have happened in the current frame
28 static double   dbvzClk32Sysclks;//how many SYSCLKs have happened in the current CLK32
29 static int8_t   pllSleepWait;
30 static int8_t   pllWakeWait;
31 static uint32_t clk32Counter;
32 static double   pctlrCpuClockDivider;
33 static double   timerCycleCounter[2];
34 static uint16_t timerStatusReadAcknowledge[2];
35 static uint8_t  portDInterruptLastValue;//used for edge triggered interrupt timing
36 static uint16_t spi1RxFifo[9];
37 static uint16_t spi1TxFifo[9];
38 static uint8_t  spi1RxReadPosition;
39 static uint8_t  spi1RxWritePosition;
40 static bool     spi1RxOverflowed;
41 static uint8_t  spi1TxReadPosition;
42 static uint8_t  spi1TxWritePosition;
43 static int32_t  pwm1ClocksToNextSample;
44 static uint8_t  pwm1Fifo[6];
45 static uint8_t  pwm1ReadPosition;
46 static uint8_t  pwm1WritePosition;
47 
48 
49 static void checkInterrupts(void);
50 static void checkPortDInterrupts(void);
51 static void pllWakeCpuIfOff(void);
52 static double sysclksPerClk32(void);
53 static int32_t audioGetFramePercentIncrementFromClk32s(int32_t count);
54 static int32_t audioGetFramePercentIncrementFromSysclks(double count);
55 static int32_t audioGetFramePercentage(void);
56 
57 #include "dbvzRegisterAccessors.c.h"
58 #include "dbvzTiming.c.h"
59 
dbvzLcdRender(void)60 void dbvzLcdRender(void){
61    static const uint16_t masterColorLut[16] = {0x746D, 0x6C0C, 0x63CB, 0x5B8A, 0x534A, 0x4AE9, 0x42A8, 0x3A67, 0x3A27, 0x31C6, 0x2985, 0x2144, 0x1904, 0x10A3, 0x0862, 0x0000};
62    static const uint8_t bppLut[4] = {1, 2, 4, 0};
63    uint16_t colorLut2Bpp[4];//stores indexes to masterColorLut
64    uint32_t startAddress = registerArrayRead32(LSSA);
65    uint8_t bitsPerPixel = bppLut[registerArrayRead8(LPICF) & 0x03];
66    uint16_t pageWidth = registerArrayRead8(LVPW) * 2;//in bytes
67    bool invertColors = registerArrayRead8(LPOLCF) & 0x01;
68    uint8_t pixelShift = registerArrayRead8(LPOSR);
69    uint16_t width = registerArrayRead16(LXMAX);
70    uint16_t height = registerArrayRead16(LYMAX) + 1;
71    uint16_t y;
72    uint16_t x;
73 
74    //dont render if LCD controller is disabled
75    if(!(registerArrayRead8(LCKCON) & 0x80)){
76       memset(dbvzFramebuffer, 0x00, dbvzFramebufferWidth * dbvzFramebufferHeight * sizeof(uint16_t));
77       return;
78    }
79 
80    width = FAST_MIN(width, dbvzFramebufferWidth);
81    height = FAST_MIN(height, dbvzFramebufferHeight);
82 
83    //TODO: cursor not implemented, not that anything will use a hardware terminal cursor on Palm OS
84    //m500 ROM I am using has the hardware feature bit for inverting color when backlight is on disabled, the backlight does not invert the colors even though HW supports it
85 
86    switch(bitsPerPixel){
87       case 1:
88          for(y = 0; y < height; y++){
89             for(x = 0; x < width / 16; x++){
90                uint16_t dataUnit = m68k_read_memory_16(startAddress + y * pageWidth + x * 2);
91                uint8_t index;
92 
93                for(index = 0; index < 16; index++)
94                   if(x * 16 + index >= pixelShift)
95                      dbvzFramebuffer[y * dbvzFramebufferWidth + x * 16 + index - pixelShift] = !!(dataUnit & 1 << 15 - index) == invertColors ? masterColorLut[0] : masterColorLut[15];
96             }
97          }
98          break;
99 
100       case 2:
101          colorLut2Bpp[0] = 0;
102          colorLut2Bpp[1] = registerArrayRead8(LGPMR) & 0x0F;
103          colorLut2Bpp[2] = registerArrayRead8(LGPMR) >> 4;
104          colorLut2Bpp[3] = 15;
105 
106          for(y = 0; y < height; y++){
107             for(x = 0; x < width / 8; x++){
108                uint16_t dataUnit = m68k_read_memory_16(startAddress + y * pageWidth + x * 2);
109                uint8_t index;
110 
111                for(index = 0; index < 8; index++)
112                   if(x * 8 + index >= pixelShift)
113                      dbvzFramebuffer[y * dbvzFramebufferWidth + x * 8 + index - pixelShift] = invertColors ? masterColorLut[15 - colorLut2Bpp[dataUnit >> 14 - index * 2 & 0x03]] : masterColorLut[colorLut2Bpp[dataUnit >> 14 - index * 2 & 0x03]];
114             }
115          }
116          break;
117 
118       case 4:
119          for(y = 0; y < height; y++){
120             for(x = 0; x < width / 4; x++){
121                uint16_t dataUnit = m68k_read_memory_16(startAddress + y * pageWidth + x * 2);
122                uint8_t index;
123 
124                for(index = 0; index < 4; index++)
125                   if(x * 4 + index >= pixelShift)
126                      dbvzFramebuffer[y * dbvzFramebufferWidth + x * 4 + index - pixelShift] = invertColors ? masterColorLut[15 - (dataUnit >> 12 - index * 4 & 0x0F)] : masterColorLut[dataUnit >> 12 - index * 4 & 0x0F];
127             }
128          }
129          break;
130 
131       default:
132          debugLog("Invalid DBVZ LCD controller pixel depth %d!\n", bitsPerPixel);
133          break;
134    }
135 }
136 
dbvzIsPllOn(void)137 bool dbvzIsPllOn(void){
138    return !(dbvzSysclksPerClk32 < 1.0);
139 }
140 
m515BacklightAmplifierState(void)141 bool m515BacklightAmplifierState(void){
142    return !!(getPortKValue() & 0x02);
143 }
144 
dbvzAreRegistersXXFFMapped(void)145 bool dbvzAreRegistersXXFFMapped(void){
146    return !!(registerArrayRead8(SCR) & 0x04);
147 }
148 
sed1376ClockConnected(void)149 bool sed1376ClockConnected(void){
150    //this is the clock output pin for the SED1376, if its disabled so is the LCD controller
151    //port f pin 2 is not GPIO and PLLCR CLKEN is false enabling clock output on port f pin 2
152    return !(registerArrayRead8(PFSEL) & 0x04) && !(registerArrayRead16(PLLCR) & 0x0010);
153 }
154 
ads7846OverridePenState(bool value)155 void ads7846OverridePenState(bool value){
156    //causes a temporary override of the touchscreen value, used to trigger fake interrupts from line noise when reading from the ADS7846
157    if(value != (ads7846PenIrqEnabled ? !palmInput.touchscreenTouched : true)){
158       if(!(registerArrayRead8(PFSEL) & registerArrayRead8(PFDIR) & 0x02)){
159          if(value == !!(registerArrayRead16(ICR) & 0x0080))
160             setIprIsrBit(DBVZ_INT_IRQ5);
161          else
162             clearIprIsrBit(DBVZ_INT_IRQ5);
163          checkInterrupts();
164       }
165 
166       //override over, put back real state
167       updateTouchState();
168       checkInterrupts();
169    }
170 }
171 
m5XXRefreshTouchState(void)172 void m5XXRefreshTouchState(void){
173    //called when ads7846PenIrqEnabled is changed
174    updateTouchState();
175    checkInterrupts();
176 }
177 
m5XXRefreshInputState(void)178 void m5XXRefreshInputState(void){
179    //update power button LED state incase palmMisc.batteryCharging changed
180    updatePowerButtonLedStatus();
181 
182    //update touchscreen
183    updateTouchState();
184 
185    //check for button presses and interrupts
186    checkPortDInterrupts();//this calls checkInterrupts() so it doesnt need to be called above
187 }
188 
interruptAcknowledge(int32_t intLevel)189 int32_t interruptAcknowledge(int32_t intLevel){
190    uint8_t vectorOffset = registerArrayRead8(IVR);
191    int32_t vector;
192 
193    //If an interrupt occurs before the IVR has been programmed, interrupt vector 15 is returned to the CPU as an uninitialized interrupt.
194    if(vectorOffset)
195       vector = vectorOffset | intLevel;
196    else
197       vector = 15;//EXCEPTION_UNINITIALIZED_INTERRUPT
198 
199    //only active interrupts should wake the CPU if the PLL is off
200    pllWakeCpuIfOff();
201 
202    //the interrupt should only be cleared after its been handled
203    return vector;
204 }
205 
dbvzSetBusErrorTimeOut(uint32_t address,bool isWrite)206 void dbvzSetBusErrorTimeOut(uint32_t address, bool isWrite){
207    uint8_t scr = registerArrayRead8(SCR);
208    debugLog("Bus error timeout at:0x%08X, PC:0x%08X\n", address, flx68000GetPc());
209    registerArrayWrite8(SCR, scr | 0x80);
210    if(scr & 0x10)
211       flx68000BusError(address, isWrite);
212 }
213 
dbvzSetPrivilegeViolation(uint32_t address,bool isWrite)214 void dbvzSetPrivilegeViolation(uint32_t address, bool isWrite){
215    uint8_t scr = registerArrayRead8(SCR);
216    debugLog("Privilege violation at:0x%08X, PC:0x%08X\n", address, flx68000GetPc());
217    registerArrayWrite8(SCR, scr | 0x20);
218    if(scr & 0x10)
219       flx68000BusError(address, isWrite);
220 }
221 
dbvzSetWriteProtectViolation(uint32_t address)222 void dbvzSetWriteProtectViolation(uint32_t address){
223    uint8_t scr = registerArrayRead8(SCR);
224    debugLog("Write protect violation at:0x%08X, PC:0x%08X\n", address, flx68000GetPc());
225    registerArrayWrite8(SCR, scr | 0x40);
226    if(scr & 0x10)
227       flx68000BusError(address, true);
228 }
229 
pllWakeCpuIfOff(void)230 static void pllWakeCpuIfOff(void){
231    static const int8_t pllWaitTable[4] = {32, 48, 64, 96};
232 
233    //PLL is off and not already in the process of waking up
234    if(!dbvzIsPllOn() && pllWakeWait == -1)
235       pllWakeWait = pllWaitTable[registerArrayRead16(PLLCR) & 0x0003];
236 }
237 
checkInterrupts(void)238 static void checkInterrupts(void){
239    //reduces time wasted on checking interrupts that where updated to a new value identical to the old one, does not need to be in states
240    static uint32_t dbvzCachedInterrupts;
241 
242    uint32_t activeInterrupts = registerArrayRead32(ISR);
243    uint16_t interruptLevelControlRegister = registerArrayRead16(ILCR);
244    uint8_t spi1IrqLevel = interruptLevelControlRegister >> 12;
245    uint8_t uart2IrqLevel = interruptLevelControlRegister >> 8 & 0x0007;
246    uint8_t pwm2IrqLevel = interruptLevelControlRegister >> 4 & 0x0007;
247    uint8_t timer2IrqLevel = interruptLevelControlRegister & 0x0007;
248    uint8_t intLevel = 0;
249 
250    //even masked interrupts turn off PCTLR, 4.5.4 Power Control Register MC68VZ328UM.pdf
251    if(registerArrayRead32(IPR) && registerArrayRead8(PCTLR) & 0x80){
252       registerArrayWrite8(PCTLR, registerArrayRead8(PCTLR) & 0x1F);
253       pctlrCpuClockDivider = 1.0;
254    }
255 
256    //dont waste time if nothing changed
257    if(activeInterrupts == dbvzCachedInterrupts)
258       return;
259 
260    //static interrupts
261    if(activeInterrupts & DBVZ_INT_EMIQ)
262       intLevel = 7;//EMIQ - Emulator IRQ, has nothing to do with emulation, used for debugging on a dev board
263 
264    if(intLevel < 6 && activeInterrupts & (DBVZ_INT_TMR1 | DBVZ_INT_PWM1 | DBVZ_INT_IRQ6))
265       intLevel = 6;
266 
267    if(intLevel < 5 && activeInterrupts & DBVZ_INT_IRQ5)
268       intLevel = 5;
269 
270    if(intLevel < 4 && activeInterrupts & (DBVZ_INT_SPI2 | DBVZ_INT_UART1 | DBVZ_INT_WDT | DBVZ_INT_RTC | DBVZ_INT_KB | DBVZ_INT_RTI | DBVZ_INT_INT0 | DBVZ_INT_INT1 | DBVZ_INT_INT2 | DBVZ_INT_INT3))
271       intLevel = 4;
272 
273    if(intLevel < 3 && activeInterrupts & DBVZ_INT_IRQ3)
274       intLevel = 3;
275 
276    if(intLevel < 2 && activeInterrupts & DBVZ_INT_IRQ2)
277       intLevel = 2;
278 
279    if(intLevel < 1 && activeInterrupts & DBVZ_INT_IRQ1)
280       intLevel = 1;
281 
282    //configureable interrupts
283    if(intLevel < spi1IrqLevel && activeInterrupts & DBVZ_INT_SPI1)
284       intLevel = spi1IrqLevel;
285 
286    if(intLevel < uart2IrqLevel && activeInterrupts & DBVZ_INT_UART2)
287       intLevel = uart2IrqLevel;
288 
289    if(intLevel < pwm2IrqLevel && activeInterrupts & DBVZ_INT_PWM2)
290       intLevel = pwm2IrqLevel;
291 
292    if(intLevel < timer2IrqLevel && activeInterrupts & DBVZ_INT_TMR2)
293       intLevel = timer2IrqLevel;
294 
295    //should be called even if intLevel is 0, that is how the interrupt state gets cleared
296    flx68000SetIrq(intLevel);
297 
298    //no interrupts have changed since the last call to this function, which is now
299    dbvzCachedInterrupts = activeInterrupts;
300 }
301 
checkPortDInterrupts(void)302 static void checkPortDInterrupts(void){
303    uint16_t icr = registerArrayRead16(ICR);
304    uint8_t icrPolSwap = (!!(icr & 0x1000) << 7 | !!(icr & 0x2000) << 6 | !!(icr & 0x4000) << 5 | !!(icr & 0x8000) << 4) ^ 0xF0;//shifted to match port d layout
305    uint8_t icrEdgeTriggered = !!(icr & 0x0100) << 7 | !!(icr & 0x0200) << 6 | !!(icr & 0x0400) << 5 | !!(icr & 0x0800) << 4;//shifted to match port d layout
306    uint8_t portDInterruptValue = getPortDValue() ^ icrPolSwap;//not the same as the actual pin values, this already has all polarity swaps applied
307    uint8_t portDInterruptEdgeTriggered = icrEdgeTriggered | registerArrayRead8(PDIRQEG);
308    uint8_t portDInterruptEnabled = (~registerArrayRead8(PDSEL) & 0xF0) | registerArrayRead8(PDIRQEN);
309    uint8_t portDIsInput = ~registerArrayRead8(PDDIR);
310    uint8_t portDInterruptTriggered = portDInterruptValue & portDInterruptEnabled & portDIsInput & (~portDInterruptEdgeTriggered | ~portDInterruptLastValue & (dbvzIsPllOn() ? 0xFF : 0xF0));
311 
312    if(portDInterruptTriggered & 0x01)
313       setIprIsrBit(DBVZ_INT_INT0);
314    else if(!(portDInterruptEdgeTriggered & 0x01))
315       clearIprIsrBit(DBVZ_INT_INT0);
316 
317    if(portDInterruptTriggered & 0x02)
318       setIprIsrBit(DBVZ_INT_INT1);
319    else if(!(portDInterruptEdgeTriggered & 0x02))
320       clearIprIsrBit(DBVZ_INT_INT1);
321 
322    if(portDInterruptTriggered & 0x04)
323       setIprIsrBit(DBVZ_INT_INT2);
324    else if(!(portDInterruptEdgeTriggered & 0x04))
325       clearIprIsrBit(DBVZ_INT_INT2);
326 
327    if(portDInterruptTriggered & 0x08)
328       setIprIsrBit(DBVZ_INT_INT3);
329    else if(!(portDInterruptEdgeTriggered & 0x08))
330       clearIprIsrBit(DBVZ_INT_INT3);
331 
332    if(portDInterruptTriggered & 0x10)
333       setIprIsrBit(DBVZ_INT_IRQ1);
334    else if(!(portDInterruptEdgeTriggered & 0x10))
335       clearIprIsrBit(DBVZ_INT_IRQ1);
336 
337    if(portDInterruptTriggered & 0x20)
338       setIprIsrBit(DBVZ_INT_IRQ2);
339    else if(!(portDInterruptEdgeTriggered & 0x20))
340       clearIprIsrBit(DBVZ_INT_IRQ2);
341 
342    if(portDInterruptTriggered & 0x40)
343       setIprIsrBit(DBVZ_INT_IRQ3);
344    else if(!(portDInterruptEdgeTriggered & 0x40))
345       clearIprIsrBit(DBVZ_INT_IRQ3);
346 
347    if(portDInterruptTriggered & 0x80)
348       setIprIsrBit(DBVZ_INT_IRQ6);
349    else if(!(portDInterruptEdgeTriggered & 0x80))
350       clearIprIsrBit(DBVZ_INT_IRQ6);
351 
352    //active low/off level triggered interrupt(triggers on 0, not a pull down resistor)
353    //The SELx, POLx, IQENx, and IQEGx bits have no effect on the functionality of KBENx, 10.4.5.8 Port D Keyboard Enable Register MC68VZ328UM.pdf
354    //the above has finally been verified to be correct!
355    if(registerArrayRead8(PDKBEN) & ~(getPortDValue() ^ registerArrayRead8(PDPOL)) & portDIsInput)
356       setIprIsrBit(DBVZ_INT_KB);
357    else
358       clearIprIsrBit(DBVZ_INT_KB);
359 
360    //save to check against next time this function is called
361    portDInterruptLastValue = portDInterruptTriggered;
362 
363    checkInterrupts();
364 }
365 
printHwRegAccess(uint32_t address,uint32_t value,uint32_t size,bool isWrite)366 static void printHwRegAccess(uint32_t address, uint32_t value, uint32_t size, bool isWrite){
367    if(isWrite)
368       debugLog("CPU wrote %d bits of 0x%08X to register 0x%03X, PC:0x%08X.\n", size, value, address, flx68000GetPc());
369    else
370       debugLog("CPU read %d bits from register 0x%03X, PC:0x%08X.\n", size, address, flx68000GetPc());
371 }
372 
dbvzGetRegister8(uint32_t address)373 uint8_t dbvzGetRegister8(uint32_t address){
374 #if !defined(EMU_NO_SAFETY)
375    if((address & 0x0000F000) != 0x0000F000){
376       dbvzSetBusErrorTimeOut(address, false);
377       return 0x00;
378    }
379 #endif
380 
381    address &= 0x00000FFF;
382 
383    switch(address){
384       case PADATA:
385          return getPortAValue();
386 
387       case PBDATA:
388          return getPortBValue();
389 
390       case PCDATA:
391          return getPortCValue();
392 
393       case PDDATA:
394          return getPortDValue();
395 
396       case PEDATA:
397          return getPortEValue();
398 
399       case PFDATA:
400          return getPortFValue();
401 
402       case PGDATA:
403          return getPortGValue();
404 
405       case PJDATA:
406          return getPortJValue();
407 
408       case PKDATA:
409          return getPortKValue();
410 
411       case PMDATA:
412          return getPortMValue();
413 
414       case PWMCNT1:
415          debugLog("PWMCNT1 not implimented\n");
416          return 0x00;
417 
418       //16 bit registers being read as 8 bit
419       case SPICONT1:
420       case SPICONT1 + 1:
421       case SPIINTCS:
422       case SPIINTCS + 1:
423       case PLLFSR:
424       case PLLFSR + 1:
425 
426       //basic non GPIO functions
427       case SCR:
428       case LCKCON:
429       case IVR:
430       case PWMP1:
431       case LGPMR:
432 
433       //LCD controller
434       case LPICF:
435       case LPOLCF:
436 
437       //port d special functions
438       case PDPOL:
439       case PDIRQEN:
440       case PDIRQEG:
441       case PDKBEN:
442 
443       //I/O direction
444       case PBDIR:
445       case PDDIR:
446       case PEDIR:
447       case PFDIR:
448       case PJDIR:
449       case PKDIR:
450 
451       //select between GPIO or special function
452       case PBSEL:
453       case PCSEL:
454       case PDSEL:
455       case PESEL:
456       case PFSEL:
457       case PGSEL:
458       case PJSEL:
459       case PKSEL:
460       case PMSEL:
461 
462       //pull up/down enable
463       case PAPUEN:
464       case PBPUEN:
465       case PCPDEN:
466       case PDPUEN:
467       case PEPUEN:
468       case PFPUEN:
469       case PGPUEN:
470       case PJPUEN:
471       case PKPUEN:
472       case PMPUEN:
473          //simple read, no actions needed
474          //PGPUEN, PGSEL PMSEL and PMPUEN lack the top 2 bits but that is handled on write
475          //PDSEL lacks the bottom 4 bits but that is handled on write
476          return registerArrayRead8(address);
477 
478       default:
479          //bootloader
480          if(address >= 0xE00)
481             return registerArrayRead8(address);
482 
483          printHwRegAccess(address, 0, 8, false);
484          return 0x00;
485    }
486 }
487 
dbvzGetRegister16(uint32_t address)488 uint16_t dbvzGetRegister16(uint32_t address){
489 #if !defined(EMU_NO_SAFETY)
490    if((address & 0x0000F000) != 0x0000F000){
491       dbvzSetBusErrorTimeOut(address, false);
492       return 0x0000;
493    }
494 #endif
495 
496    address &= 0x00000FFF;
497 
498    switch(address){
499       case TSTAT1:
500          timerStatusReadAcknowledge[0] |= registerArrayRead16(TSTAT1);//active bits acknowledged
501          return registerArrayRead16(TSTAT1);
502 
503       case TSTAT2:
504          timerStatusReadAcknowledge[1] |= registerArrayRead16(TSTAT2);//active bits acknowledged
505          return registerArrayRead16(TSTAT2);
506 
507       case PWMC1:
508          return getPwmc1();
509 
510       case SPITEST:
511          //SSTATUS is unemulated because the datasheet has no descrption of how it works
512          return spi1RxFifoEntrys() << 4 | spi1TxFifoEntrys();
513 
514       case SPIRXD:{
515             uint16_t fifoVal = spi1RxFifoRead();
516             //check if SPI1 interrupts changed
517             setSpiIntCs(registerArrayRead16(SPIINTCS));
518             //debugLog("SPIRXD read, FIFO value:0x%04X, SPIINTCS:0x%04X\n", fifoVal, registerArrayRead16(SPIINTCS));
519             return fifoVal;
520          }
521 
522       case UTX1:{
523             uint16_t uart1TxStatus = registerArrayRead16(UTX1);
524             uint8_t entrys = uart1TxFifoEntrys();
525 
526             uart1TxStatus |= (entrys == 0) << 15;
527             uart1TxStatus |= (entrys < 4) << 14;
528             uart1TxStatus |= (entrys < 8) << 13;
529 
530             return uart1TxStatus;
531          }
532 
533       case UTX2:{
534             uint16_t uart2TxStatus = registerArrayRead16(UTX2);
535             uint8_t entrys = uart2TxFifoEntrys();
536 
537             uart2TxStatus |= (entrys == 0) << 15;
538             uart2TxStatus |= (entrys < 4) << 14;
539             uart2TxStatus |= (entrys < 8) << 13;
540 
541             return uart2TxStatus;
542          }
543 
544       case PLLFSR:
545          return registerArrayRead16(PLLFSR);
546 
547       //32 bit registers accessed as 16 bit
548       case IDR:
549       case IDR + 2:
550       case IMR:
551       case IMR + 2:
552       case IPR:
553       case IPR + 2:
554       case ISR:
555       case ISR + 2:
556 
557       case CSA:
558       case CSB:
559       case CSC:
560       case CSD:
561       case CSGBA:
562       case CSGBB:
563       case CSGBC:
564       case CSGBD:
565       case CSUGBA:
566       case PLLCR:
567       case DRAMC:
568       case SDCTRL:
569       case RTCISR:
570       case RTCCTL:
571       case RTCIENR:
572       case ILCR:
573       case ICR:
574       case TCMP1:
575       case TCMP2:
576       case TPRER1:
577       case TPRER2:
578       case TCTL1:
579       case TCTL2:
580       case SPICONT1:
581       case SPIINTCS:
582       case SPISPC:
583       case SPICONT2:
584       case SPIDATA2:
585       case USTCNT1:
586       case UBAUD1:
587       case UMISC1:
588       case NIPR1:
589       case USTCNT2:
590       case UBAUD2:
591       case UMISC2:
592       case NIPR2:
593       case HMARK:
594       case LCXP:
595       case PWMR:
596       case LXMAX:
597       case LYMAX:
598          //simple read, no actions needed
599          return registerArrayRead16(address);
600 
601       default:
602          //bootloader
603          if(address >= 0xE00)
604             return registerArrayRead16(address);
605 
606          printHwRegAccess(address, 0, 16, false);
607          return 0x0000;
608    }
609 }
610 
dbvzGetRegister32(uint32_t address)611 uint32_t dbvzGetRegister32(uint32_t address){
612 #if !defined(EMU_NO_SAFETY)
613    if((address & 0x0000F000) != 0x0000F000){
614       dbvzSetBusErrorTimeOut(address, false);
615       return 0x00000000;
616    }
617 #endif
618 
619    address &= 0x00000FFF;
620 
621    switch(address){
622       case ISR:
623       case IPR:
624       case IMR:
625       case RTCTIME:
626       case IDR:
627       case LSSA:
628          //simple read, no actions needed
629          return registerArrayRead32(address);
630 
631       default:
632          //bootloader
633          if(address >= 0xE00)
634             return registerArrayRead32(address);
635 
636          printHwRegAccess(address, 0, 32, false);
637          return 0x00000000;
638    }
639 }
640 
dbvzSetRegister8(uint32_t address,uint8_t value)641 void dbvzSetRegister8(uint32_t address, uint8_t value){
642 #if !defined(EMU_NO_SAFETY)
643    if((address & 0x0000F000) != 0x0000F000){
644       dbvzSetBusErrorTimeOut(address, true);
645       return;
646    }
647 #endif
648 
649    address &= 0x00000FFF;
650 
651    switch(address){
652       case SCR:
653          setScr(value);
654          return;
655 
656       case UTX1 + 1:
657          //this is a 16 bit register but Palm OS writes to the 8 bit FIFO section alone
658          //send byte and update interrupts if enabled
659          if((registerArrayRead16(USTCNT1) & 0xA000) == 0xA000){
660             uart1TxFifoWrite(value);
661             updateUart1Interrupt();
662          }
663          return;
664 
665       case UTX2 + 1:
666          //this is a 16 bit register but Palm OS writes to the 8 bit FIFO section alone
667          //send byte and update interrupts if enabled
668          if((registerArrayRead16(USTCNT2) & 0xA000) == 0xA000){
669             uart2TxFifoWrite(value);
670             updateUart2Interrupt();
671          }
672          return;
673 
674       case PWMS1 + 1:
675          //write only if PWM1 enabled
676          if(registerArrayRead16(PWMC1) & 0x0010)
677             pwm1FifoWrite(value);
678          return;
679 
680       case PWMP1:
681          //write only if PWM1 enabled
682          if(registerArrayRead16(PWMC1) & 0x0010)
683             registerArrayWrite8(address, value);
684          return;
685 
686       case PCTLR:
687          registerArrayWrite8(address, value & 0x9F);
688          if(value & 0x80)
689             pctlrCpuClockDivider = (value & 0x1F) / 31.0;
690          checkInterrupts();//may need to turn PCTLR off right after its turned on(could be in an interrupt)
691          return;
692 
693       case IVR:
694          //write without the bottom 3 bits
695          registerArrayWrite8(address, value & 0xF8);
696          return;
697 
698       case LPICF:
699       case LPOLCF:
700       case LPOSR:
701          registerArrayWrite8(address, value & 0x0F);
702          return;
703 
704       case LPXCD:
705          registerArrayWrite8(LPXCD, value & 0x3F);
706          return;
707 
708       case PBSEL:
709       case PBDIR:
710       case PBDATA:
711          registerArrayWrite8(address, value);
712          updatePowerButtonLedStatus();
713          return;
714 
715       case PDSEL:
716          //write without the bottom 4 bits
717          registerArrayWrite8(address, value & 0xF0);
718          checkPortDInterrupts();
719          return;
720 
721       case PDPOL:
722       case PDIRQEN:
723       case PDIRQEG:
724          //write without the top 4 bits
725          registerArrayWrite8(address, value & 0x0F);
726          checkPortDInterrupts();
727          return;
728 
729       case PDDATA:
730       case PDKBEN:
731          //can change interrupt state
732          registerArrayWrite8(address, value);
733          checkPortDInterrupts();
734          return;
735 
736       case PFSEL:
737          //this register controls the clock output pin for the SED1376 and IRQ line for PENIRQ
738          registerArrayWrite8(PFSEL, value);
739          m515SetSed1376Attached(sed1376ClockConnected());
740 #if !defined(EMU_NO_SAFETY)
741          updateTouchState();
742          checkInterrupts();
743 #endif
744          return;
745 
746       case PFDIR:
747          //this register controls the IRQ line for PENIRQ
748          registerArrayWrite8(PFDIR, value);
749 #if !defined(EMU_NO_SAFETY)
750          updateTouchState();
751          checkInterrupts();
752 #endif
753          return;
754 
755       case PGSEL:
756       case PGDIR:
757       case PGDATA:
758          //write without the top 2 bits
759          registerArrayWrite8(address, value & 0x3F);
760          updateAds7846ChipSelectStatus();
761          if(palmEmulatingM500)
762             palmMisc.backlightLevel = !!(getPortGValue() & 0x02) * 100;
763          return;
764 
765       case PJSEL:
766       case PJDIR:
767       case PJDATA:
768          registerArrayWrite8(address, value);
769          updateSdCardChipSelectStatus();
770          return;
771 
772       case PKSEL:
773       case PKDIR:
774       case PKDATA:
775          registerArrayWrite8(address, value);
776          checkPortDInterrupts();
777          updateVibratorStatus();
778          if(!palmEmulatingM500)
779             sed1376UpdateLcdStatus();
780          return;
781 
782       case PMSEL:
783       case PMDIR:
784       case PMDATA:
785          //unemulated
786          //infrared shutdown
787          registerArrayWrite8(address, value & 0x3F);
788          return;
789 
790       case PMPUEN:
791       case PGPUEN:
792          //write without the top 2 bits
793          registerArrayWrite8(address, value & 0x3F);
794          return;
795 
796       //select between GPIO or special function
797       case PCSEL:
798       case PESEL:
799 
800       //direction select
801       case PADIR:
802       case PCDIR:
803       case PDDIR:
804       case PEDIR:
805 
806       //pull up/down enable
807       case PAPUEN:
808       case PBPUEN:
809       case PCPDEN:
810       case PDPUEN:
811       case PEPUEN:
812       case PFPUEN:
813       case PJPUEN:
814       case PKPUEN:
815 
816       //port data value, nothing known is attached to port
817       case PCDATA:
818       case PEDATA:
819       case PFDATA:
820 
821       //dragonball LCD controller
822       case LVPW:
823       case LCKCON:
824       case LBLKC:
825       case LACDRC:
826       case LGPMR:
827          //simple write, no actions needed
828          registerArrayWrite8(address, value);
829          return;
830 
831       default:
832          //writeable bootloader region
833          if(address >= 0xFC0){
834             registerArrayWrite32(address, value);
835             return;
836          }
837 
838          printHwRegAccess(address, value, 8, true);
839          return;
840    }
841 }
842 
dbvzSetRegister16(uint32_t address,uint16_t value)843 void dbvzSetRegister16(uint32_t address, uint16_t value){
844 #if !defined(EMU_NO_SAFETY)
845    if((address & 0x0000F000) != 0x0000F000){
846       dbvzSetBusErrorTimeOut(address, true);
847       return;
848    }
849 #endif
850 
851    address &= 0x00000FFF;
852 
853    switch(address){
854       case RTCIENR:
855          //missing bits 6 and 7
856          registerArrayWrite16(address, value & 0xFF3F);
857          return;
858 
859       case RTCCTL:
860          registerArrayWrite16(address, value & 0x00A0);
861          return;
862 
863       case IMR:
864          //this is a 32 bit register but Palm OS writes to it as 16 bit chunks
865          registerArrayWrite16(IMR, value & 0x00FF);
866          registerArrayWrite16(ISR, registerArrayRead16(IPR) & ~registerArrayRead16(IMR));
867          checkInterrupts();
868          return;
869       case IMR + 2:
870          //this is a 32 bit register but Palm OS writes to it as 16 bit chunks
871          registerArrayWrite16(IMR + 2, value & 0xFFFF);//Palm OS writes to reserved bits 14 and 15
872          registerArrayWrite16(ISR + 2, registerArrayRead16(IPR + 2) & ~registerArrayRead16(IMR + 2));
873          checkInterrupts();
874          return;
875 
876       case ISR:
877          setIsr(value << 16, true, false);
878          return;
879       case ISR + 2:
880          setIsr(value, false, true);
881          return;
882 
883       case TCTL1:
884       case TCTL2:
885          registerArrayWrite16(address, value & 0x01FF);
886          return;
887 
888       case TSTAT1:
889          setTstat1(value);
890          return;
891 
892       case TSTAT2:
893          setTstat2(value);
894          return;
895 
896       case WATCHDOG:
897          //writing to the watchdog resets the counter bits(8 and 9) to 0
898          //1 must be written to clear INTF
899          registerArrayWrite16(WATCHDOG, (value & 0x0003) | (registerArrayRead16(WATCHDOG) & (~value & 0x0080)));
900          if(!(registerArrayRead16(WATCHDOG) & 0x0080))
901             clearIprIsrBit(DBVZ_INT_WDT);
902          return;
903 
904       case RTCISR:
905          registerArrayWrite16(RTCISR, registerArrayRead16(RTCISR) & ~value);
906          if(!(registerArrayRead16(RTCISR) & 0xFF00))
907             clearIprIsrBit(DBVZ_INT_RTI);
908          if(!(registerArrayRead16(RTCISR) & 0x003F))
909             clearIprIsrBit(DBVZ_INT_RTC);
910          checkInterrupts();
911          return;
912 
913       case PLLFSR:
914          setPllfsr(value);
915          return;
916 
917       case PLLCR:
918          //CLKEN is required for SED1376 operation
919          registerArrayWrite16(PLLCR, value & 0x3FBB);
920          dbvzSysclksPerClk32 = sysclksPerClk32();
921          m515SetSed1376Attached(sed1376ClockConnected());
922 
923          if(value & 0x0008)
924             pllSleepWait = 30;//The PLL shuts down 30 clocks of CLK32 after the DISPLL bit is set in the PLLCR
925          else
926             pllSleepWait = -1;//allow the CPU to cancel the shut down
927          return;
928 
929       case ICR:
930          registerArrayWrite16(ICR, value & 0xFF80);
931          updateTouchState();
932          checkPortDInterrupts();//this calls checkInterrupts() so it doesnt need to be called above
933          return;
934 
935       case ILCR:
936          setIlcr(value);
937          return;
938 
939       case DRAMC:
940          //somewhat unemulated
941          //missing bit 7 and 6
942          //debugLog("Set DRAMC, old value:0x%04X, new value:0x%04X, PC:0x%08X\n", registerArrayRead16(address), value, flx68000GetPc());
943          registerArrayWrite16(DRAMC, value & 0xFF3F);
944          updateCsdAddressLines();//the EDO bit can disable SDRAM access
945          return;
946 
947       case DRAMMC:
948          //unemulated, address line remapping, too CPU intensive to emulate
949          registerArrayWrite16(address, value);
950          return;
951 
952       case SDCTRL:
953          //missing bits 13, 9, 8 and 7
954          //debugLog("Set SDCTRL, old value:0x%04X, new value:0x%04X, PC:0x%08X\n", registerArrayRead16(address), value, flx68000GetPc());
955          registerArrayWrite16(SDCTRL, value & 0xDC7F);
956          updateCsdAddressLines();
957          return;
958 
959       case CSA:{
960             uint16_t oldCsa = registerArrayRead16(CSA);
961             bool oldBootMode = dbvzChipSelects[DBVZ_CHIP_A0_ROM].inBootMode;
962 
963             setCsa(value);
964 
965             //only reset address space if size changed, enabled/disabled or exiting boot mode
966             if((value & 0x000F) != (oldCsa & 0x000F) || dbvzChipSelects[DBVZ_CHIP_A0_ROM].inBootMode != oldBootMode)
967                dbvzResetAddressSpace();
968          }
969          return;
970 
971       case CSB:{
972             uint16_t oldCsb = registerArrayRead16(CSB);
973 
974             setCsb(value);
975 
976             //only reset address space if size changed or enabled/disabled
977             if((value & 0x000F) != (oldCsb & 0x000F))
978                dbvzResetAddressSpace();
979          }
980          return;
981 
982       case CSC:
983          registerArrayWrite16(CSC, value & 0xF9FF);
984          return;
985 
986       case CSD:{
987             uint16_t oldCsd = registerArrayRead16(CSD);
988 
989             setCsd(value);
990 
991             //CSD DRAM bit changed
992             if((value & 0x0200) != (oldCsd & 0x0200))
993                updateCsdAddressLines();
994 
995 
996             //only reset address space if size changed, enabled/disabled or DRAM bit changed
997             if((value & 0x020F) != (oldCsd & 0x020F))
998                dbvzResetAddressSpace();
999          }
1000          return;
1001 
1002       case CSGBA:
1003          //sets the starting location of ROM(0x10000000) and the PDIUSBD12 chip
1004          if((value & 0xFFFE) != registerArrayRead16(CSGBA)){
1005             setCsgba(value);
1006             dbvzResetAddressSpace();
1007          }
1008          return;
1009 
1010       case CSGBB:
1011          //sets the starting location of the SED1376(0x1FF80000)
1012          if((value & 0xFFFE) != registerArrayRead16(CSGBB)){
1013             setCsgbb(value);
1014             dbvzResetAddressSpace();
1015          }
1016          return;
1017 
1018       case CSGBC:
1019          registerArrayWrite16(CSGBC, value & 0xFFFE);
1020          return;
1021 
1022       case CSGBD:
1023          //sets the starting location of RAM(0x00000000)
1024          if((value & 0xFFFE) != registerArrayRead16(CSGBD)){
1025             setCsgbd(value);
1026             dbvzResetAddressSpace();
1027          }
1028          return;
1029 
1030       case CSUGBA:
1031          if((value & 0xF777) != registerArrayRead16(CSUGBA)){
1032             registerArrayWrite16(CSUGBA, value & 0xF777);
1033             //refresh all chip select address lines
1034             setCsgba(registerArrayRead16(CSGBA));
1035             setCsgbb(registerArrayRead16(CSGBB));
1036             setCsgbd(registerArrayRead16(CSGBD));
1037             dbvzResetAddressSpace();
1038          }
1039          return;
1040 
1041       case CSCTRL1:{
1042             uint16_t oldCsctrl1 = registerArrayRead16(CSCTRL1);
1043 
1044             registerArrayWrite16(CSCTRL1, value & 0x7F55);
1045 
1046             if((value & 0x4055) != (oldCsctrl1 & 0x4055)){
1047                //something important changed, update all chip selects
1048                //CSA is not dependent on CSCTRL1
1049                setCsb(registerArrayRead16(CSB));
1050                setCsd(registerArrayRead16(CSD));
1051                dbvzResetAddressSpace();
1052             }
1053          }
1054          return;
1055 
1056       case SPICONT1:
1057          setSpiCont1(value);
1058          return;
1059 
1060       case SPIINTCS:
1061          setSpiIntCs(value);
1062          return;
1063 
1064       case SPITEST:
1065          debugLog("SPITEST write not implented yet\n");
1066          return;
1067 
1068       case SPITXD:
1069          if(registerArrayRead16(SPICONT1) & 0x0200){
1070             spi1TxFifoWrite(value);
1071             //check if SPI1 interrupts changed
1072             setSpiIntCs(registerArrayRead16(SPIINTCS));
1073          }
1074          return;
1075 
1076       case SPICONT2:
1077          setSpiCont2(value);
1078          return;
1079 
1080       case SPIDATA2:
1081          //ignore writes when SPICONT2 ENABLE is not set
1082          if(registerArrayRead16(SPICONT2) & 0x0200)
1083             registerArrayWrite16(SPIDATA2, value);
1084          return;
1085 
1086       case USTCNT1:
1087          setUstcnt1(value);
1088          return;
1089 
1090       case UBAUD1:
1091          //just does timing stuff, should be OK to ignore
1092          registerArrayWrite16(UBAUD1, value & 0x2F3F);
1093          return;
1094 
1095       case UMISC1:
1096          //TODO: most of the bits here are for factory testing and can be ignored but not all of them can be
1097          registerArrayWrite16(UMISC1, value & 0xFCFC);
1098          return;
1099 
1100       case UTX1:
1101          registerArrayWrite16(UTX1, value & 0x1F00);
1102 
1103          //send byte and update interrupts if enabled
1104          if((registerArrayRead16(USTCNT1) & 0xA000) == 0xA000){
1105             uart1TxFifoWrite(value & 0x1000 ? value & 0xFF : EMU_SERIAL_BREAK);
1106             updateUart1Interrupt();
1107          }
1108          return;
1109 
1110       case USTCNT2:
1111          setUstcnt2(value);
1112          return;
1113 
1114       case UBAUD2:
1115          //just does timing stuff, should be OK to ignore
1116          registerArrayWrite16(UBAUD2, value & 0x2F3F);
1117          return;
1118 
1119       case UMISC2:
1120          //TODO: most of the bits here are for factory testing and can be ignored but not all of them can be
1121          registerArrayWrite16(UMISC2, value & 0xFCFC);
1122          return;
1123 
1124       case UTX2:
1125          registerArrayWrite16(UTX2, value & 0x1F00);
1126 
1127          //send byte and update interrupts if enabled
1128          if((registerArrayRead16(USTCNT2) & 0xA000) == 0xA000){
1129             uart2TxFifoWrite(value & 0x1000 ? value & 0xFF : EMU_SERIAL_BREAK);
1130             updateUart2Interrupt();
1131          }
1132          return;
1133 
1134       case HMARK:
1135          registerArrayWrite16(HMARK, value & 0x0F0F);
1136          updateUart2Interrupt();
1137          return;
1138 
1139       case PWMC1:
1140          setPwmc1(value);
1141          return;
1142 
1143       case PWMS1:
1144          //write only if PWM1 enabled
1145          if(registerArrayRead16(PWMC1) & 0x0010){
1146             pwm1FifoWrite(value >> 8);
1147             pwm1FifoWrite(value & 0xFF);
1148          }
1149          return;
1150 
1151       case NIPR1:
1152          //just does timing stuff, should be OK to ignore
1153          registerArrayWrite16(NIPR1, value & 0x87FF);
1154          return;
1155 
1156       case LXMAX:
1157          registerArrayWrite16(LXMAX, value & 0x03F0);
1158          return;
1159 
1160       case LYMAX:
1161          registerArrayWrite16(LYMAX, value & 0x01FF);
1162          return;
1163 
1164       case LCXP:
1165          registerArrayWrite16(LCXP, value & 0xC3FF);
1166          return;
1167 
1168       case LCYP:
1169          registerArrayWrite16(LCYP, value & 0x01FF);
1170          return;
1171 
1172       case LCWCH:
1173          registerArrayWrite16(LCWCH, value & 0x1F1F);
1174          return;
1175 
1176       case LRRA:
1177          registerArrayWrite16(LRRA, value & 0x03FF);
1178          return;
1179 
1180       case PWMR:
1181          registerArrayWrite16(PWMR, value & 0x07FF);
1182          return;
1183 
1184       case SPISPC:
1185       case TCMP1:
1186       case TCMP2:
1187       case TPRER1:
1188       case TPRER2:
1189          //simple write, no actions needed
1190          registerArrayWrite16(address, value);
1191          return;
1192 
1193       default:
1194          //writeable bootloader region
1195          if(address >= 0xFC0){
1196             registerArrayWrite16(address, value);
1197             return;
1198          }
1199 
1200          printHwRegAccess(address, value, 16, true);
1201          return;
1202    }
1203 }
1204 
dbvzSetRegister32(uint32_t address,uint32_t value)1205 void dbvzSetRegister32(uint32_t address, uint32_t value){
1206 #if !defined(EMU_NO_SAFETY)
1207    if((address & 0x0000F000) != 0x0000F000){
1208       dbvzSetBusErrorTimeOut(address, true);
1209       return;
1210    }
1211 #endif
1212 
1213    address &= 0x00000FFF;
1214 
1215    switch(address){
1216       case RTCTIME:
1217       case RTCALRM:
1218          registerArrayWrite32(address, value & 0x1F3F003F);
1219          return;
1220 
1221       case IDR:
1222       case IPR:
1223          //write to read only register, do nothing
1224          return;
1225 
1226       case ISR:
1227          setIsr(value, true, true);
1228          return;
1229 
1230       case IMR:
1231          registerArrayWrite32(IMR, value & 0x00FFFFFF);//Palm OS writes to reserved bits 14 and 15
1232          registerArrayWrite32(ISR, registerArrayRead32(IPR) & ~registerArrayRead32(IMR));
1233          checkInterrupts();
1234          return;
1235 
1236       case LSSA:
1237          registerArrayWrite32(address, value & 0xFFFFFFFE);
1238          return;
1239 
1240       default:
1241          //writeable bootloader region
1242          if(address >= 0xFC0){
1243             registerArrayWrite32(address, value);
1244             return;
1245          }
1246 
1247          printHwRegAccess(address, value, 32, true);
1248          return;
1249    }
1250 }
1251 
dbvzReset(void)1252 void dbvzReset(void){
1253    uint32_t oldRtc = registerArrayRead32(RTCTIME);//preserve RTCTIME
1254    uint16_t oldDayr = registerArrayRead16(DAYR);//preserve DAYR
1255 
1256    memset(dbvzReg, 0x00, DBVZ_REG_SIZE - DBVZ_BOOTLOADER_SIZE);
1257    dbvzSysclksPerClk32 = 0.0;
1258    clk32Counter = 0;
1259    pctlrCpuClockDivider = 1.0;
1260    pllSleepWait = -1;
1261    pllWakeWait = -1;
1262    timerCycleCounter[0] = 0.0;
1263    timerCycleCounter[1] = 0.0;
1264    timerStatusReadAcknowledge[0] = 0x0000;
1265    timerStatusReadAcknowledge[1] = 0x0000;
1266    portDInterruptLastValue = 0x00;
1267    memset(spi1RxFifo, 0x00, sizeof(spi1RxFifo));
1268    memset(spi1TxFifo, 0x00, sizeof(spi1TxFifo));
1269    spi1RxReadPosition = 0;
1270    spi1RxWritePosition = 0;
1271    spi1RxOverflowed = false;
1272    spi1TxReadPosition = 0;
1273    spi1TxWritePosition = 0;
1274    pwm1ClocksToNextSample = 0;
1275    memset(pwm1Fifo, 0x00, sizeof(pwm1Fifo));
1276    pwm1ReadPosition = 0;
1277    pwm1WritePosition = 0;
1278 
1279    memset(dbvzChipSelects, 0x00, sizeof(dbvzChipSelects));
1280    //all chip selects are disabled at boot and CSA0 is mapped to 0x00000000 and covers the entire address range until CSA is set enabled
1281    dbvzChipSelects[DBVZ_CHIP_A0_ROM].inBootMode = true;
1282 
1283    //default sizes
1284    dbvzChipSelects[DBVZ_CHIP_A0_ROM].lineSize = 0x20000;
1285    dbvzChipSelects[DBVZ_CHIP_A1_USB].lineSize = 0x20000;
1286    dbvzChipSelects[DBVZ_CHIP_B0_SED].lineSize = 0x20000;
1287    dbvzChipSelects[DBVZ_CHIP_DX_RAM].lineSize = 0x8000;
1288 
1289    //masks for reading and writing
1290    dbvzChipSelects[DBVZ_CHIP_A0_ROM].mask = 0x003FFFFF;//4mb
1291    dbvzChipSelects[DBVZ_CHIP_A1_USB].mask = 0x00000002;//A1 is used as USB chip A0
1292    dbvzChipSelects[DBVZ_CHIP_B0_SED].mask = 0x0001FFFF;
1293    dbvzChipSelects[DBVZ_CHIP_DX_RAM].mask = 0x00000000;//16mb, no RAM enabled until the DRAM module is initialized
1294 
1295    //system control
1296    registerArrayWrite8(SCR, 0x1C);
1297 
1298    //CPU ID
1299    registerArrayWrite32(IDR, 0x57000000);//value of IDR on actual hardware
1300 
1301    //I/O drive control //probably unused
1302    registerArrayWrite16(IODCR, 0x1FFF);
1303 
1304    //chip selects
1305    registerArrayWrite16(CSA, 0x00B0);
1306    registerArrayWrite16(CSD, 0x0200);
1307    registerArrayWrite16(EMUCS, 0x0060);
1308    registerArrayWrite16(CSCTRL2, 0x1000);
1309    registerArrayWrite16(CSCTRL3, 0x9C00);
1310 
1311    //phase lock loop
1312    registerArrayWrite16(PLLCR, 0x24B3);
1313    registerArrayWrite16(PLLFSR, 0x0347);
1314 
1315    //power control
1316    registerArrayWrite8(PCTLR, 0x1F);
1317 
1318    //interrupts
1319    registerArrayWrite32(IMR, 0x00FFFFFF);//the data sheet says 0x00FFFFFF and 0x00FF3FFF, using 0x00FFFFFF because thats how its set on the device
1320    registerArrayWrite16(ILCR, 0x6533);
1321 
1322    //GPIO ports
1323    registerArrayWrite8(PADATA, 0xFF);
1324    registerArrayWrite8(PAPUEN, 0xFF);
1325 
1326    registerArrayWrite8(PBDATA, 0xFF);
1327    registerArrayWrite8(PBPUEN, 0xFF);
1328    registerArrayWrite8(PBSEL, 0xFF);
1329 
1330    registerArrayWrite8(PCPDEN, 0xFF);
1331    registerArrayWrite8(PCSEL, 0xFF);
1332 
1333    registerArrayWrite8(PDDATA, 0xFF);
1334    registerArrayWrite8(PDPUEN, 0xFF);
1335    registerArrayWrite8(PDSEL, 0xF0);
1336 
1337    registerArrayWrite8(PEDATA, 0xFF);
1338    registerArrayWrite8(PEPUEN, 0xFF);
1339    registerArrayWrite8(PESEL, 0xFF);
1340 
1341    registerArrayWrite8(PFDATA, 0xFF);
1342    registerArrayWrite8(PFPUEN, 0xFF);
1343    registerArrayWrite8(PFSEL, 0x87);
1344 
1345    registerArrayWrite8(PGDATA, 0x3F);
1346    registerArrayWrite8(PGPUEN, 0x3D);
1347    registerArrayWrite8(PGSEL, 0x08);
1348 
1349    registerArrayWrite8(PJDATA, 0xFF);
1350    registerArrayWrite8(PJPUEN, 0xFF);
1351    registerArrayWrite8(PJSEL, 0xEF);
1352 
1353    registerArrayWrite8(PKDATA, 0x0F);
1354    registerArrayWrite8(PKPUEN, 0xFF);
1355    registerArrayWrite8(PKSEL, 0xFF);
1356 
1357    registerArrayWrite8(PMDATA, 0x20);
1358    registerArrayWrite8(PMPUEN, 0x3F);
1359    registerArrayWrite8(PMSEL, 0x3F);
1360 
1361    //pulse width modulation control
1362    //registerArrayWrite16(PWMC1, 0x0020);//FIFOAV is controlled by getPwmc1()
1363    registerArrayWrite8(PWMP1, 0xFE);
1364 
1365    //timers
1366    registerArrayWrite16(TCMP1, 0xFFFF);
1367    registerArrayWrite16(TCMP2, 0xFFFF);
1368 
1369    //serial I/O
1370    registerArrayWrite16(UBAUD1, 0x0002);
1371    registerArrayWrite16(UBAUD2, 0x0002);
1372    registerArrayWrite16(HMARK, 0x0102);
1373 
1374    //LCD control registers, unused since the SED1376 controls the LCD
1375    registerArrayWrite8(LVPW, 0xFF);
1376    registerArrayWrite16(LXMAX, 0x03F0);
1377    registerArrayWrite16(LYMAX, 0x01FF);
1378    registerArrayWrite16(LCWCH, 0x0101);
1379    registerArrayWrite8(LBLKC, 0x7F);
1380    registerArrayWrite16(LRRA, 0x00FF);
1381    registerArrayWrite8(LGPMR, 0x84);
1382    registerArrayWrite8(DMACR, 0x62);
1383 
1384    //realtime clock
1385    registerArrayWrite32(RTCTIME, oldRtc);//RTCTIME is not changed on reset
1386    registerArrayWrite16(WATCHDOG, 0x0001);
1387    registerArrayWrite16(RTCCTL, 0x0080);//conflicting size in datasheet, it says its 8 bit but provides 16 bit values
1388    registerArrayWrite16(STPWCH, 0x003F);//conflicting size in datasheet, it says its 8 bit but provides 16 bit values
1389    registerArrayWrite16(DAYR, oldDayr);//DAYR is not changed on reset
1390 
1391    //SDRAM control, unused since RAM refresh is unemulated
1392    registerArrayWrite16(SDCTRL, 0x003C);
1393 
1394    //move register settings to other I/O
1395    updatePowerButtonLedStatus();
1396    updateVibratorStatus();
1397    updateAds7846ChipSelectStatus();
1398    updateSdCardChipSelectStatus();
1399    if(!palmEmulatingM500)
1400       sed1376UpdateLcdStatus();
1401 
1402    dbvzSysclksPerClk32 = sysclksPerClk32();
1403 
1404    dbvzResetAddressSpace();
1405    checkInterrupts();
1406    flx68000Reset();
1407 }
1408 
dbvzLoadBootloader(uint8_t * data,uint32_t size)1409 void dbvzLoadBootloader(uint8_t* data, uint32_t size){
1410    uint16_t index;
1411 
1412    if(!data)
1413       size = 0;
1414 
1415    size = FAST_MIN(size, DBVZ_BOOTLOADER_SIZE);
1416 
1417    //copy size bytes from buffer to bootloader area
1418    for(index = 0; index < size; index++)
1419       registerArrayWrite8(DBVZ_REG_SIZE - DBVZ_BOOTLOADER_SIZE + index, data[index]);
1420 
1421    //fill remainig space with 0x00
1422    for(; index < DBVZ_BOOTLOADER_SIZE; index++)
1423       registerArrayWrite8(DBVZ_REG_SIZE - DBVZ_BOOTLOADER_SIZE + index, 0x00);
1424 }
1425 
dbvzSetRtc(uint16_t days,uint8_t hours,uint8_t minutes,uint8_t seconds)1426 void dbvzSetRtc(uint16_t days, uint8_t hours, uint8_t minutes, uint8_t seconds){
1427    registerArrayWrite32(RTCTIME, hours << 24 & 0x1F000000 | minutes << 16 & 0x003F0000 | seconds & 0x0000003F);
1428    registerArrayWrite16(DAYR, days & 0x01FF);
1429 }
1430 
dbvzStateSize(void)1431 uint32_t dbvzStateSize(void){
1432    uint32_t size = 0;
1433 
1434    size += flx68000StateSize();
1435    size += DBVZ_REG_SIZE;//hardware registers
1436    size += DBVZ_TOTAL_MEMORY_BANKS;
1437    size += sizeof(uint32_t) * 4 * DBVZ_CHIP_END;//chip select states
1438    size += sizeof(uint8_t) * 5 * DBVZ_CHIP_END;//chip select states
1439    size += sizeof(uint64_t) * 5;//32.32 fixed point double, timerXCycleCounter and CPU cycle timers
1440    size += sizeof(int8_t);//pllSleepWait
1441    size += sizeof(int8_t);//pllWakeWait
1442    size += sizeof(uint32_t);//clk32Counter
1443    size += sizeof(uint64_t);//pctlrCpuClockDivider
1444    size += sizeof(uint16_t) * 2;//timerStatusReadAcknowledge
1445    size += sizeof(uint8_t);//portDInterruptLastValue
1446    size += sizeof(uint16_t) * 9;//RX 8 * 16 SPI1 FIFO, 1 index is for FIFO full
1447    size += sizeof(uint16_t) * 9;//TX 8 * 16 SPI1 FIFO, 1 index is for FIFO full
1448    size += sizeof(uint8_t) * 5;//spi1(R/T)x(Read/Write)Position / spi1RxOverflowed
1449    size += sizeof(int32_t);//pwm1ClocksToNextSample
1450    size += sizeof(uint8_t) * 6;//pwm1Fifo[6]
1451    size += sizeof(uint8_t) * 2;//pwm1(Read/Write)
1452 
1453    return size;
1454 }
1455 
dbvzSaveState(uint8_t * data)1456 void dbvzSaveState(uint8_t* data){
1457    uint32_t offset = 0;
1458    uint8_t index;
1459 
1460    //CPU core
1461    flx68000SaveState(data + offset);
1462    offset += flx68000StateSize();
1463 
1464    //memory
1465    memcpy(data + offset, dbvzReg, DBVZ_REG_SIZE);
1466    swap16BufferIfLittle(data + offset, DBVZ_REG_SIZE / sizeof(uint16_t));
1467    offset += DBVZ_REG_SIZE;
1468    memcpy(data + offset, dbvzBankType, DBVZ_TOTAL_MEMORY_BANKS);
1469    offset += DBVZ_TOTAL_MEMORY_BANKS;
1470    for(index = DBVZ_CHIP_BEGIN; index < DBVZ_CHIP_END; index++){
1471       writeStateValue8(data + offset, dbvzChipSelects[index].enable);
1472       offset += sizeof(uint8_t);
1473       writeStateValue32(data + offset, dbvzChipSelects[index].start);
1474       offset += sizeof(uint32_t);
1475       writeStateValue32(data + offset, dbvzChipSelects[index].lineSize);
1476       offset += sizeof(uint32_t);
1477       writeStateValue32(data + offset, dbvzChipSelects[index].mask);
1478       offset += sizeof(uint32_t);
1479       writeStateValue8(data + offset, dbvzChipSelects[index].inBootMode);
1480       offset += sizeof(uint8_t);
1481       writeStateValue8(data + offset, dbvzChipSelects[index].readOnly);
1482       offset += sizeof(uint8_t);
1483       writeStateValue8(data + offset, dbvzChipSelects[index].readOnlyForProtectedMemory);
1484       offset += sizeof(uint8_t);
1485       writeStateValue8(data + offset, dbvzChipSelects[index].supervisorOnlyProtectedMemory);
1486       offset += sizeof(uint8_t);
1487       writeStateValue32(data + offset, dbvzChipSelects[index].unprotectedSize);
1488       offset += sizeof(uint32_t);
1489    }
1490 
1491    //timing
1492    writeStateValueDouble(data + offset, dbvzSysclksPerClk32);
1493    offset += sizeof(uint64_t);
1494    writeStateValueDouble(data + offset, palmCycleCounter);
1495    offset += sizeof(uint64_t);
1496    writeStateValueDouble(data + offset, palmClockMultiplier);
1497    offset += sizeof(uint64_t);
1498    writeStateValue8(data + offset, pllSleepWait);
1499    offset += sizeof(int8_t);
1500    writeStateValue8(data + offset, pllWakeWait);
1501    offset += sizeof(int8_t);
1502    writeStateValue32(data + offset, clk32Counter);
1503    offset += sizeof(uint32_t);
1504    writeStateValueDouble(data + offset, pctlrCpuClockDivider);
1505    offset += sizeof(uint64_t);
1506    writeStateValueDouble(data + offset, timerCycleCounter[0]);
1507    offset += sizeof(uint64_t);
1508    writeStateValueDouble(data + offset, timerCycleCounter[1]);
1509    offset += sizeof(uint64_t);
1510    writeStateValue16(data + offset, timerStatusReadAcknowledge[0]);
1511    offset += sizeof(uint16_t);
1512    writeStateValue16(data + offset, timerStatusReadAcknowledge[1]);
1513    offset += sizeof(uint16_t);
1514    writeStateValue8(data + offset, portDInterruptLastValue);
1515    offset += sizeof(uint8_t);
1516 
1517    //SPI1
1518    for(index = 0; index < 9; index++){
1519       writeStateValue16(data + offset, spi1RxFifo[index]);
1520       offset += sizeof(uint16_t);
1521    }
1522    for(index = 0; index < 9; index++){
1523       writeStateValue16(data + offset, spi1TxFifo[index]);
1524       offset += sizeof(uint16_t);
1525    }
1526    writeStateValue8(data + offset, spi1RxReadPosition);
1527    offset += sizeof(uint8_t);
1528    writeStateValue8(data + offset, spi1RxWritePosition);
1529    offset += sizeof(uint8_t);
1530    writeStateValue8(data + offset, spi1RxOverflowed);
1531    offset += sizeof(uint8_t);
1532    writeStateValue8(data + offset, spi1TxReadPosition);
1533    offset += sizeof(uint8_t);
1534    writeStateValue8(data + offset, spi1TxWritePosition);
1535    offset += sizeof(uint8_t);
1536 
1537    //PWM1, audio
1538    writeStateValue32(data + offset, pwm1ClocksToNextSample);
1539    offset += sizeof(int32_t);
1540    for(index = 0; index < 6; index++){
1541       writeStateValue8(data + offset, pwm1Fifo[index]);
1542       offset += sizeof(uint8_t);
1543    }
1544    writeStateValue8(data + offset, pwm1ReadPosition);
1545    offset += sizeof(uint8_t);
1546    writeStateValue8(data + offset, pwm1WritePosition);
1547    offset += sizeof(uint8_t);
1548 }
1549 
dbvzLoadState(uint8_t * data)1550 void dbvzLoadState(uint8_t* data){
1551    uint32_t offset = 0;
1552    uint8_t index;
1553 
1554    //CPU core
1555    flx68000LoadState(data + offset);
1556    offset += flx68000StateSize();
1557 
1558    //memory
1559    memcpy(dbvzReg, data + offset, DBVZ_REG_SIZE);
1560    swap16BufferIfLittle(dbvzReg, DBVZ_REG_SIZE / sizeof(uint16_t));
1561    offset += DBVZ_REG_SIZE;
1562    memcpy(dbvzBankType, data + offset, DBVZ_TOTAL_MEMORY_BANKS);
1563    offset += DBVZ_TOTAL_MEMORY_BANKS;
1564    for(index = DBVZ_CHIP_BEGIN; index < DBVZ_CHIP_END; index++){
1565       dbvzChipSelects[index].enable = readStateValue8(data + offset);
1566       offset += sizeof(uint8_t);
1567       dbvzChipSelects[index].start = readStateValue32(data + offset);
1568       offset += sizeof(uint32_t);
1569       dbvzChipSelects[index].lineSize = readStateValue32(data + offset);
1570       offset += sizeof(uint32_t);
1571       dbvzChipSelects[index].mask = readStateValue32(data + offset);
1572       offset += sizeof(uint32_t);
1573       dbvzChipSelects[index].inBootMode = readStateValue8(data + offset);
1574       offset += sizeof(uint8_t);
1575       dbvzChipSelects[index].readOnly = readStateValue8(data + offset);
1576       offset += sizeof(uint8_t);
1577       dbvzChipSelects[index].readOnlyForProtectedMemory = readStateValue8(data + offset);
1578       offset += sizeof(uint8_t);
1579       dbvzChipSelects[index].supervisorOnlyProtectedMemory = readStateValue8(data + offset);
1580       offset += sizeof(uint8_t);
1581       dbvzChipSelects[index].unprotectedSize = readStateValue32(data + offset);
1582       offset += sizeof(uint32_t);
1583    }
1584 
1585    //timing
1586    dbvzSysclksPerClk32 = readStateValueDouble(data + offset);
1587    offset += sizeof(uint64_t);
1588    palmCycleCounter = readStateValueDouble(data + offset);
1589    offset += sizeof(uint64_t);
1590    palmClockMultiplier = readStateValueDouble(data + offset);
1591    offset += sizeof(uint64_t);
1592    pllSleepWait = readStateValue8(data + offset);
1593    offset += sizeof(int8_t);
1594    pllWakeWait = readStateValue8(data + offset);
1595    offset += sizeof(int8_t);
1596    clk32Counter = readStateValue32(data + offset);
1597    offset += sizeof(uint32_t);
1598    pctlrCpuClockDivider = readStateValueDouble(data + offset);
1599    offset += sizeof(uint64_t);
1600    timerCycleCounter[0] = readStateValueDouble(data + offset);
1601    offset += sizeof(uint64_t);
1602    timerCycleCounter[1] = readStateValueDouble(data + offset);
1603    offset += sizeof(uint64_t);
1604    timerStatusReadAcknowledge[0] = readStateValue16(data + offset);
1605    offset += sizeof(uint16_t);
1606    timerStatusReadAcknowledge[1] = readStateValue16(data + offset);
1607    offset += sizeof(uint16_t);
1608    portDInterruptLastValue = readStateValue8(data + offset);
1609    offset += sizeof(uint8_t);
1610 
1611    //SPI1
1612    for(index = 0; index < 9; index++){
1613       spi1RxFifo[index] = readStateValue16(data + offset);
1614       offset += sizeof(uint16_t);
1615    }
1616    for(index = 0; index < 9; index++){
1617       spi1TxFifo[index] = readStateValue16(data + offset);
1618       offset += sizeof(uint16_t);
1619    }
1620    spi1RxReadPosition = readStateValue8(data + offset);
1621    offset += sizeof(uint8_t);
1622    spi1RxWritePosition = readStateValue8(data + offset);
1623    offset += sizeof(uint8_t);
1624    spi1RxOverflowed = readStateValue8(data + offset);
1625    offset += sizeof(uint8_t);
1626    spi1TxReadPosition = readStateValue8(data + offset);
1627    offset += sizeof(uint8_t);
1628    spi1TxWritePosition = readStateValue8(data + offset);
1629    offset += sizeof(uint8_t);
1630 
1631    //PWM1, audio
1632    pwm1ClocksToNextSample = readStateValue32(data + offset);
1633    offset += sizeof(int32_t);
1634    for(index = 0; index < 6; index++){
1635       pwm1Fifo[index] = readStateValue8(data + offset);
1636       offset += sizeof(uint8_t);
1637    }
1638    pwm1ReadPosition = readStateValue8(data + offset);
1639    offset += sizeof(uint8_t);
1640    pwm1WritePosition = readStateValue8(data + offset);
1641    offset += sizeof(uint8_t);
1642 
1643    //UART1, cant load state while beaming
1644    uart1RxFifoFlush();
1645 
1646    //UART2, cant load state while syncing
1647    uart2RxFifoFlush();
1648 }
1649 
dbvzLoadStateFinished(void)1650 void dbvzLoadStateFinished(void){
1651    flx68000LoadStateFinished();
1652 }
1653 
dbvzExecute(void)1654 void dbvzExecute(void){
1655    uint32_t samples;
1656 
1657    //I/O
1658    m5XXRefreshInputState();
1659 
1660    //CPU
1661    dbvzFrameClk32s = 0;
1662    for(; palmCycleCounter < (double)M5XX_CRYSTAL_FREQUENCY / EMU_FPS; palmCycleCounter += 1.0){
1663       uint8_t cpuTimeSegments;
1664 
1665       dbvzBeginClk32();
1666 
1667       for(cpuTimeSegments = 0; cpuTimeSegments < 2; cpuTimeSegments++){
1668          double cyclesRemaining = dbvzSysclksPerClk32 / 2.0;
1669 
1670          while(cyclesRemaining >= 1.0){
1671             double sysclks = FAST_MIN(cyclesRemaining, DBVZ_SYSCLK_PRECISION);
1672             int32_t cpuCycles = sysclks * pctlrCpuClockDivider * palmClockMultiplier;
1673 
1674             if(cpuCycles > 0)
1675                flx68000Execute(cpuCycles);
1676             dbvzAddSysclks(sysclks);
1677 
1678             cyclesRemaining -= sysclks;
1679          }
1680 
1681          //toggle CLK32 bit in PLLFSR, it indicates the current state of CLK32 so it must start false and be changed to true in the middle of CLK32
1682          registerArrayWrite16(PLLFSR, registerArrayRead16(PLLFSR) ^ 0x8000);
1683       }
1684 
1685       dbvzEndClk32();
1686       dbvzFrameClk32s++;
1687    }
1688    palmCycleCounter -= (double)M5XX_CRYSTAL_FREQUENCY / EMU_FPS;
1689 
1690    //audio
1691    blip_end_frame(palmAudioResampler, blip_clocks_needed(palmAudioResampler, AUDIO_SAMPLES_PER_FRAME));
1692    blip_read_samples(palmAudioResampler, palmAudio, AUDIO_SAMPLES_PER_FRAME, true);
1693    MULTITHREAD_LOOP(samples) for(samples = 0; samples < AUDIO_SAMPLES_PER_FRAME * 2; samples += 2)
1694       palmAudio[samples + 1] = palmAudio[samples];
1695 }
1696