The music doesn’t sound much like Pacman and I don’t know what those monsters are doing there.
The music doesn’t sound much like Pacman
If you have another look at my repo, there’s something there that may be of interest.
Thanks for the music
I have been thinking of other ways of getting controller input.
A very simple button implementation with your top module is to define an array of buttons as an input, use SB_IO to pull them up and assign the negation of the D_IN_0 pin to iomem_rdata. That way reading any register gives you the button values. For example we could rename reg_leds to reg_gpio and writing it would set leds and reading it would read buttons. I could then use my PC gamepad with it or you could make a simple gamepad with buttons.
Another approach is to use the uart to read characters from the PC. You could then use a serial terminal or simple program on the PC to read characters from the keyboard and write to the uart. That needs no change to hardware.bin
Building on that, you could use a serial HM-10 Bluetooth Low Energy device connected to the uart. You could then drive that from a phone app or a handmade controller using another HM-10. This gives you a wireless controller with no change to hardware.bin
I have written phone apps that talk to the HM-10 device. There is software that allows you write an app that runs either on Android or iOS.
Or an ESP32 could be used instead of the HM-10, which gives other options such as a Wifi controller, again without changing hardware.bin.
I think I’d still really like to, if possible, get everything to fit on the TinyFPGA… IMO it makes a more convincing demo if we haven’t had to add a bunch of external stuff to it… it’s also easier for others to pick up the code and play with it that way too.
That said, an outboard processor like an ESP32 would certainly open up a lot of possibilities.
I’ve done a bit of reading today about the actual pacman game from a document written by Chris Lomont: https://www.lomont.org/Software/Games/PacMan/PacmanEmulation.pdf
There’s actually some pretty neat tricks that are used to save memory - including multiple levels of indirection for the sprite colour map. It got me thinking about using my digilent VGA adaptor and maybe aiming for something > 1bpp output. Using that kind of mapping would fit better with the LCD outputs too if we go down that path.
My implementation is coming on, but I will need some eating sound effects soon:
We could do a fairly faithful copy if we followed that guide.
Lawrie, I’ve taken a lot of your improvements and moved them into my branch. Hope that’s okay. Top work BTW - I really like your approach.
I’ve also re-wired things on my breadboard so I can use your pin constraint file to keep things consistent.
Also, I’ve modified my top.v with the conditional includes that you had, but pushed some of the “clutter” down into the actual peripheral definitions. You were asking earlier about how I’d support “read” capability for peripherals - I’ve given examples with the I2C and GPIO modules - basically it involved having a separate iomem_ready and iomem_rdata for each peripheral and muxing them into the picosoc iomem lines.
I’ve got a build now with your i2c code in it, so I think I can finally plug the nunchuck in and start playing. And maybe focus on some higher level goals like improving the audio player, adding support for triggering sound FX (which will help with your pac-man eating soundfx). I’d also like to make it easier to compose tunes and make sound FX. As you can imagine it’s pretty painful at the moment.
Oh, side note, I discovered that I’d transcribed a few of the notes for the pacman theme tune incorrectly. I was wondering why some of the notes sounded a little flat. The new code fixes that too.
Excellent. I will probably stop using my project now and move my Pacman game into a fork of your repository.
I ported @gundy 's demo to the LCD screen: https://twitter.com/DesChips/status/1043508654924816384
Wonderful. I have that screen on order from China so will try it when it arrives.
The refresh rate looks really good too!
Can you share more about what it took to do that? What type of screen? How is it connected? How many pins does it use? How hard would it be to add support for extra colours etc?
I’m excited! The idea of a truly portable retro-style TinyFPGA console might actually be plausible!
I have now put my Pacman game in a fork of your repository. It is still missing a lot and has lots of bugs, but you can play it a bit with the Nunchuk.
I think it’s about 60Hz, It is somewhat by accident given my lack of Verilog expertise
There’s also visible artifacts because rendering is not in sync with LCD refresh, this can be fixed with the Tearing Effect pin of the module.
The screen is this one: https://www.buydisplay.com/default/2-8-inch-tft-touch-shield-for-arduino-w-capacitive-touch-screen-module
with 8-bit parallel interface and without touch screen.
- 8 for the data
- 1 nreset
- 1 ncs
- 1 data/command
- 1 write edge
- 1 read edge (This one I don’t use so we can get rid of it)
- 1 backlight, we would have to make a PWM signal to control the brightness
So 13 pins.
The colors are RGB565 format. To support extra colors we can use palettes.
Me too Thanks for starting up the Verilog design, I tried a few things myself but nothing worked…
I will try to find some time to make a simple prototype PCB.
I’m having trouble getting my cheap nunchuk clone to work
If I look at the results it’s reading from the serial debug log, it seems like the y-axis is being skipped:
Joystick x: 80 <-- actual joystick left-right axis (verified) Joystick y: 4A <-- appears to be accel X Accel x: 7E <-- appears to be accel Y Accel y: 8A <-- appears to be accel Z Accel z: 03 <-- buttons Buttons: 00
… because the buttons aren’t being read properly (buttons are active-low so 00 indicates buttons are pressed, which you’ve used to trigger a reset), my display ends up in a reset loop where the sprites all just flash quickly on the screen then disappear again
It feels like I’m
--->| |<--- this close.
Nice to see the little hi-score and 1-up signs though!
I had two Nunhuk’s from my grandson’s Wii U. Only one of them works. The other has issues similar to yours. I bought another from eBay and that had similar issues. I tested the first one on an Arduino so I don’t think it is my code. Perhaps there are lots of defectives ones around.
I also bought a pair of SNES mini controllers as they were very cheap. They did not work with the Nunchuk code so I need to look at what protocol they use.
It feels like it might be timing related issues with the I2C protocol - eg. master holding the bus while the slave thinks it should be sending the first byte.
I hooked it up to my digilent digital discovery and tried to spy on the traffic, and it seemed to confirm my suspicion, but I don’t really know where to look from here:
Start, hA4 [ h52 | WR ], h00, h00, Stop <-- Notice the two "write" bytes here Start, hA5 [ h52 | RD ], h80 NAK, Stop Start, hA5 [ h52 | RD ], h4B NAK, Stop Start, hA5 [ h52 | RD ], h83 NAK, Stop Start, hA5 [ h52 | RD ], h8F NAK, Stop Start, hA5 [ h52 | RD ], h03 NAK, Stop Start, hA5 [ h52 | RD ], h00 NAK, Stop
I’m not sure how the DD knows when a byte is written by the host vs the nunchuk, but if the above is reliable, then it seems like an extra zero byte is being written than is required.
The two zeroes are because the i2c master implementation currently only supports sending two or three bytes. It should be changed to either 1 or 2 and the shift register reduced in size. However, sending the zero twice did not seem to be a problem for me.
The first Nunchuk that didn’t work for me didn’t work with the Arduino code either. However, I did not investigate it much as I have one Nunchuk that works.
The i2c master does support a write and single read in one operation, but that did not work with the Nunchuk for me. It has worked for other devices. It is not really appropriate for the Nunchuk which needs to read 6 bytes. Most i2c devices support reading the bytes one at a time, e.g sending 1 rather than 0 for reading the second value (joystick y for the Nunchuk), That is they treat the register value as an address to read from. But the Nunchuk didn’t seem to support that.
I am currently trying the change to the i2c master to just send one byte, to see if that makes a difference. I just tried my third Nunchuk (the one I recently bought on ebay) and that fails the same way as yours. I did not try that one on Arduino.
I think just removing “& read” on line 282 on I2C_master.v should make it support 1-byte writes. We then need an i2c function called i2c_write_reg to just send the register. It selects the one-byte write by not setting bit 31 in the i2c write register.
For what it’s worth, I’ve been working on a minimal USB host controller which can be used by PicoSoC to talk to USB peripherals, including an Xbox-style USB gamepad. I’ve got a hacked up test where the TinyFPGA BX can receive the state of the gamepad, but I’m perhaps a week away from having something useful (if all goes well).
It may not be appropriate for this project, since a USB implementation will certainly use more logic cells than an I2C implementation, and also because it requires a precise 48 MHz clock to receive full speed 1.x USB data.
The 48 MHz clock will limit what can be done with VGA output. I’ve tested running 640x480 VGA off a 48 MHz clock by keeping a register which counts fractional 25 MHz pixel clock cycles, and it does work, but the resulting image quality is a bit fuzzy. I assume this is because of clock cycle aliasing. For a while, I was trying to find a clock speed which can be generated by the PLL and is a multiple of both some standard VGA clock speed and also 12 MHz (for USB), but I couldn’t find one. If that were the case, a pair of clock dividers could be used to generate both signals.
In any case, the option may soon be there to use a USB gamepad, if the constraints are acceptable.
I made that change just removing “& read” on line 182 of I2c_master.v and all 3 of my Nunchuk’s started working without any changes to the C code. I am not certain why that is. I will investigate. But the change will probably work for you.
I had difficulty testing things as we are so close to the limit that most builds fail after any minor change.
UPDATE: I discovered why my change made all Nunchuk’s work, without C code changes. It was incorrect and made all i2c writes 1 byte, which for the read requests, but it probably worked for the activate request which is supposed to be x40, x00, but instead it just got x40, but that was followed by writing x00 for the read request.
Anyway, it does look like the double 0x00 write was the problem, and so I just need to get the fix right. I suspect the double 0x00 writes works on genuine Nuchuks but not copies.