Offline
Michigan

heh.

Last edited by Jazzmarazz (May 19, 2014 1:22 am)

Offline
Melbourne, Australia
rvan wrote:

Reading the Freescale Reference Manual, it turns out that the Teensy's chip does have two SPI ports.  We may yet be in luck...

...are those pins available on the board though? and is there software library support for two SPI ports?

Another option which does have support for two SPI ports is the good old Maple Mini, and it looks like they can be found pretty cheaply on eBay...

Offline
Michigan
uXe wrote:
rvan wrote:

Reading the Freescale Reference Manual, it turns out that the Teensy's chip does have two SPI ports.  We may yet be in luck...

...are those pins available on the board though? and is there software library support for two SPI ports?

Another option which does have support for two SPI ports is the good old Maple Mini, and it looks like they can be found pretty cheaply on eBay...

Thats pretty neat, but you utilize port manipulation?

Offline
Michigan

Well, I was in the process of moving when this thread started and then I got a new job ... and more than a month later, I have my home office mostly set up. I can finally dedicate some time and effort into this project.

Now, what I am doing is going back to the basics. For the time being I am ignoring Hsync and Vsync and just focusing on clock and data. That means if I get a picture, it will be skewed, but at this point, all I care about is a picture! Any picture! Also worth mentioning, I am working with a 16MHz arduino pro mini so I have to focus on sketch streamlining. The reason I set aside my Teensy is because they are expensive and anyone wanting to build this into a GB will be put off by the Teensy's price and size. I also think that the CPP to machine code conversion for the Teensy's CPU is worse than that of the atmega168.

I have to go grocery shopping before I can sit down and modify friendofmegaman's PC-side code but I have a simple fast program for the arduino:
1. wait for clock interrupt
2. Serial.print(PORTB)
3. repeat

PORTB is just a byte with data0 and data1 at the farthest right bits. The PC is going to do the horizontal counting for me, at least until I get a legit picture. Once I get that picture, I will implement Vsync. Hsync may remain as a simple counter on the PC-side.

Future goal: implement composite video output without the help of a PC.

brb

Offline
CA
Jazzmarazz wrote:

Well, I was in the process of moving when this thread started and then I got a new job ... and more than a month later, I have my home office mostly set up. I can finally dedicate some time and effort into this project.

Now, what I am doing is going back to the basics. For the time being I am ignoring Hsync and Vsync and just focusing on clock and data. That means if I get a picture, it will be skewed, but at this point, all I care about is a picture! Any picture! Also worth mentioning, I am working with a 16MHz arduino pro mini so I have to focus on sketch streamlining. The reason I set aside my Teensy is because they are expensive and anyone wanting to build this into a GB will be put off by the Teensy's price and size. I also think that the CPP to machine code conversion for the Teensy's CPU is worse than that of the atmega168.

I have to go grocery shopping before I can sit down and modify friendofmegaman's PC-side code but I have a simple fast program for the arduino:
1. wait for clock interrupt
2. Serial.print(PORTB)
3. repeat

PORTB is just a byte with data0 and data1 at the farthest right bits. The PC is going to do the horizontal counting for me, at least until I get a legit picture. Once I get that picture, I will implement Vsync. Hsync may remain as a simple counter on the PC-side.

Future goal: implement composite video output without the help of a PC.

brb


Nice, but how does it address the fact that clock (and therefore data) comes in as fast as 4Mbs and therefore you only have 16/4 = 4 cycles to do anything with it?

Offline
Michigan

Because it's written to be so simple, that its stupid. Basically it does nothing but forward the data pins out the serial port. I'll detail my results once I get home and test it out.

Offline
Michigan

Speaking of which, it mag be economical to test a serially clocked parallel-in, serial-out shift register and process all five pins on the PC. I think I have one such IC on hand .... But still grocery shopping. tongue

Offline
Melbourne, Australia
Jazzmarazz wrote:
uXe wrote:

...are those pins available on the board though? and is there software library support for two SPI ports?

Another option which does have support for two SPI ports is the good old Maple Mini, and it looks like they can be found pretty cheaply on eBay...

Thats pretty neat, but you utilize port manipulation?

Of course - jump to Chapter 9 on GPIOs:

http://www.st.com/st-web-ui/static/acti … 171190.pdf

or even program in assembly if you like:

http://www.st.com/st-web-ui/static/acti … 228163.pdf

Offline
Michigan

Finally back from the damn store. (I hate shopping)
Soldered in some new wires to an old project:



NOW ... I cannot find a female parallel plug. lol ... I'll breadboard this out as soon as I find a plug ... I have so many boxes of junk around here ... sad

Offline
uXe wrote:

...are those pins available on the board though? and is there software library support for two SPI ports?

Right now I can't locate SPI1_SCK on the Pin Assignment table, but the other pins are broken out.  I haven't had any luck with software yet.  I tried btmcmahan's library in slave mode using the example code, but nothing happens (I was using an Arduino as the master).

uXe wrote:

Another option which does have support for two SPI ports is the good old Maple Mini, and it looks like they can be found pretty cheaply on eBay...

Thanks, I may look into this some time.

Jazzmarazz wrote:

Well, I was in the process of moving when this thread started and then I got a new job ... and more than a month later, I have my home office mostly set up. I can finally dedicate some time and effort into this project.

Great to hear you're set up in your new place and on board for the project.

Jazzmarazz wrote:

Also worth mentioning, I am working with a 16MHz arduino pro mini so I have to focus on sketch streamlining. The reason I set aside my Teensy is because they are expensive and anyone wanting to build this into a GB will be put off by the Teensy's price and size. I also think that the CPP to machine code conversion for the Teensy's CPU is worse than that of the atmega168.

I suspect you're right that Arduino code will be more efficient that Teensyduino code, but I have to agree with friendofmegaman that you're going to be very pushed for cycles, especially using an interrupt and doing a serial write straight away.

Jazzmarazz wrote:

Speaking of which, it mag be economical to test a serially clocked parallel-in, serial-out shift register and process all five pins on the PC.

Do you mean converting CLK, D0, D1, HS, and VS to serial data?  Do you plan to send this data to a microcontroller, or are you connecting the DMG to the PC through something else?

Jazzmarazz wrote:

I have to go grocery shopping before I can sit down and modify friendofmegaman's PC-side code...

You might want to use this version of the display code which I've modified to use Pygame instead of Pylab.  Pylab was extremely slow here...

#!/usr/bin/python
#author: friendofmegaman, rvan
#Display captured frame data on the PC.  Expects a 0x1E00 header and four
#pixels per byte.  Uses pygame, which is faster than pylab's scatter.

import pygame
from pygame.locals import *

upscale = 2

width = 160
height = 144

grey = []
grey.append((224,248,208))
grey.append((136,192,112))
grey.append((52, 104, 86))
grey.append((8, 24, 32))

fd = open('/path/to/screen.bin', 'rb')
data = fd.read()
fd.close()

frames = data.split('\x1E\x00')
print len(frames), 'frames'

class Pixel:
    x = 0;
    y = 0;
    def __call__(self, col):
        for upy in range(upscale):
            for upx in range(upscale):
                window.set_at(((self.x)*upscale+upx,
                               (self.y)*upscale+upy), grey[col])
    
        self.x +=1
        if self.x==160:
            self.x = 0
            self.y +=1

pixel = Pixel()
window = pygame.display.set_mode((width*upscale, height*upscale))

for frame in frames:
    # First and last frames can be smaller than that (because there's small
    # chance we start capture right at the beginning of the frame)
    if len(frame)!=5760:
        continue

    for y in range(144):
        for x in range(160):
            bit_offset = y*320+x*2
            array_offset = bit_offset/8
            byte_offset = bit_offset%8

            byte = ord(frame[array_offset])
            px = (byte>>byte_offset)&0b11
            pixel(px)

pygame.display.update()

quit = False
while not quit:
    event = pygame.event.wait()
    if event.type == pygame.QUIT or event.type == KEYDOWN and \
    event.key == K_ESCAPE:
        quit = True
Offline
Michigan
uXe wrote:
Jazzmarazz wrote:

Thats pretty neat, but you utilize port manipulation?

Of course - jump to Chapter 9 on GPIOs:

http://www.st.com/st-web-ui/static/acti … 171190.pdf

or even program in assembly if you like:

http://www.st.com/st-web-ui/static/acti … 228163.pdf

Excellent and I love assembly, but until I exhaust the option on-hand, I will set aside the maple mini for now.

rvan wrote:
Jazzmarazz wrote:

Also worth mentioning, I am working with a 16MHz arduino pro mini so I have to focus on sketch streamlining. The reason I set aside my Teensy is because they are expensive and anyone wanting to build this into a GB will be put off by the Teensy's price and size. I also think that the CPP to machine code conversion for the Teensy's CPU is worse than that of the atmega168.

I suspect you're right that Arduino code will be more efficient that Teensyduino code, but I have to agree with friendofmegaman that you're going to be very pushed for cycles, especially using an interrupt and doing a serial write straight away.

Yeah, it will be a challenge but I must try. Worse case scenario, I can try something like:

loop() 
{
Serial.print(PORTB); // where port B = 0, 0, 0, CLK, H, V, D1, D0
}

And then edit the PC-side program to process clock changes, Hsync and Vsync. Actually, its not a bad idea to be honest...

rvan wrote:
Jazzmarazz wrote:

Speaking of which, it mag be economical to test a serially clocked parallel-in, serial-out shift register and process all five pins on the PC.

Do you mean converting CLK, D0, D1, HS, and VS to serial data?  Do you plan to send this data to a microcontroller, or are you connecting the DMG to the PC through something else?

The 74HC165 is a Parallel-In, Serial-Out shift register... however I think that it may not be connected directly to a USB cable. lol
Maybe an RS232 cable, but not directly USB... it was a wild idea any way. The thought was to have no microcontroller to reduce size and cost.

rvan wrote:
Jazzmarazz wrote:

I have to go grocery shopping before I can sit down and modify friendofmegaman's PC-side code...

You might want to use this version of the display code which I've modified to use Pygame instead of Pylab.  Pylab was extremely slow here...

#!/usr/bin/python
#author: friendofmegaman, rvan
#Display captured frame data on the PC.  Expects a 0x1E00 header and four
#pixels per byte.  Uses pygame, which is faster than pylab's scatter.

import pygame
from pygame.locals import *

upscale = 2

width = 160
height = 144

grey = []
grey.append((224,248,208))
grey.append((136,192,112))
grey.append((52, 104, 86))
grey.append((8, 24, 32))

fd = open('/path/to/screen.bin', 'rb')
data = fd.read()
fd.close()

frames = data.split('\x1E\x00')
print len(frames), 'frames'

class Pixel:
    x = 0;
    y = 0;
    def __call__(self, col):
        for upy in range(upscale):
            for upx in range(upscale):
                window.set_at(((self.x)*upscale+upx,
                               (self.y)*upscale+upy), grey[col])
    
        self.x +=1
        if self.x==160:
            self.x = 0
            self.y +=1

pixel = Pixel()
window = pygame.display.set_mode((width*upscale, height*upscale))

for frame in frames:
    # First and last frames can be smaller than that (because there's small
    # chance we start capture right at the beginning of the frame)
    if len(frame)!=5760:
        continue

    for y in range(144):
        for x in range(160):
            bit_offset = y*320+x*2
            array_offset = bit_offset/8
            byte_offset = bit_offset%8

            byte = ord(frame[array_offset])
            px = (byte>>byte_offset)&0b11
            pixel(px)

pygame.display.update()

quit = False
while not quit:
    event = pygame.event.wait()
    if event.type == pygame.QUIT or event.type == KEYDOWN and \
    event.key == K_ESCAPE:
        quit = True

I will have a look! I may need to modify it to accommodate my arduino code, but we'll see when I get to that point.
Cheers

Offline
Jazzmarazz wrote:
loop() 
{
Serial.print(PORTB); // where port B = 0, 0, 0, CLK, H, V, D1, D0
}

Don't you want PINB here?  And probably Serial.write() if you want raw data.

Offline
Michigan

Yes, you are right. PINx is for reading only and PORTx is commonly used for writing values to your port.
Also, Serial.print prints an ASCII character by default, so I would either have to use:

Serial.print(PINB, BYTE);
or
Serial.write(PINB);

Good catch pal.

Offline
Michigan
uXe wrote:

Edit: unless the VRAM is built into the CPU? hmm

Haha, thanks for sharing. wink
Even though the VRAM may be internal, the pins are still available on the outer edge of the CPU. Now in both cases, you would have to add one of those dual port RAM ICs, so while using a pocket CPU, the contents would be mirrored to the dual port RAM. In both cases, the contents would still be fully accessible, granted they end up as being of any use to us. I think we dropped that idea by now though.

Offline
CA
jazzmarazz wrote:

The 74HC165 is a Parallel-In, Serial-Out shift register... however I think that it may not be connected directly to a USB cable. lol
Maybe an RS232 cable, but not directly USB... it was a wild idea any way. The thought was to have no microcontroller to reduce size and cost.

Theoretically... could we leverage some parallel interface for that? It should be feasible to clock it from GB clock and get all the data as needed. In fact we only need VSYNC, CLOCK, DATA0, DATA1... some 4 pin parallel interface anyone?

UPDATE
Ok, quick check tells me that there's DB25 printer port which is absent in pretty much all of the modern machines, but I'm sure we could emulate via USB.

Another thing is could we somehow leverage TCP/IP stack to handle large volumes of information? Does anybody know how Ethernet shiled works for instance. If packing data into TCP/IP frame is completely handled by the shield and is fast enough then we could think of feeding it parallel data somehow...

It was just random brainstorming...

Last edited by friendofmegaman (Jun 2, 2014 9:50 pm)

Offline
Michigan
friendofmegaman wrote:
jazzmarazz wrote:

The 74HC165 is a Parallel-In, Serial-Out shift register... however I think that it may not be connected directly to a USB cable. lol
Maybe an RS232 cable, but not directly USB... it was a wild idea any way. The thought was to have no microcontroller to reduce size and cost.

Theoretically... could we leverage some parallel interface for that? It should be feasible to clock it from GB clock and get all the data as needed. In fact we only need VSYNC, CLOCK, DATA0, DATA1... some 4 pin parallel interface anyone?

Yeah, possibly. The only problem I see is that very few people are going to have access to a parallel interface at home, let alone "on the road."