rossumur / esp_8_bit

Atari 8 bit computers, NES and SMS game consoles on your TV with nothing more than a ESP32 and a sense of nostalgia
1.04k stars 148 forks source link

No video #27

Open migreg opened 3 years ago

migreg commented 3 years ago

Hi,

I need some help.

I don't get video with the sketch. In the console I see a correct boot, Wiimote pairing and .nes load from SPIFFS, but no video

Board: DOIT ESP32 DEVKIT V1 Tried both pins 26 and 25, PAL and NTSC and ATARI and NES setups Bitlunis CompositeVideoSimple sketch works fine with same setup (ESP32 board, pin 25 and same TV) In the Oscilloscope I see video output with Bitlunis sketch but not with esp_8_bit nor espflix

Thanks in advance!

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) ets Jun 8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0018,len:4 load:0x3fff001c,len:1044 load:0x40078000,len:8896 load:0x40080400,len:5816 entry 0x400806ac

esp_8_bit

mounting spiffs (will take ~15 seconds if formatting for the first time).... ... mounted in 99 ms frame_time:0 drawn:1 displayed:0 blit_ticks:0->0, isr time:0.00% emu_task nofrendo running on core 0 at 240000000mhz nofrendo inserting /nofrendo/mario.nes nofrendo /nofrendo/mario.nes is 40976 bytes main: partition type = 0. main: partition subtype = 17. main: partition starting address = 150000. main: partition size = 140000. main: partition label = app1. main: partition encrypted = 0.

00010000 00006010 /nofrendo/chase.nes 00020000 0000A010 /nofrendo/mario.nes CrapFS::mmap mapping /nofrendo/mario.nes offset:00020000 len:40976 CrapFS::mmap mapped to 3F430000 Head: 0x3f430000 (4e 45 53 1a) video_init frame_time:11815 drawn:121 displayed:0 blit_ticks:-1->0, isr time:0.00% frame_time:11142 drawn:241 displayed:0 blit_ticks:-1->0, isr time:0.00%

bootrino commented 3 years ago

I also was not able to get this project working with either NTSC or PAL for some reason.

This fork seems to work though: https://github.com/CornN64/esp_8_bit

No idea what is different about the cornn64 fork that makes it work.

Even using the CornN64 fork, one of my esp32's works, another one does not. Both work with the bitluni Composite code but that its only black and white.

Check the partition and also the board type, this is what worked for me in the end:

Screen Shot 2020-08-25 at 4 58 51 pm

Screen Shot 2020-08-25 at 4 34 46 pm

Also try erasing your flash first with this sketch:

include "FS.h"

include "SPIFFS.h"

include "esp_partition.h"

/ You only need to format SPIFFS the first time you run a test or else use the SPIFFS plugin to create a partition https://github.com/me-no-dev/arduino-esp32fs-plugin /

define FORMAT_SPIFFS_IF_FAILED true

void listPartitions(void) { size_t ul; esp_partition_iterator_t _mypartiterator; const esp_partition_t *_mypart; ul = spi_flash_get_chip_size(); Serial.print("Flash chip size: "); Serial.println(ul); Serial.println("Partiton table:"); _mypartiterator = esp_partition_find(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL); if (_mypartiterator) { do { _mypart = esp_partition_get(_mypartiterator); printf("%x - %x - %x - %x - %s - %i\r\n", _mypart->type, _mypart->subtype, _mypart->address, _mypart->size, _mypart->label, _mypart->encrypted); } while ((_mypartiterator = esp_partition_next(_mypartiterator))); }

esp_partition_iterator_release(_mypartiterator); _mypartiterator = esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, NULL); if (_mypartiterator) { do { _mypart = esp_partition_get(_mypartiterator); printf("%x - %x - %x - %x - %s - %i\r\n", _mypart->type, _mypart->subtype, _mypart->address, _mypart->size, _mypart->label, _mypart->encrypted); } while ((_mypartiterator = esp_partition_next(_mypartiterator))); }

esp_partition_iterator_release(_mypartiterator); }

void setup() { Serial.begin(115200); if (!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)) { Serial.println("SPIFFS Mount Failed"); return; }

listPartitions(); Serial.println("Test complete"); }

void loop() {

})

Here is the esp32 that I used: IMG_0842

And it working on two different TVs:

IMG_8327

IMG_7014

migreg commented 3 years ago

Thanks for your reply.

I've tried many things, erasing the flash at Macos with % esptool.py --chip esp32 --port /dev/cu.SLAB_USBtoUART erase_flash

and flashing with your suggested parameters.

I've only succeeded with CornN64 fork and NTSC and SMS emulator combination

No success with PAL nor other emulators.

If I comment the Bluetooth init code at setup and hid updates inside the main loop then the video works with for example NES and NTSC, both with the Rossumur and CornN64 sketches, so it has something to do with the Bluetooth code. I don't know about DAC, but I've read that ADC2 is not usable while using WIFI/BLE

bootrino commented 3 years ago

Interesting - both PAL and NTSC work for me.

Which model of esp32 are you using? Can you post a close up image?

Also what model of TV are you using? Can you post an image and model number?

I'd suggest buying a couple of different models of esp32 - one of them may work - there seems to be differences in the esp32 models that prevent some of them working.

I've had a look at the code in cornn64 and I could not find what it was that made it work whereas this project doesn't - but that's no surprise because there's lots in there to understand.

migreg commented 3 years ago

Hi,

I'm using a Doit esp32 devkit v1 board:

IMG_8823 IMG_8824

These two console output logs are from a CornN64 fork sketch with BLE commented, configured for NES, Dual cores, Video on pin 25 and audio on pin 18 and perf enabled.

The first one is NTSC and the second one is PAL In the first one you can see displayed !=0 and the video works. In the PAL one displayed frames=0 and video doesn't work so it's not a TV related issue, as I can tell whether it works or not even before connecting it to the TV

ets Jun 8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) ets Jun 8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0018,len:4 load:0x3fff001c,len:1216 ho 0 tail 12 room 4 load:0x40078000,len:9720 ho 0 tail 12 room 4 load:0x40080400,len:6352 entry 0x400806b8

esp_8_bit

mounting spiffs (will take ~15 seconds if formatting for the first time).... ... mounted in 98 ms emu_task nofrendo running on core 0 at 240000000Hz frame_time:0 drawn:1 displayed:0 blit_ticks:0->0, isr time:0.00% nofrendo inserting /nofrendo/mario.nes nofrendo /nofrendo/mario.nes is 40976 bytes main: partition type = 0. main: partition subtype = 17. main: partition starting address = 150000. main: partition size = 140000. main: partition label = app1. main: partition encrypted = 0.

00010000 00020000 /smsplus/baraburuu.sms 00030000 00006010 /nofrendo/chase.nes 00040000 0000A010 /nofrendo/mario.nes CrapFS::mmap mapping /nofrendo/mario.nes offset:00040000 len:40976 CrapFS::mmap mapped to 3F430000 Head: 0x3f430000 (4e 45 53 1a) video_init frame_time:8870 drawn:121 displayed:115 blit_ticks:3229->4406, isr time:25.06% frame_time:8862 drawn:241 displayed:235 blit_ticks:3229->4402, isr time:26.06% frame_time:8858 drawn:361 displayed:355 blit_ticks:3229->4405, isr time:26.06% B⸮I]A⸮0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0018,len:4 load:0x3fff001c,len:1216 ho 0 tail 12 room 4 load:0x40078000,len:9720 ho 0 tail 12 room 4 load:0x40080400,len:6352 entry 0x400806b8

esp_8_bit

mounting spiffs (will take ~15 seconds if formatting for the first time).... ... mounted in 97 ms emu_task nofrendo running on core 0 at 240000000Hz frame_time:0 drawn:1 displayed:0 blit_ticks:0->0, isr time:0.00% nofrendo inserting /nofrendo/mario.nes nofrendo /nofrendo/mario.nes is 40976 bytes main: partition type = 0. main: partition subtype = 17. main: partition starting address = 150000. main: partition size = 140000. main: partition label = app1. main: partition encrypted = 0.

00010000 00020000 /smsplus/baraburuu.sms 00030000 00006010 /nofrendo/chase.nes 00040000 0000A010 /nofrendo/mario.nes CrapFS::mmap mapping /nofrendo/mario.nes offset:00040000 len:40976 CrapFS::mmap mapped to 3F430000 Head: 0x3f430000 (4e 45 53 1a) video_init frame_time:8666 drawn:121 displayed:0 blit_ticks:-1->0, isr time:0.00% frame_time:8671 drawn:241 displayed:0 blit_ticks:-1->0, isr time:0.00% frame_time:8665 drawn:361 displayed:0 blit_ticks:-1->0, isr time:0.00%

bootrino commented 3 years ago

My primary suggestion would be to buy several other varieties of esp32 assuming the $10 per unit isn't going to be a problem to you.

There's some other video generation things you can try for further research:

A hacked down version of esp_8_bit: https://github.com/erenard/obd-esp-dashboard

bitluni CompositeVideoSimple (I think maybe you've tried this)? https://github.com/bitluni/ESP32CompositeVideo

Also this pattern generator which I think is also bitluni based: https://github.com/erenard/esp32-i2s-composite

CornN64 commented 3 years ago

there seems to be a bug in the audio PLL on older silicon (older than yr2017 or so) https://www.esp32.com/viewtopic.php?t=1363 (see section 3.7 in errata) Maybe this is causing the the problems you are seeing. As for my changes in my fork I checked that timing for NTSC is closer to spec. and recalculated colors for both PAL and NTSC for NES (among many other things).

here is a sketch that will give you the version number and it need to be "1" and not "0" more details here https://www.instructables.com/id/How-to-Check-the-Revision-Level-of-Your-ESP32/

/* This sketch reads the version number of hte ESP32 chip

2017-07-17 Andreas Spiess

*/

include "soc/efuse_reg.h"

int getChipRevision() { return (REG_READ(EFUSE_BLK0_RDATA3_REG) >> (EFUSE_RD_CHIP_VER_RESERVE_S)&&EFUSE_RD_CHIP_VER_RESERVE_V) ; }

void setup() { Serial.begin(115200); delay(200); Serial.print("REG_READ(EFUSE_BLK0_RDATA3_REG) "); Serial.println(REG_READ(EFUSE_BLK0_RDATA3_REG), BIN);

Serial.print("EFUSE_RD_CHIP_VER_RESERVE_S "); Serial.println(EFUSE_RD_CHIP_VER_RESERVE_S, BIN);

Serial.print("EFUSE_RD_CHIP_VER_RESERVE_V "); Serial.println(EFUSE_RD_CHIP_VER_RESERVE_V, BIN);

Serial.println();

Serial.print("Chip Revision (official version): "); Serial.println(getChipRevision());

Serial.print("Chip Revision from shift Opration "); Serial.println(REG_READ(EFUSE_BLK0_RDATA3_REG) >> 15, BIN); }

// the loop function runs over and over again forever void loop() { }

migreg commented 3 years ago

Thanks. Yes mine is old. I’ve ordered newer ones. Let’s see

Thanks

El El mié, 2 sept 2020 a las 15:04, CornN64 notifications@github.com escribió:

there seems to be a bug in the audio PLL on older silicon (older than yr2017 or so)

https://www.esp32.com/viewtopic.php?t=1363 (see section 3.7 in errata)

Maybe this is causing the the problems you are seeing.

As for my changes in my fork I checked that timing for NTSC is closer to spec. and recalculated colors for both PAL and NTSC for NES (among many other things).

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/rossumur/esp_8_bit/issues/27#issuecomment-685721839, or unsubscribe https://github.com/notifications/unsubscribe-auth/AQTICDVVBKB2YAMUTGF7IW3SDY7GXANCNFSM4P6J3UOA .

bootrino commented 3 years ago

@CornN64 it might be useful for to detect old versions of the esp32 and warn the user. Just a thought.

bootrino commented 3 years ago

@CornN64 there's a function in the source code test_wave but I can't see what it does or any way to execute it. Do you know what it is?

CornN64 commented 3 years ago

It was left there to test DDS (in case some one wants to make a fancy signal generator) but it has no purpose otherwise... As far as I can tell on the photo you made of your ESP32 it is also from the old silicon eg. pre 2017 so try to get a newer part and things should work fine. The old silicon has a bug that makes it impossible to set a generic sample freq. accurately which is a must to get it to work with the color carriers.

migreg commented 3 years ago

Hi,

I've just received two new modules and I can confirm that both of them worked like a charm at the first attempt (PAL, NES emulator) with both Rossumur and CornN64 sketches

I bought them (Sept 2020) via Banggood: "ESP32 Development Board WiFi+bluetooth Ultra Low Power Consumption Dual Cores ESP-32 ESP-32S Board. Brand: Geekcreit", and they are also labeled "DOIT ESP32 DEVKIT V1" as the other older one that I had, purchased years ago, that didn't worked.

This is the photograph of the new ones:

IMG_8870

Thanks!

romeurolo commented 3 years ago

I have troubles in the video, no output, the problem is some lines in the video_out.h and now is working.

when you define VIDEO_PIN 25 the dac_output_enable() must be DAC_CHANNEL_1 and when VIDEO_PIN 26 dac_output_enable() is DAC_CHANNEL_2.

I found the solution in a post from another issue in this project. https://github.com/rossumur/esp_8_bit/issues/4#issuecomment-812904408

I hope this solves the video out problem for everyone.

JimDrewGH commented 3 years ago

It should also be noted that the problem with no video with the original Rossumur version appeared (for me) when switching from core v1.0.5 to v1.0.6. The video hangs in the PLL initialization. If I go back and forth between v1.0.5 and v1.0.6 it either works or it doesn't work, with the later occurring with the v1.0.6 core.

I will try the CornN64 version to see if there changes there that make a difference with the new core.

CornN64 commented 3 years ago

The main additions/changes I made are: Possibility to use SD card as storage for ROMs (still needs to write selected ROM to internal memory mapped flash) Added option to use single or dual original NES or SNES hard wired controller for two player action and lowest possible latency. Tweaked the color space (for NES) and video signal generation to better follow the NTSC specs.

The old ESP32 silicon prior to 2017 had a bug that makes it impossible to run the APLL properly (and can be seen with a warning in the debug output in my version if detected)

JimDrewGH commented 3 years ago

The sketch above to determine the revision of the ESP32 chip does not compile under Arduino IDE v1.8.13 using any version of the ESP32 core. I tried v1.0.1 through v1.0.6. Maybe this compiles under Platform I/O? The error I see is:

'EFUSE_RD_CHIP_VER_RESERVE_S' was not declared in this scope

CornN64 commented 3 years ago

Not sure whats up since I also use 1.8.13...

you can try this simpler version that I also have in my sketch

` int silicon_version = (REG_READ(EFUSE_BLK0_RDATA3_REG) >> 15) & 1;

if (silicon_version == 0) printf("Warning this revision of the chip has an issue with the APLL and will not work properly!\n"); `

JimDrewGH commented 3 years ago

Yeah, your code compiles just fine and I don't get the warning. I will remove and re-install 1.8.13 as that is the only thing I have not tried.

I did notice something rather interesting this evening. After installing ESPFlix I was no longer able to actually run either the original or your version of esp_8_bit. The compilation goes fine, after its done the serial monitor showed that the init couldn't allocate the last block of memory (out of memory error). This is a never-ending loop. I tried several ESP23 modules, all with the same result. On a whim I used ESPTOOL to "erase_flash" the entire flash memory. After doing this both the original and your version now works fine, even with core v1.0.6. So, I am guessing that something in ESPflix must be somehow corrupting the flash.

I am interested in making a couple of emulators. using the color composite output. Is there any info on how to set this up as a simple frame buffer, where one core handles the video/audio, leaving the other core free to draw into that buffer? I see reference to a simulator, but I am not sure what that does. Thanks!

CornN64 commented 3 years ago

Yes the memory mapped ROM files are not double checked (so that they are not corrupted) before trying to boot them which leads to everything hanging and the only way out is to use the ESPTOOL to wipe everything.

Ideally some check should be added before booting the ROM but as it is now the emulator counts on being able to boot the last loaded ROM or die trying. Would be nice to get that sorted at some point...

As for the frame buffer... NES at least uses it own frame buffer (and I think this would be the same for the other two emulators) for rendering the emulated frame. Then the DMA takes one line at the time and renders the composite signal and send it off to the DAC. The DMA only buffer one line while sending the other line.

JimDrewGH commented 3 years ago

Well, I take that back... just going from core 1.0.5 to 1.0.6 and recompiling the exact same code causes the same error. I had to erase the flash again, and once I did it worked fine and subsequent re-compiles using the same core (even changing between emulator types) works fine. What is interesting is that I can go from 1.0.6 to 1.0.5 without having to erase the flash, but when going back to 1.0.6 it wouldn't work and required the flash to be erased again. I guess rule of thumb (with this) is to erase the flash after updating the core version.

What I am trying to do is have an 8 bit palette with a 320x200 or 320x240 display. I don't need double-buffering (probably). How many colors are you able to get with this setup? I don't know a lot about color generation (other than colors are created by some phase offset in relation to the burst signal), but I have a lot of experience with monochrome composite output. If the video output is handled as a series of interrupts (state machine) with a flat memory model (frame buffer), then I should be able to just start that up, initialize the palette, and then poke into the frame buffer as needed.

CornN64 commented 3 years ago

Ok I see what you mean now, I am actually on 1.0.4 (assuming that by core you mean the board manager->esp32 configs) and have not tried the newer ones...

In essence it works like this: The emulator renders a full frame in memory which is kept as 8bit per pixel Since the console in question usually has a fixed number of colors like NES can only have 64 different colors they can be mapped in a translation table mapped to colors on the composite signal space where each entry in the table contains 4 sample bytes stored as a 32bit integer, The DMA accesses the rendered frame buffer line by line and translate each pixel in that line to its corresponding composite values. This means there is only on large buffer that holds the complete frame (which also saves precious memory)

Now here are a few tricks which complicate things when it comes to number of pixels that can be had. In order to get color it is easier to have something that is completely in synch with the color carrier in order to perfectly match up pixels with number of samples needed to translate them into composite. So the sample rate is set to exactly 4 times the color carrier about 14.318MHz. Since a composite line is about 64us long it means it can only fit 273 pixels or so but a line also need to contain the composite front porch, synch pulse the back porch with color carrier so only 186 actually visible pixels. In order to still get the 256 pixels needed for NES, each pixel only takes 3 samples from the table and then jumps to the pixel color (but still keeping the phase order of the sample, first pixel {p0,p1,p2} next pixel {p3,p0,p1} and so on) to reach 248 visible pixels which is good enough. I suppose that in theory this could be extended to map 2 pixels into 4 samples and that should give you 372 visible pixels.

As for the Y direction any number up to 240 lines should work fine...

It will require some digging in the code but all is in there to do what you want..

JimDrewGH commented 3 years ago

Yes, by core I mean the core selected by the board manager. Apparently the problem occurs just going from v1.0.5 to v1.0.6.

Why not use a higher multiplier than 4x the colorburst? The ESP32 should be able to handle much higher. With the PIC micros I use for monochrome composite generation, I am using 16x the colorburst frequency to get a high number of pixels (wide). There is 52.6us of time for the active (visible) video space (edge to edge). It seems that even using 8x the color burst should allow double the number of pixels without any issues. Of course you need the available RAM for the buffer (320x212, typical for a real NTSC display) is ~66.25KB. I know how the lines and interlacing work, so that should not be too much of a concern. The color depth and number of pixels wide is the real issue. Ideally, it would be nice to be able to double the memory usage and have 16 bit colors, even if you had to use YUV values directly without a palette.

The info on ESPFlix states that the resolution is 352x192, so I guess Rossumur is doubling the clock? The color space also appears to be higher using YUV 4:1:3 at the cost of a lot more memory.

The DAC only uses ~1.1v p-p out of the 3.3v, limiting the number of "shades" (luminosity). I think that this would be an easy way to increase the apparent number of colors by just doing a simple 1/3 resistor divider. Have you looked into that?

CornN64 commented 3 years ago

The DAC is already running out of spec and I am not sure it can handle much beyond 20Msps anyways The problem is that a complete color cycle with 8 samples you would still need to cut the cycle in half so there is nothing to gain from the 4 samples case and using 2 samples for each pixel value. You would end up with enough pixels anyway in doing so. Also keep in mind that composite has a bandwidth limitation of about 6-7MHz so you cant really get very high resolution on the old analog stuff (color already limits the resolution due to the color carrier) Also the number of colors are not only the number of DAC level amplitudes but also it relative phase so you get way more than 255 colors as it is.

I have not looked to much at the ESPFlix code to be able to say what he did there other than he reused much of the stuff from this code base.

You might get some small gain in quality by using more DAC levels but I dont think it will be a big difference from what you get with the current setup. I sort of tried doubling the signal level and adding a proper 75ohm resistance in series to proper terminate the video signal but I saw very little difference if any so I did not pursue this further.

JimDrewGH commented 3 years ago

Right, typically the number of phases is correlated to the color clock you are using. Each phase is a color and the luminosity gives you the shades of that color. This is what is done with a PIC32, getting 384 x 216 pixels in 256 colors using just some timers and no hardware DAC (and much slower single core CPU). Having 3 times the DAC resolution should offer a lot more overall colors.