Thursday, March 31, 2011

Seeking causes crash on AVR (bug in my code)

So yesterday when I started a game of Dragon's Lair, the AVR would crash. I wasn't sure what was causing it but today I simulated the same command sequence using the PC's parallel port (to eliminate the Dragon's Lair as being the problem) and it crashed again. Here's the log:


Starting Main Game Loop
Play
LDP : Received pause while disc was not playing, ignoring
listener: Controller is using our current settings (yay!)
listener: VLDP-HW: <- fd
listener: VLDP-HW: Play
listener: VLDP-HW: -> 64
listener: VLDP-HW: LDP Status: Spinning up
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> e4
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: <- 3f
listener: VLDP-HW: -> 64
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> e4
listener: VLDP-HW: <- f
listener: VLDP-HW: -> 64
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> e4
listener: VLDP-HW: <- 2f
listener: VLDP-HW: -> 64
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> e4
listener: VLDP-HW: <- 8f
listener: VLDP-HW: -> 64
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> e4
listener: VLDP-HW: <- 2f
listener: VLDP-HW: -> 64
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> e4
listener: VLDP-HW: AM HERE!
listener: VLDP-HW: Settings applied
listener: Controller said hello
listener: VLDP-HW: LDV1000 start
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> fc
listener: VLDP-HW: LDP Status: Stopped
listener: Controller is using our current settings (yay!)


Do you know what this means? It means that this.. DANG THING.. doesn't work at all!

Actually what it means is that I get to step through in the simulator and see why it's crashing. The "AM HERE!" string is the first thing the AVR sends when it boots. I've seen crashes caused by null pointer dereferencing so that is one possibility. I sure hope I can figure out a way to make the simulator run most of this code by itself because entering in the entire command sequence by hand in the debugger would take a long time.

Measured voltage levels on my dragon's lair

So Warren suggested that I measure the voltage levels on my Dragon's Lair hardware to troubleshoot my monitor's problems that were evident in the video from yesterday. I just did. It's a little hard to tell for sure, but I believe that there is some A/C interference going on. I measured the voltage between the power supply's metal piece and the monitor's metal frame which should be 0, and it definitely did not seem to be steady at 0. It seemed to be fluctuating a bit between 0 and 0.02V but since it shows an average I couldn't tell for sure. I did measure the voltage going to the NTSC decoder card and it is a solid 18.6V (supposed to be 16V). I don't know what to think about that.

Wednesday, March 30, 2011

Video now playing at full speed!

After getting the I/O between the AVR and the Dragon's Lair working properly yesterday, I turned my attention to getting video playing on the PC. I was seeing my CPU usage pegged at 100% and no video which was disconcerting since I knew this PC was fast enough to play the video while running real-time linux (which is slower than normal linux).

I found two things. The first one was that my code that automatically drops fields if the PC is behind was not working, so it was getting more and more behind. The other thing was that somehow I had switched to using the slowest type of JPEG IDCT algorithm. Once I switched it back to my hand-crafted SSE2 algorithm (which ended up not being much faster than the reference integer version unfortunately) things improved dramatically and the PC was then able to play video at full speed using about 75% CPU which is acceptable (considering it doesn't need the CPU for any other purpose).

So I made a video of the attract mode playing with the video being rendered on the VGA monitor. I did attempt to route through the arcade monitor on the Dragon's Lair but my usual electrical problems made this underwhelming. I've included it in the video anyway.

Sound isn't working but I haven't spent any time looking into why. It's probably something simple.

Tuesday, March 29, 2011

It works!!!

I finally have successfully worked out the problems with communicating with the Dragon's Lair hardware. It now seems to be working perfectly (phew!!).

I did two things:
1) the AVR datasheet has specific instructions on how to switch between input and output modes that I was not exactly following so I fixed that
2) I enabled the AVR's internal pull-up resistors when in input mode which meant when dragon's lair stayed in input mode during the command strobe, I would receive a FF command.

My log file for your curiosity/enjoyment:


listener: VLDP-HW: LDP Status: Stopped
listener: Controller is not using our current settings, so we are pushing down new ones.
listener: VLDP-HW: Settings applied
listener: Controller is using our current settings (yay!)
listener: VLDP-HW: LDP Status: Stopped
listener: VLDP-HW: LDP Status: Stopped
listener: VLDP-HW: LDP Status: Stopped
listener: VLDP-HW: LDP Status: Stopped
listener: VLDP-HW: <- cd
listener: VLDP-HW: -> 7c
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> fc
listener: VLDP-HW: <- 3f
listener: VLDP-HW: -> 7c
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> fc
listener: VLDP-HW: <- 3f
listener: VLDP-HW: -> 7c
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> fc
listener: VLDP-HW: <- f
listener: VLDP-HW: -> 7c
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> fc
listener: VLDP-HW: <- 5f
listener: VLDP-HW: -> 7c
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> fc
listener: VLDP-HW: <- 1f
listener: VLDP-HW: -> 7c
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> fc
listener: VLDP-HW: <- f7
listener: VLDP-HW: Search to frame 197
listener: VLDP-HW: -> 50
listener: VLDP-HW: <- ff
listener: VLDP-HW: LDP Status: Searching
listener: VLDP-HW: -> d0
listener: VLDP-HW: LDP Status: Paused
listener: VLDP-HW: LDP Status: Paused
listener: VLDP-HW: LDP Status: Paused
listener: VLDP-HW: <- cd
listener: VLDP-HW: -> 50
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> d0
listener: VLDP-HW: <- 3f
listener: VLDP-HW: -> 50
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> d0
listener: VLDP-HW: <- 3f
listener: VLDP-HW: -> 50
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> d0
listener: VLDP-HW: <- 4f
listener: VLDP-HW: -> 50
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> d0
listener: VLDP-HW: <- 3f
listener: VLDP-HW: -> 50
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> d0
listener: VLDP-HW: <- 6f
listener: VLDP-HW: -> 50
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> d0
listener: VLDP-HW: <- f7
listener: VLDP-HW: Search to frame 306
listener: VLDP-HW: -> 50
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> d0
listener: VLDP-HW: LDP Status: Paused
listener: VLDP-HW: LDP Status: Paused
listener: VLDP-HW: LDP Status: Paused
listener: VLDP-HW: <- cd
listener: VLDP-HW: -> 50
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> d0
listener: VLDP-HW: <- 3f
listener: VLDP-HW: -> 50
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> d0
listener: VLDP-HW: <- 3f
listener: VLDP-HW: -> 50
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> d0
listener: VLDP-HW: <- 4f
listener: VLDP-HW: -> 50
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> d0
listener: VLDP-HW: <- 8f
listener: VLDP-HW: -> 50
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> d0
listener: VLDP-HW: <- 4f
listener: VLDP-HW: -> 50
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> d0
listener: VLDP-HW: <- f7
listener: VLDP-HW: Search to frame 323
listener: VLDP-HW: -> 50
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> d0
listener: VLDP-HW: <- fd
listener: VLDP-HW: Play
listener: VLDP-HW: -> 64
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> e4
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: LDP Status: Playing
listener: VLDP-HW: <- cd
listener: VLDP-HW: -> 64
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> e4
listener: VLDP-HW: <- 3f
listener: VLDP-HW: -> 64
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> e4
listener: VLDP-HW: <- 3f
listener: VLDP-HW: -> 64
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> e4
listener: VLDP-HW: <- f
listener: VLDP-HW: -> 64
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> e4
listener: VLDP-HW: <- 5f
listener: VLDP-HW: -> 64
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> e4
listener: VLDP-HW: <- 1f
listener: VLDP-HW: -> 64
listener: VLDP-HW: <- ff
listener: VLDP-HW: -> e4
listener: VLDP-HW: <- f7
listener: VLDP-HW: Search to frame 197

Researching real LD-V1000 behavior

So yesterday I observed that Dragon's Lair was ignoring some command strobes (actually a lot of them) and just staying in input mode during this time. The result was that after a successful seek, the AVR would read back codes like 0xD0. I guess the real LD-V1000 had some pull-up (and/or pull-down) resistors for handling this scenario which I probably ought to implement.

UPDATE: Looks like my LD-V1001 won't play discs anymore, or even respond to play. That means all it is good for is comparing strobe timings :) I guess this gives new motivation for me completing my project! Hehe.

Monday, March 28, 2011

I/O with Dragon's Lair working!

It looks like I am receiving the proper commands from the Dragon's Lair board!
Unfortunately, my own AVR code seems to be pretty buggy because it is not responding properly to those codes. This is a little surprising because I am using the exact same code on the AVR to interpret and handle the laserdisc state as I am in windows/linux for DAPHNE. I did this on purpose to ensure that the AVR code would be good. Well, apparently it's not so good. But the problem is probably only in one or two places. For all I know, it's a buffer overrun or some nonsense like that.

Basically, what I am seeing right now is Dragon's Lair is sending the proper search/play codes and the AVR is responding with endless "busy searching" codes. Bad AVR! :)

At least the problem is back in my software which is my specialty, so it shouldn't be too hard to fix.

Saturday, March 26, 2011

Mystery Solved!

The reason Dragon's Lair was not booting was because I did not have pin 17 (the Enter signal) connected. It was just a dangling wire coming from the dragon's lair hardware. The LD-V1000 manual made it sound like this pin wasn't used anymore so I didn't think that it mattered if it was connected, but I had eliminated almost every other possibility as being a potential problem so hooking up the Enter signal was one of the last things I hadn't tried. The reason I hadn't hooked it up earlier was because I had made the wire too short so it was inconvenient *embarrassed grin*.

If someone with dragon's lair schematics and time on their hands wants to figure out why this line needs to be connected, I would be interested in hearing about it. :)

More troubleshooting

I read in the AVR datasheet that on port B, some of the pins are used to reprogram the AVR. So for now I am going to use a different pin set on the STK (probably port A) since power is coming from the parallel port during my tests.

Speaking of power, I measured that ~3.4V are sent from my parallel port when the line is active and drops to ~2.6V once it gets to the breadboard. Unplugged, it is ~4.4V. I also tried to measure the current with my multimeter and got 0.00 even though the light was lit, so I'm hoping this means that the current is very small and won't fry my stuff :)

Soon I will need to plug in my real LD-V1001 and see if my dragon's lair hardware is still even working (that could be the problem).

UPDATE: I just plugged in my LD-V1001 to my dragon's lair game and I got all 3 beeps (I didn't even have a disc in the player but it proves that the strobes were working).

Also, I am communicating to/from the STK600 from a random PC I have through the parallel port, using the command/status strobes and the data lines (I made a cable to control a real LD-V1000 player via the parallel port a few years ago and am using that for testing).

In other words, both the STK600 and the dragon's lair hardware are working properly, but Dragon's Lair can't see the strobes sent from the STK600. I don't know why not, but once I find out, there will be much rejoicing.

UPDATE: I just tested the STK600 again connected to the Dragon's Lair hardware. No dice. I guess the next things to check are the lengths of the strobes when they are active and whether the ribbon cable from the Dragon's Lair to the STK600 is passing the strobes along properly. Since it is working with the LD-V1001 all I can think of is maybe the contacts aren't touching on my customized connector where they are on the LD-V1001's connector. I'm narrowing the possibilities down to a very small place where problems can be occurring.

Friday, March 25, 2011

Troubleshooting...

Update from the lit LED observed from yesterday: the power is coming from the parallel port (when a pin is raised) and going through the 328P. Odd!

I just plugged in port B to the STK600's push-button switches just to test input and port B is only reading 0xBF (instead of 0xFF). This means that pin B6 isn't reading input. I will have to check the data sheet to see if there's something special about pin 6.

UPDATE: well dang, looks like pin 6 can't be used if I have an external clock source active (which I do). I guess I'm glad to have discovered this now rather than later. So I will need to rethink my pin design.

UPDATE #2: well shoot... looks like none of the pin sets (B, C, or D) allow me to use 8 data lines freely. B6 is reserved for external clock sources, pins C only have 7 lines instead of 8 (and one of them is used optionally for RESET which I think I want to keep) and pins D are used for serial I/O and external interrupts. So I think I am going to swap out this 328 for now and put in one of my other AVRs that has more pins just to get this dang thing working! Then I can map out the 328's pins later.

Thursday, March 24, 2011

Plugging into the Dragon's Lair machine powers my breadboard...





I noticed by random chance that when the Dragon's Lair is plugged into the LD-V1000 connector that it is sending power to my breadboard (it is lighting up my LED). This means it is also sending power through the STK600. Should this be happening? I wouldn't expect this to happen.

Strobe pins are plugged into LEDs

I've plugged the pins that output the LD-V1000 status and command strobes into the STK600's LEDs and so far I am not seeing any activity. This would indicate a problem! The odd thing is that I checked my code yesterday and everything _should_ be working. I hope to report good news soon...

UPDATE: Ok, I've reprogrammed the AVR and now the strobes are controlling the LEDs properly. So the AVR code seems to be working fine.

Wednesday, March 23, 2011

Gahhhh

I was sitting here working when all of the sudden it hit me: if Dragon's Lair is only getting to the first beep, then that means that the status/command strobes are not working! And that is exactly what I did not expect when I was imagining what the problem could be. Can't wait to troubleshoot those strobes (probably by plugging them into the STK600's LEDs and see if they are flashing)

Serial port problems resolved, but not there yet

Got the serial port problems resolved but the AVR thinks that Dragon's Lair is trying to send it a "BC" command on startup. As I recall, Dragon's Lair tries to send a "FD" command (play), so it looks like my wiring needs review. Also, I'm only getting one beep so I think my wiring needs double review.. and my code too :)

Tuesday, March 22, 2011

Bummer


Realizing that defects are very common (and almost unavoidable) in software, I try to choose the most convenient debug environments. For example, if I have a choice between debugging code using Visual Studio's debugger or using print statements on the GP2X, I will choose the former every time. It is a lot more powerful and takes a lot less time to find problems.

Well, I failed to foresee a potential issue this morning. I "lugged" my STK600 and breadboard, along with my laptop, out to my garage and hooked it up to my Dragon's Lair. It was a few minutes later that I discovered that serial port communication from the STK600 and my "garage PC" was not working at all. So I fired up minicom and saw that the serial communication worked within minicom so I knew the serial port was good and the STK600 was working properly. That meant that the bug was in _my_ code somewhere. I started debugging, but it was so cold out in the garage that my fingers eventually froze up and refused to function.

So I had to make the disappointing journey back inside to debug this serial port issue in a warmer environment. I'll try the garage thing again tomorrow.

UPDATE: Looks like the problem was that I was doing this:


unsigned char baud_symbol = 0;
baud_symbol = B115200;


which was throwing this warning:

warning: large integer implicitly truncated to unsigned type

but I couldn't see the warning because I was running the entire build process using "make". It wasn't until I wrote a little test app that I saw the warning. I guess this is a lesson to make warnings fail the build :(

The fix was to change it to this:

unsigned int baud_symbol = 0;
baud_symbol = B115200;

Monday, March 21, 2011

AVR code ready for testing

I am basically finished with the first draft of the AVR code. Remaining things to do with it are implement seek delay (and blanking) and spin-up delay but these are not necessary to see it working in action.

The next step is to finish the code for the PC-side of things. I am hoping that it will not take much longer and that I can try it out in my garage within the next couple of days.

Saturday, March 19, 2011

Serial code almost complete for AVR, LEDs hooked up

I'm almost done with the serial code coding on the AVR. Working with only 2k of RAM is really quite interesting. I had to delete quite a few log messages just to conserve space. I had never really thought of ASCII text as taking up a lot of space but it really does when each byte counts.

The last remaining piece of serial code for the AVR that I need to write is the part that receives the new settings from the PC. This shouldn't be that bad. Of course, I still need to finish the serial code for the PC side of things before I can actually test it on real hardware.

I realized it would be nice to see some status without having to rely on the serial port so I dedicated a few of the AVRs pins to controlling LEDs. I haven't nailed down exactly what I want the LEDs to mean but at the moment I'm thinking that I want one LED to indicate whether vsync is being received properly (so it will blink rapidly with each vsync), and I want the other LED to indicate any errors. I am thinking a solid LED would indicate all is well, 1 blink per some interval would indicate that the AVR hasn't heard from the PC yet (may be a problem with the serial port) and 2 blinks per some interval would indicate that the serial buffer has overflowed and some characters had to be dropped (something that I want to avoid at all costs but it's tricky when I have such a small amount of RAM for my buffers).

A little more about serial buffer overflow: I put in a log message to say "vsync!" every time a vsync pulse occurred. This would overflow my outgoing transmit buffer in less than a second because the data could not be sent over the 115200 bps serial link fast enough. So things like that are things I need to watch out for; I need to ensure that I am not spamming log messages too frequently.



UPDATE: Well, I did the math (again) about how fast 115200 bits/second really is and it's really not that fast compared to the speed of a 14.7MHz AVR. I posted the above chart to show that each byte comes in (or goes out) every 1,280 cycles on the AVR so that is an eternity of time to do the necessary processing. So spamming "Got vsync!" every field (16.666ms) should work fine because I can send 192 bytes every field.

So I checked my code again and found a bug. I fixed it and I may try spamming "got vsync!" again just to be satisfied that it won't overflow over a long period of time :)

Friday, March 18, 2011

Some more Microzine disks to save...


Out of this lot, 29, 30, and 34 are done, although I did get some trouble with 34, disk 2, side A. Trying to do a disk archive produced I/O errors so I tried to do a file archive instead (since not all of the disk will be used by files) and all the files copied over successfully *phew*. So I'd say there's a 95% chance that this disk was fully recovered since I think Scholastic gave up on copy protection once they switched to a ProDOS model.

UPDATE: Looks like all the drama about the bad sectors on disk 34 was for nothing because I just realized that Chip had already sent me Microzine 34 and I already successfully saved it. Oh well, it was still exciting seeing the files copy successfully :)

In the midst of writing serial I/O code


I hooked up the ATMega328P to my STK600 yesterday and as you can see by this report, I'm running out of Data (RAM) room fast. I will need to use another 500 bytes at least so I will be using almost all of the 2k max size available.

I'm in the midst of writing the serial I/O routines for the AVR. I'm creating "small" buffers both for transmitting and receiving on the serial port. I say small because they are only about 256 bytes each but that is 1/8 of my total RAM size on this AVR. The receive buffer is necessary because I can't predict when serial input will come in and I need to capture it inside a serial interrupt handler. The transmit buffer though... I'm not so sure I really need it. My thinking is that I may need it because I may have a bunch of log strings I need to send but I may not be able to wait for each byte to be sent before the next vsync comes in, so I need a way to buffer outgoing messages and send them a byte at a time between vsyncs.

But it could be that my buffering routines are just as slow as sending each byte to the serial port and waiting for it to be sent. I will need to calculate this.

One thing that is troubling me is how sophisticated the serial code that I'm writing for the AVR is. It is complicated enough that the chance for defects is pretty good and using my traditional debug methods won't be feasible, or at least it will be less feasible. So I need to find a better way to validate my code without actually having to run it on real hardware.

Thursday, March 17, 2011

Installed ATMega328P into my STK600, fixed my code errors from yesterday






I think I'm finally through with fixing the VBI Compact bugs that I've been dealing with lately. The unit tests really helped. Now I can focus my attention on implementing the serial protocol between the VLDP-HW controller and the VLDP-HW media server. I've already fleshed out the details of how I want the protocol to look so hopefully the implementation goes quickly. Once I'm done with the implementation, then I can hook up this schlop to my Dragon's Lair machine and hopefully see some awesomeness. :)

Oh yeah, I also successfully got the ATMega328P installed into my STK600 as you can see from the pictures. It's so tiny :)

New toys





This little board is so I can use that STK600-DIP board with the ATMega328P.



Whoa.. it comes with an AVR chip in the socket! I was not expecting that. And I have no idea which chip this is :) ATMega32L-8PU? huh? I hope it's awesome :)

Wednesday, March 16, 2011

Compact VBI code has replaced VBI lookup code

I've replaced my VBI lookup code with my VBI compact code. The lookup code uses a lot of memory but is able to quickly find the track/field that houses any picture number (aka frame number) on the disc. This is what I was using for the latest dev version of DAPHNE, but since the AVR only has 2k, I needed a different method so I wrote the VBI compact stuff. I've decided I don't want to maintain two separate methods so I am dumping the lookup code in favor of the compact code and making sure all my unit tests are still passing. A few aren't which means I've got a few bugs. Thank goodness for unit tests.
But carefully debugging this stuff isn't exactly the fun part and I am looking forward to finishing this so I can move on to seeing something interesting happen with my real Dragon's Lair machine.

Tuesday, March 15, 2011

Getting VBI data down to the controller

I spent a decent amount of effort recently coding up a solution to get VBI data down to the AVR (aka the "controller"). The problem is that VBI data uses 3 bytes per line and 3 lines per field. And if your laserdisc has 2 fields per frame and 60,000 frames, then that is 60,000 * 2 * 3 * 3 bytes, so over a megabyte of data. The AVR I am targetting has 2k of RAM so it definitely cannot hold a megabyte. Fortunately, the VBI data usually follows a predictable pattern which can be described in much less space (for example, 36 bytes would be the minimum for an entire disc if the whole disc follows the same pattern). The trick is writing algorithms to find and recognize these patterns from the raw VBI data and compact them down.

Monday, March 14, 2011

Fast booting PC?

Out of curiosity, I did a little googling and apparently newer motherboards have an option in the BIOS to enable "quick boot" which makes the start-up process a lot faster. I'll have to test to see if my motherboard supports this.

Hardware is waiting on software

I've got the hardware-side of my VLDP-HW project completed enough so I'm ready to plug it into my Dragon's Lair machine and see something awesome happen :)

Unfortunately, the software side of things is not done yet. I still need to write the interface between the AVR and the PC and this isn't as trivial as one might think. The interface will be through the serial port, running at 115200 bits per second and it will mainly consist of the AVR telling the PC which field it should be displaying at any given time. A conservative estimate of the bytes/second that this speed will provide is about 10,000 and each field changes at a rate of 60 fields per second, so I should have plenty of breathing room.

I have also been thinking about the following problem:
Real laserdisc players were pretty much ready once you powered them on. You could issue a play command and the disc would start spinning up.

My solution will only be partially ready when it is powered on. The AVR will be ready instantly to communicate with the arcade hardware, but the PC may have a potentially long boot-up time. But the AVR needs the PC to be up and running in order to know which kind of laserdisc player to emulate and what the VBI for the laserdisc will be.

Well I think I've come up with a pretty nifty solution to this problem. The AVR will simply remember its previous settings from the last time it talked to the PC (stored in its EEPROM) and until it hears from the PC, it will assume that those settings have not changed. The AVR can start communicating with the arcade hardware normally (including responding to seek requests) without being connected to the PC and then when the PC comes online, it can get "in sync". I could also make the AVR wait for the PC during its "disc spinning up" stage, but some games (ie Dragon's Lair) don't check to see if the disc has finished spinning up, they just delay a period of time and then assume that the disc must be playing (which is pretty lousy programming by the way hehehe).

So I say again, the communication between the AVR and the PC will need to have some cleverness built into it to solve the above problem.

Saturday, March 12, 2011

Vsync detector chip installed (and working!)


I've installed by LM1881 chip which is designed to detect vsync signals from NTSC/PAL sources. This is important for my VLDP-HW project because a laserdisc player replacement may need to know when vsync occurs in order to be accurate and reliable. (some laserdisc games will not care but some probably will and it's better to be accurate than sorry)

The plan is that the NTSC output, which at this time will come from a PC, will be plugged into the VLDP-HW board via RCA cable so that the VLDP-HW can know when vsync is occurring. And then another RCA cable will come out of the VLDP-HW board and go into the arcade game's NTSC decoder card.

Many thanks to my friend, Warren, who came up with the idea to use this chip and to do the pass-thru scheme. He's helped me a lot on this project :)

Here's a movie of the vsync chip in action (it works!!). WARNING: Movie is 7 minutes long and your eyes may glaze over! :)



Here's the pass-thru cable installed:


Here's me pointing my camera at a TV and taking a picture (infinite loop). This shows that the pass-thru cable is working.

Friday, March 11, 2011

LD-V1000 connector soldered



Time to butcher errr solder this connector.



Wow, I did a horrible job. No surprise there :)
It should still work though.



All ground connections tested and working :)



This thing is ready to plug into the STK600 and my Dragon's Lair hardware.
But first I need to write some more code to make it actually do something interesting.

Got the Sparkfun newbie tutorial completed

I followed this tutorial (after ordering the kit) and got it working. It was pretty exciting to have something to do with electronics actually work for me :)





Then I took it a step further and replaced the tutorial's power supply with a PC power supply.



Thursday, March 10, 2011

Two mysterious packages have arrived!







It's like Christmas morning! :)


The rough inventory:
- A sparkfun newbie starter kit with breadboard (yay!)
- Atmel AVR mega328 (VLDP-HW)
- MAX232 serial port chip (VLDP-HW)
- some resistors, capacitors and LEDs (whatever these are.. lol)
- little power supply
- LD-V1000 female connector (VLDP-HW)
- two female RCA jacks (VLDP-HW)
- TC7662 voltage convertor (Disk ][)
- LM1881N NTSC/PAL video sync separator (VLDP-HW)

Most of this stuff is to help me prototype my VLDP-HW interface. I did get the voltage convertor to help with my Disk ][ project since the Disk ][ stupidly needs -12V and +12V. I hope it works...

Wednesday, March 9, 2011

Stumped.. for now

I am pretty sure my code is sound and I am seeing some unpredictable behavior with the AVR so I am suspecting that perhaps the voltage from the disk drive is unstable. When I was getting readable intervals, I was getting all of them 200-400 cycles apart and some of those intervals should be 60 cycles (4 microseconds at 14.7 MHz) I won't be able to address this issue until some hardware that I've ordered in the mail arrives so for now the disk drive project is officially shelved.

Once the parts arrive, I'll probably start working on the VLDP project instead because that has much more potential for awesomeness. :)

Still getting all 1's...

I plugged in my new revamped assembly language routine and I am getting the same results as I was two days ago. Instead of being frustrated, however, I am starting to get really curious what's going on.

My next step is to time the intervals between pulses again and see if something has changed.

Assembly language routine written!

As I said yesterday, I decided that I needed to re-write my code in AVR assembly language in order to make it fast enough to be able to reliably detect the 4 microsecond bit cells send from the Apple 5.25" disk drive.

I now have ported both the bit detector function and the interrupt service routine (ISR) to assembly language. The ISR was the one that I was the most keen on optimizing because the C compiler added a bunch of wasteful stack pushes/pops that I didn't need, but I also benefited from optimizing the main loop also because I was able to move a global variable from memory into a register which saved a few cycles.. and when talking about microseconds at 14.7 MHz, a few cycles are worth a lot!

I am excited to test out my new routine on real hardware.

Here is the ISR routine below. As you can see, it's pretty short. It gets activated when a read pulse is received from the 5.25" disk drive.

// this interrupt is triggered when a pulse (connected to INT6 pin) starts (active low)
.global INT6_vect
INT6_vect:
in sreg_save, _SFR_IO_ADDR(SREG) ; preserve flags

; When we store this cycle value to the timer, it will be at most 1 cycle off so it is pretty accurate
; I got this value by counting cycles in the simulator/debugger.
; I want the timer to be relative to the start of the pulse so it's easier to visualize in my head.
; The timer will not overflow within the time that it is useful to us.
ldi u8Timer, 12
out _SFR_IO_ADDR(TCNT0), u8Timer

clr bPulseOccurred ; this register should already be 0 in every case but I want to be safe and this only uses 1 cycle
inc bPulseOccurred ; let main loop know that a pulse started

; we need to wait for the pulse to end or else this ISR will get triggered again immediately
wait_pulse_end:
sbis _SFR_IO_ADDR(PINE), 6
rjmp wait_pulse_end

out _SFR_IO_ADDR(SREG), sreg_save ; restore flags
reti

Tuesday, March 8, 2011

Pulling out my hair

So last night I ambitiously decided to take my AVR program to the next level and instead of just logging elapsed time between pulses from the Apple 5.25" drive, I would actually try to convert these time intervals into actual bits so that the emulation community can enjoy copy-protected disk images someday (I find the concept interesting). So I started writing my AVR program, using C. I carefully stepped through each instruction in AVR Studio's simulator and counted the cycles and I felt like I had come up with a pretty awesome solution if I do say so myself. Then I flashed the code to the real AVR and powered up my Apple //gs.

At first, nothing happened and I found and fixed a bug in one of my loops. Then I tried again.

For the next hour, my supposed-to-be-awesome program sat there insolently spitting out 1's at me, no 0's at all. And since I was expecting a healthy mix of 1's and 0's, I was not getting the correct data here that I wanted! I pulled out my hair for probably an hour, then sighed in defeat and decided to go to sleep.

Once I got upstairs, I realized that maybe the problem was that my C program was simply too slow. Also, it didn't help that I was trying to take the easy way out and not use any interrupt handling.

So now I am resigned to the fact that I will probably have to rewrite the program in assembly language and use one or more interrupt handlers to ensure that my timing is rock solid. I had wanted to avoid this because coding in C is so much faster, but I can't seem to tell the C compiler that I want every variable stored in a register instead of in memory. I came close... :)

Hopefully I will have some good news soon.

Monday, March 7, 2011

Wow, I'm closer than I thought


Looking at the AVR elapsed cycle timings in the terminal program was kind of depressing but once I plugged the numbers into a spreadsheet, they looked like I'm almost there as long as I can process the values in a minimal amount of cycles.

This screenshot will hopefully show that a human being (with a lot of knowledge about how the Disk ][ drive works and a spreadsheet) can manually compute the value of the bits that happened to be read at the snapshot in time that this log represents.

It's looking really good! :)

Setting up my AVR has been a real pain

So recently (within the last month), I decided that I needed to learn about micro-controllers (basically cheap mini CPUs) so I could move some of My Cool Projects forward. A friend recommended the Atmel STK600 as a good starter kit, so I got one. The good news is that the STK600 is pretty awesome, the bad news is that the documentation for it is abysmal. So I've been maintaining my own "getting started" guide to help anyone else who may want to tread these waters.

You can find my guide here.

Seventeen Microzine games saved

Thanks to a few friends who have sent me 5.25" floppies in the mail, I have now recovered seventeen Microzine games. It's surprising how readable the floppies were considering they are 25 years old! Some of my personal favorites were Microzine #9 (the Big Nap) and Microzine #8 (Zazoo Come Home). I played these relentlessly when I was in 6th grade. Great memories.

The disk images are downloadable here.

You can play these using an Apple 2 emulator such as AppleWin or KEGS.

Sunday, March 6, 2011

Getting closer ...


I am thinking that maybe the reason I was getting weird results earlier is because the disk had not had a chance to spin up fully. I created a longer delay and am getting the results I am expecting here, although there are still a few errors.
I will probably have to wait until I find a string of sync bytes before I know whether the drive is spun up properly.

Optimized code a little bit


I've optimized the AVR code a little bit so that the timing for when the disk drive is sending a "clock" signal is now really tight and I am getting the correct results. Since the AVR is clocked at 14.7456 MHz (so that it can send serial communications reliably), 1 microsecond is about 0xE cycles, and I am alternating between 0xC and 0xF cycles in my tests which is exactly what I would expect. Unfortunately, the lengths after the "1" bit are too long. Each bit field is 4 microseconds long, which is about 0x3A cycles, so I should be seeing values near 0x2C at least every 8 bits (because every nibble on the drive has the high bit set).

I'm not seeing that, so I'm wondering if I am missing the transition due to some of my code being too slow.

Attempt #2 on the Apple ][ disk drive

Still not much success, but getting closer...

Saturday, March 5, 2011

Microzine!

Back in the mid-80's, Scholastic software used to release software called Microzine that included a choose-your-own-adventure (aka Twistaplot) type game along with some other educational software for elementary school kids. I loved these games and I decided I wanted to play them again. Unfortunately, they were impossible to find on the internet... until now!



I have hooked up the old family Apple //gs and have begun extracting the images off of these old floppy disks so they can be enjoyed in modern emulators.

Apple ][ Disk Drive Project Started

Back in February, I suddenly got interested in the Apple ][ computer after probably 15 years of having not thought about it.

Specifically, I became interested in understanding how the old copy protection schemes worked. So I decided to see what I could do to figure this out. This video represents an early (failed) attempt at reading the raw bits off of an old 5.25" disk.



Hopefully I will be posting some success later.

VLDP-HW Project Introduced

Back in 2009, I embarked upon an ambitious project to prolong the life of classic laserdisc arcade games (such as Dragon's Lair) by attempting to replace the unreliable and old laserdisc players (and associated laserdiscs) with modern, reliable hardware.

I called this project the Virtual Laserdisc Hardware (VLDP-HW), sometimes referred to as VLDP (although this can be ambiguous since my DAPHNE project uses the term VLDP to mean something entirely different).

I made good progress and chronicled my progress in several videos:







After this point, I started working on a web config option to control the virtual laserdisc player, and got distracted on another more interesting project.

Well, I'm pleased to report that the Virtual Laserdisc Project is BACK ON after a 1.5 year hiatus :)

I intend to post updates here as I make them. Stay tuned.

Welcome

Here I will (sometimes) track the progress of any cool projects that I happen to be working on.