From 36dcd1065878b6a80338f1fbb0258c00a143c4dc Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Sun, 29 Oct 2017 12:41:49 +0800 Subject: [PATCH] Get sound working; add partial updates (scanlines) to gfx driver --- components/tme-esp32/adns9500.c | 2 +- components/tme-esp32/mipi_lcd.c | 107 ++++++++++++++++++++++---------- components/tme-esp32/snd.c | 61 ++++++++++++------ components/tme/emu.c | 31 ++++----- 4 files changed, 134 insertions(+), 67 deletions(-) diff --git a/components/tme-esp32/adns9500.c b/components/tme-esp32/adns9500.c index de92d1a..cf63656 100644 --- a/components/tme-esp32/adns9500.c +++ b/components/tme-esp32/adns9500.c @@ -101,7 +101,7 @@ void adns900_get_dxdybtn(int *x, int *y, int *btn) { sy|=adnsRead(0x6)<<8; ets_delay_us(100); *btn=gpio_get_level(ADNS_MISO)?0:1; - if (sx!=0 || sy!=0) printf("Mouse: %hd %hd %d\n", sx, sy, *btn); +// if (sx!=0 || sy!=0) printf("Mouse: %hd %hd %d\n", sx, sy, *btn); *x=sx; *y=sy; } diff --git a/components/tme-esp32/mipi_lcd.c b/components/tme-esp32/mipi_lcd.c index 9e89c84..b46b57c 100644 --- a/components/tme-esp32/mipi_lcd.c +++ b/components/tme-esp32/mipi_lcd.c @@ -62,10 +62,13 @@ static const DispPacket initPackets[]={ }; +#define DO_RESCALE 1 - +#if DO_RESCALE #define SCALE_FACT 51 //Floating-point number, actually x/32. Divide mac reso by this to get lcd reso. - +#else +#define SCALE_FACT 32 +#endif static uint8_t mask[512]; static void calcLut() { @@ -115,7 +118,7 @@ static int IRAM_ATTR findMacVal(uint8_t *data, int x, int y) { // // Due to the weird buildup, a horizontal subpixel actually is 1/3rd real pixel wide! -#if 1 +#if DO_RESCALE static int IRAM_ATTR findPixelVal(uint8_t *data, int x, int y) { int sx=(x*SCALE_FACT); //32th is 512/320 -> scale 512 mac screen to 320 width @@ -177,50 +180,88 @@ static void initLcd() { printf("Display inited.\n"); } +static inline void setColRange(int xstart, int xend) { + uint8_t cmd[5]; + //No idea why the *2... maybe per byte? + xstart=xstart*2; + xend=xend*2; + cmd[0]=0x2a; //set_col_addr + cmd[1]=(xstart>>8); //scolh + cmd[2]=(xstart&0xff); //scoll + cmd[3]=(xend>>8); //ecolh + cmd[4]=(xend&0xff); //ecoll + mipiDsiSendLong(0x39, cmd, 5); +} + +static inline void setRowRange(int ystart, int yend) { + uint8_t cmd[5]; + cmd[0]=0x2b; //set_page_addr + cmd[1]=(ystart>>8); //scolh + cmd[2]=(ystart&0xff); //scoll + cmd[3]=(yend>>8); //ecolh + cmd[4]=(yend&0xff); //ecoll + mipiDsiSendLong(0x39, cmd, 5); +} + static void IRAM_ATTR displayTask(void *arg) { uint8_t *img=malloc((LINESPERBUF*320*2)+1); assert(img); calcLut(); uint8_t cmd[5]; + uint8_t *oldImg=malloc(512*342/8); int firstrun=1; + setColRange(0, 319); while(1) { int l=0; mipiResync(); xSemaphoreTake(dispSem, portMAX_DELAY); -#if 0 - cmd[0]=0x2a; //set_col_addr - cmd[1]=0; //scolh - cmd[2]=40; //scoll - cmd[3]=(320>>8); //ecolh - cmd[4]=(320&0xff); //ecoll - mipiDsiSendLong(0x39, cmd, 4); - - cmd[0]=0x2b; //set_row_addr - cmd[1]=0; //scolh - cmd[2]=40; //scoll - cmd[3]=(320>>8); //ecolh - cmd[4]=(320&0xff); //ecoll - mipiDsiSendLong(0x39, cmd, 4); -#endif uint8_t *myData=(uint8_t*)currFbPtr; - img[0]=0x2c; - uint8_t *p=&img[1]; - for (int j=0; j<319; j++) { - for (int i=0; i<320; i++) { - int v=findPixelVal(myData, i, j); - *p++=(v&0xff); - *p++=(v>>8); + + int xstart, xend, ystart, yend; + if (!firstrun) { + xstart=0; xend=320; + for (ystart=0; ystart<342; ystart++) { + if (memcmp(oldImg+64*ystart, myData+64*ystart, 64)!=0) break; } - l++; - if (l>=LINESPERBUF || j==319) { - mipiDsiSendLong(0x39, img, (LINESPERBUF*320*2)+1); - img[0]=0x3c; - l=0; - p=&img[1]; - if (!firstrun && j>=200) break; //no need to render black bar in subsequent times - firstrun=0; + for (yend=342-1; yend>=ystart; --yend) { + if (memcmp(oldImg+64*yend, myData+64*yend, 64)!=0) break; } + if (ystart==342) { + //No need for update + yend=342; + } else { + ystart=(ystart*32)/SCALE_FACT-1; + yend=(yend*32)/SCALE_FACT+1; + if (ystart<0) ystart=0; + printf("Changed %d to %d\n", ystart, yend); + } + } else { + xstart=0; xend=320; + ystart=0; yend=320; + } + memcpy(oldImg, myData, 512*342/8); + + if (ystart!=yend) { + setRowRange(ystart, 319); + img[0]=0x2c; + uint8_t *p=&img[1]; + for (int j=ystart; j>8); + } + l++; + if (l>=LINESPERBUF || j==yend-1) { + mipiDsiSendLong(0x39, img, (l*320*2)+1); + img[0]=0x3c; + l=0; + p=&img[1]; + if (!firstrun && j>=200) break; //no need to render black bar in subsequent times + } + } + firstrun=0; } } } diff --git a/components/tme-esp32/snd.c b/components/tme-esp32/snd.c index a214909..2ba2a60 100644 --- a/components/tme-esp32/snd.c +++ b/components/tme-esp32/snd.c @@ -9,28 +9,50 @@ static QueueHandle_t soundQueue; -int sndDone() { - return uxQueueSpacesAvailable(soundQueue)<2; +//powers of 2 plzthx +#define BUFLEN 2048 + +static uint8_t buf[BUFLEN]; +static volatile int wp=256, rp=0; + +static int bufLen() { + return (wp-rp)&(BUFLEN-1); } +int sndDone() { //1 when stuff can be written to buffer +// printf("sndpoll %d\n", bufLen()); + return bufLen()<(BUFLEN-400); +} -#define SND_CHUNKSZ 32 -int sndPush(uint8_t *data, int volume) { - uint32_t tmpb[SND_CHUNKSZ]; - int i=0; - int len=370; - while (iSND_CHUNKSZ) plen=SND_CHUNKSZ; - for (int j=0; j>(7-volume)); -// s=s/16; + s=s/16; tmpb[j]=((s+128)<<8)+((s+128)<<24); - data+=2; + rp++; + if (rp>=BUFLEN) rp=0; } - i2s_write_bytes(0, (char*)tmpb, plen*4, portMAX_DELAY); - i+=plen; + i2s_write_bytes(0, (char*)tmpb, sizeof(tmpb), portMAX_DELAY); +// printf("snd %d\n", rp); + } +} + +int sndPush(uint8_t *data, int volume) { + while (!sndDone()) usleep(1000); + myVolume=volume; + for (int i=0; i<370; i++) { + buf[wp]=*data; + data+=2; + wp++; + if (wp>=BUFLEN) wp=0; } return 1; } @@ -38,13 +60,13 @@ int sndPush(uint8_t *data, int volume) { void sndInit() { i2s_config_t cfg={ .mode=I2S_MODE_DAC_BUILT_IN|I2S_MODE_TX|I2S_MODE_MASTER, - .sample_rate=22000, + .sample_rate=22200, .bits_per_sample=16, .channel_format=I2S_CHANNEL_FMT_RIGHT_LEFT, .communication_format=I2S_COMM_FORMAT_I2S_MSB, .intr_alloc_flags=0, - .dma_buf_count=4, - .dma_buf_len=1024/4 + .dma_buf_count=8, + .dma_buf_len=1024/8 }; i2s_driver_install(0, &cfg, 4, &soundQueue); i2s_set_pin(0, NULL); @@ -63,6 +85,7 @@ void sndInit() { }; gpio_config(&io_conf); #endif + xTaskCreatePinnedToCore(&sndTask, "snd", 3*1024, NULL, 6, NULL, 1); } diff --git a/components/tme/emu.c b/components/tme/emu.c index 817a828..296d026 100644 --- a/components/tme/emu.c +++ b/components/tme/emu.c @@ -459,6 +459,7 @@ void printFps() { void tmeStartEmu(void *rom) { int ca1=0, ca2=0; int x, m=0, frame=0; + int cyclesPerSec=0; macRom=rom; ramInit(); rom_remap=1; @@ -482,23 +483,23 @@ void tmeStartEmu(void *rom) { localtalkInit(); printf("Done! Running.\n"); while(1) { - for (x=0; x<8000000/60; x+=10) { - m68k_execute(10); - viaStep(1); //should run at 783.36KHz - sccTick(); - m++; - if (m>=1000) { - int r=mouseTick(); - if (r&MOUSE_BTN) viaClear(VIA_PORTB, (1<<3)); else viaSet(VIA_PORTB, (1<<3)); - if (r&MOUSE_QXB) viaClear(VIA_PORTB, (1<<4)); else viaSet(VIA_PORTB, (1<<4)); - if (r&MOUSE_QYB) viaClear(VIA_PORTB, (1<<5)); else viaSet(VIA_PORTB, (1<<5)); - sccSetDcd(SCC_CHANA, r&MOUSE_QXA); - sccSetDcd(SCC_CHANB, r&MOUSE_QYA); - m=0; + for (x=0; x<8000000/60; x+=1000) { + for (int i=0; i<100; i++) { + m68k_execute(10); + viaStep(1); //should run at 783.36KHz + sccTick(); } + int r=mouseTick(); + if (r&MOUSE_BTN) viaClear(VIA_PORTB, (1<<3)); else viaSet(VIA_PORTB, (1<<3)); + if (r&MOUSE_QXB) viaClear(VIA_PORTB, (1<<4)); else viaSet(VIA_PORTB, (1<<4)); + if (r&MOUSE_QYB) viaClear(VIA_PORTB, (1<<5)); else viaSet(VIA_PORTB, (1<<5)); + sccSetDcd(SCC_CHANA, r&MOUSE_QXA); + sccSetDcd(SCC_CHANB, r&MOUSE_QYA); + m=0; //Sound handler keeps track of real time, if its buffer is empty we should be done with the video frame. - //if (sndDone()) break; + if (sndDone()) break; } + cyclesPerSec+=x; dispDraw(macFb[video_remap?1:0]); sndPush(macSnd[audio_remap?1:0], audio_en?audio_volume:0); localtalkTick(); @@ -511,6 +512,8 @@ void tmeStartEmu(void *rom) { rtcTick(); frame=0; printFps(); + printf("%d Hz\n", cyclesPerSec); + cyclesPerSec=0; } } }