- fix display FIFO;
- more accurate RTC implementation (is working more correct with Homebrew now);
This commit is contained in:
mtabachenko 2009-01-20 21:31:32 +00:00
parent 36132978f5
commit a0c3c02ea9
4 changed files with 239 additions and 195 deletions

View File

@ -2,7 +2,8 @@
yopyop156@ifrance.com
yopyop156.ifrance.com
Copyright (C) 2007 shash
Copyright 2007 shash
Copyright 2007-2009 DeSmuME team
This file is part of DeSmuME
@ -18,7 +19,7 @@
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "FIFO.h"
@ -191,6 +192,7 @@ void DISP_FIFOsend(u32 val)
u32 DISP_FIFOrecv()
{
if (disp_fifo.tail == disp_fifo.head) return (0); // FIFO is empty
u32 val = disp_fifo.buf[disp_fifo.head];
disp_fifo.head++;
if (disp_fifo.head > 0x5FFF)

View File

@ -3181,7 +3181,10 @@ void GPU_ligne(NDS_Screen * screen, u16 l)
}
if (gpu->core == GPU_MAIN)
{
GPU_ligne_DispCapture(l);
if (l == 192) { disp_fifo.head = disp_fifo.tail = 0; }
}
GPU_ligne_MasterBrightness(screen, l);
}

View File

@ -2,7 +2,8 @@
yopyop156@ifrance.com
yopyop156.ifrance.com
Copyright (C) 2006-2008 DeSmuME team
Copyright 2008 CrazyMax
Copyright 2008-2009 DeSmuME team
This file is part of DeSmuME
@ -18,9 +19,11 @@
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
// TODO: interrupt handler
#include "rtc.h"
#include "common.h"
#include "debug.h"
@ -28,233 +31,268 @@
#include <time.h>
#include <string.h>
const u8 valRTC[100]= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99 };
const u8 cmdSizes[8] = {1, 7, 3, 1, 3, 1, 1};
typedef struct
{
u16 reg;
// RTC registers
u8 regStatus1;
u8 regStatus2;
u8 regAdjustment;
u8 regFree;
// BUS
u8 _prevSCK;
u8 _prevCS;
u8 _prevSIO;
u8 _SCK;
u8 _CS;
u8 _SIO;
u8 _DD;
u16 _REG;
// command & data
u8 cmd;
u8 dataWrite;
u8 bitPosWrite;
u32 dataRead1;
u32 dataRead2;
u8 bitPosRead;
u8 bitSizeRead;
u8 cmdSize;
u8 stat; // 0 - write, 1 - read
u8 cmdStat;
u8 bitsCount;
u8 data[8];
} _RTC;
_RTC rtc;
void rtcPost(u8 data);
u8 cmdBitsSize[8] = {8, 8, 56, 24, 0, 24, 8, 8};
void rtcInit()
#define toBCD(x) ((x / 10) << 4) | (x % 10);
void rtcRecv()
{
memset(&rtc, 0, sizeof(_RTC));
}
//====================================================== RTC write
INLINE void rtcPost(u8 data)
{
if (rtc.cmdSize == 0)
{
if (rtc.bitPosRead != rtc.bitSizeRead) return;
rtc.bitPosRead = 0;
if ((data & 0x0F) == 0x06)
rtc.cmd = reverseBitsInByte(data);
else
if ((data & 0xF0) == 0x60)
rtc.cmd = data;
else
{
//INFO("RTC ERROR: command not supported\n");
return;
}
rtc.stat = (rtc.cmd & 0x01);
rtc.cmd = (rtc.cmd & 0x0E)>>1;
//INFO("+++++RTC: execute command 0x%02X (%s)\n", rtc.cmd, rtc.stat?"read":"write");
if (!rtc.stat)
{
rtc.cmdSize = cmdSizes[rtc.cmd];
return;
}
else
rtc.cmdSize = 0;
if (rtc.stat)
{
rtc.bitSizeRead = 8;
rtc.dataRead1 = 0;
rtc.dataRead2 = 0;
//INFO("RTC: read %X\n", rtc.cmd);
switch (rtc.cmd)
{
case 0: // status register 1
//INFO("RTC: read status 1 (%X) %s\n", rtc.regStatus1, rtc.revBits?"rev":"fwd");
rtc.dataRead1 = rtc.regStatus1;
rtc.regStatus1 &= 0x0F;
break;
case 1: // status register 2
//INFO("RTC: read status 2 %s\n", rtc.revBits?"rev":"fwd");
rtc.dataRead1 = rtc.regStatus2;
break;
case 2: // date & time
{
time_t tm;
time(&tm);
struct tm *tm_local= localtime(&tm);
u8 hour = tm_local->tm_hour, noon=0;
if (hour>11)
{
hour-=12;
noon=1;
}
rtc.dataRead2 = ( ((valRTC[hour]) << 0)
//| (noon << 7)
| (valRTC[tm_local->tm_min] << 8)
| (valRTC[tm_local->tm_sec] << 16));
rtc.dataRead1 = ( (valRTC[tm_local->tm_year-100] << 0)
| (valRTC[tm_local->tm_mon+1] << 8)
| (valRTC[tm_local->tm_mday] << 16)
| (valRTC[tm_local->tm_wday] << 24));
rtc.bitSizeRead = 7 << 3;
break;
}
case 3: // time
{
//INFO("RTC: read time\n");
time_t tm;
time(&tm);
struct tm *tm_local= localtime(&tm);
u8 hour = tm_local->tm_hour, noon=0;
if (hour>11)
{
hour-=12;
noon=1;
}
rtc.dataRead1 = ( ((valRTC[hour]) << 0)
//| (noon << 6)
| (valRTC[tm_local->tm_min] << 8)
| (valRTC[tm_local->tm_sec] << 16));
rtc.bitSizeRead = 3 << 3;
break;
}
case 4: // freq/alarm 1
//INFO("RTC: read freq");
break;
case 5: // alarm 2
//INFO("RTC: read alarm 2\n");
break;
case 6: // clock adjust
//INFO("RTC: read clock adjust\n");
break;
case 7: // free register
//INFO("RTC: read free register\n");
break;
default:
rtc.bitSizeRead = 0;
break;
}
}
return;
}
rtc.cmdSize--;
//INFO("RTC: write %X val=%X\n", rtc.cmd, data);
//INFO("RTC Read command 0x%02X\n", rtc.cmd);
memset(rtc.data, 0, sizeof(rtc.data));
switch (rtc.cmd)
{
case 0: // status1
//INFO("RTC: write status 1 (%X)\n", data);
rtc.regStatus1 = data;
if (rtc.regStatus1 & 0x10)
{
//INFO("IRQ7\n");
NDS_makeARM7Int(7);
}
case 0: // status register 1
//INFO("RTC: read regstatus1 (0x%02X)\n", rtc.regStatus1);
rtc.data[0] = rtc.regStatus1;
rtc.regStatus1 &= 0x7F;
break;
case 1: // status register 2
rtc.regStatus2 = data;
//INFO("RTC: write status 2 (%X)\n", data);
//INFO("RTC: read regstatus2 (0x%02X)\n", rtc.regStatus1);
rtc.data[0] = rtc.regStatus2;
break;
case 2: // date & time
//INFO("RTC: write date & time (%X)\n", data);
break;
{
//INFO("RTC: read date & time\n");
time_t tm;
time(&tm);
struct tm *tm_local= localtime(&tm);
tm_local->tm_year %= 100;
tm_local->tm_mon++;
rtc.data[0] = toBCD(tm_local->tm_year);
rtc.data[1] = toBCD(tm_local->tm_mon);
rtc.data[2] = toBCD(tm_local->tm_mday);
rtc.data[3] = (tm_local->tm_wday + 6) & 7;
if (!(rtc.regStatus1 & 0x02))
{
rtc.data[4] = (tm_local->tm_hour < 12)?0x00:0x40;
tm_local->tm_hour %= 12;
}
rtc.data[4] |= toBCD(tm_local->tm_hour);
rtc.data[5] = toBCD(tm_local->tm_min);
rtc.data[6] = toBCD(tm_local->tm_sec);
break;
}
case 3: // time
//INFO("RTC: write time (%X)\n", data);
break;
{
//INFO("RTC: read time\n");
time_t tm;
time(&tm);
struct tm *tm_local= localtime(&tm);
if (!(rtc.regStatus1 & 0x02))
{
rtc.data[4] = (tm_local->tm_hour < 12)?0x00:0x40;
tm_local->tm_hour %= 12;
}
rtc.data[0] |= toBCD(tm_local->tm_hour);
rtc.data[1] = toBCD(tm_local->tm_min);
rtc.data[2] = toBCD(tm_local->tm_sec);
break;
}
case 4: // freq/alarm 1
//INFO("RTC: write freq (%X)", data);
/*if (cmdBitsSize[0x04] == 8)
INFO("RTC: read INT1 freq\n");
else
INFO("RTC: read INT1 alarm1\n");*/
//NDS_makeARM7Int(7);
break;
case 5: // alarm 2
//INFO("RTC: write alarm 2 (%X)\n", data);
//INFO("RTC: read alarm 2\n");
break;
case 6: // clock adjust
//INFO("RTC: write clock adjust (%X)\n", data);
//INFO("RTC: read clock adjust\n");
rtc.data[0] = rtc.regAdjustment;
break;
case 7: // free register
//INFO("RTC: write free register (%X)\n", data);
//INFO("RTC: read free register\n");
rtc.data[0] = rtc.regFree;
break;
}
}
u8 rtcRead()
void rtcSend()
{
u8 val;
//INFO("RTC write 0x%02X\n", rtc.cmd);
switch (rtc.cmd)
{
case 0: // status register 1
//INFO("RTC: write regstatus1 0x%02X\n", rtc.data[0]);
rtc.regStatus1 &= 0xF1;
rtc.regStatus1 |= (rtc.data[0] | 0x0E);
break;
case 1: // status register 2
//INFO("RTC: write regstatus2 0x%02X\n", rtc.data[0]);
rtc.regStatus2 = rtc.data[0];
break;
case 2: // date & time
//INFO("RTC: write date & time\n");
break;
case 3: // time
//INFO("RTC: write time\n");
break;
case 4: // freq/alarm 1
/*if (cmdBitsSize[0x04] == 8)
INFO("RTC: write INT1 freq 0x%02X\n", rtc.data[0]);
else
INFO("RTC: write INT1 alarm1 0x%02X\n", rtc.data[0]);*/
break;
case 5: // alarm 2
//INFO("RTC: write alarm 2\n");
break;
case 6: // clock adjust
//INFO("RTC: write clock adjust\n");
rtc.regAdjustment = rtc.data[0];
break;
case 7: // free register
//INFO("RTC: write free register\n");
rtc.regFree = rtc.data[0];
break;
}
}
if (rtc.bitPosRead == rtc.bitSizeRead)
rtcPost(rtc.cmd);
void rtcInit()
{
memset(&rtc, 0, sizeof(_RTC));
rtc.regStatus1 |= 0x02;
}
if (rtc.bitPosRead > 31)
val = ((rtc.dataRead2 >> rtc.bitPosRead) & 0x01);
else
val = ((rtc.dataRead1 >> rtc.bitPosRead) & 0x01);
rtc.bitPosRead++;
return val;
u8 rtcRead()
{
//INFO("MMU Read RTC 0x%02X (%03i)\n", rtc._REG, rtc.bitsCount);
return (rtc._REG);
}
void rtcWrite(u16 val)
{
rtc.reg = val;
//INFO("MMU Write RTC 0x%02X (%03i)\n", val, rtc.bitsCount);
rtc._DD = (val & 0x10) >> 4;
rtc._SIO = rtc._DD?(val & 0x01):rtc._prevSIO;
rtc._SCK = (val & 0x20)?((val & 0x02) >> 1):rtc._prevSCK;
rtc._CS = (val & 0x40)?((val & 0x04) >> 2):rtc._prevCS;
if (!(rtc.reg & 0x02))
switch (rtc.cmdStat)
{
rtc.dataWrite |= ((val & 0x01) << rtc.bitPosWrite);
rtc.bitPosWrite++;
if (rtc.bitPosWrite == 8)
{
//INFO("RTC: write\n");
rtcPost(rtc.dataWrite);
rtc.bitPosWrite = 0;
rtc.dataWrite = 0;
}
case 0:
if ( (!rtc._prevCS) && (rtc._prevSCK) && (rtc._CS) && (rtc._SCK) )
{
rtc.cmdStat = 1;
rtc.bitsCount = 0;
rtc.cmd = 0;
}
break;
case 1:
if (!rtc._CS)
{
rtc.cmdStat = 0;
break;
}
if (rtc._SCK && rtc._DD) break;
if (!rtc._SCK && !rtc._DD) break;
rtc.cmd |= (rtc._SIO << rtc.bitsCount );
rtc.bitsCount ++;
if (rtc.bitsCount == 7)
{
if ( (rtc.cmd & 0x06) != 0x06 )
{
rtc.cmdStat = 0;
//INFO("RTC uknown command 0x02%X\n", rtc.cmd);
break;
}
rtc.cmdStat = 2;
rtc.cmd >>= 4;
rtc.cmd &= 0x07;
//INFO("RTC command 0x%02X\n", rtc.cmd);
}
break;
case 2:
if (!rtc._CS)
{
rtc.cmdStat = 0;
break;
}
if((rtc._prevSCK) && (!rtc._SCK))
{
rtc.bitsCount = 0;
if (rtc.cmd == 0x04)
{
if (rtc.regStatus2 & 0x0F == 0x04)
cmdBitsSize[rtc.cmd] = 24;
else
cmdBitsSize[rtc.cmd] = 8;
}
if (rtc._SIO)
{
rtc.cmdStat = 4;
rtcRecv();
}
else
{
rtc.cmdStat = 3;
}
}
break;
case 3: // write:
if( (rtc._prevSCK) && (!rtc._SCK) )
{
if(rtc._SIO) rtc.data[rtc.bitsCount >> 3] |= (1 << (rtc.bitsCount & 0x07));
rtc.bitsCount++;
if (rtc.bitsCount == cmdBitsSize[rtc.cmd])
{
rtcSend();
rtc.cmdStat = 0;
}
}
break;
case 4: // read:
if( (rtc._prevSCK) && (!rtc._SCK) )
{
rtc._REG = val;
if(rtc.data[rtc.bitsCount >> 3] >> (rtc.bitsCount & 0x07) & 0x01)
rtc._REG |= 0x01;
else
rtc._REG &= ~0x01;
rtc.bitsCount++;
if (rtc.bitsCount == cmdBitsSize[rtc.cmd])
rtc.cmdStat = 0;
}
break;
}
rtc._prevSIO = rtc._SIO;
rtc._prevSCK = rtc._SCK;
rtc._prevCS = rtc._CS;
}

View File

@ -2,7 +2,8 @@
yopyop156@ifrance.com
yopyop156.ifrance.com
Copyright (C) 2006-2008 DeSmuME team
Copyright 2008 CrazyMax
Copyright 2008-2009 DeSmuME team
This file is part of DeSmuME
@ -18,7 +19,7 @@
You should have received a copy of the GNU General Public License
along with DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _RTC_H_