nILS Posted October 14, 2007 Report Posted October 14, 2007 As some of you might have read in the chat or across the forum, I started working on a POKEY synth. My plan is to start with a board designed by Mike Hill way back in time that hooks up to the LPT Port of a computer to test the POKEY and fiddle around with it a bit and hopefully finally come up with an mbPokey board and the MIOS app to go with it.I'll try to use this thread as a blog, mainly to keep me from quitting the project when that damn little chip does what it wants rather than what I want it to =)First up, a few links (most of them have been posted around here somewhere before):http://en.wikipedia.org/wiki/Atari_POKEY - Wikipedia entry for the POKEY chip (polish version is much more in-depth, but my polish isn't really all that good)http://krap.pl/mirrorz/atari/homepage.ntlworld.com/kryten_droid/Atari/800XL/atari_hw/pokey.htm - HTML version of the datasheet of the Pokey. The original datasheet can be found on the web as well - only god and smashTV now where they got it =)http://www.hillsoftware.com/atari/index.html . Mike Hill's website. He's the guy who created the LPT-Pokey schem and wrote a DOS app for it (won't work on Windows obviously)http://www.pokey.nl/xoops/modules/books/index.php?op=viewarticle&artid=10 - Some information on what to do with the POKEY So far, I built the LPT interface on a piece of perfboard and ported Mike's application to Windows and added a complete (well sorta) CS to it, so that I can access all registers. I have a small and rather random sound test right here.I really want to thank SmashTV, Mike Hill, stryd_one and jimp at this point - without those guys I wouldn't even have gotten this far :DI'll post some pictures later on today =)Cheerio,nILS Quote
Wild_Weasel Posted October 14, 2007 Report Posted October 14, 2007 Hi!Where do you source this chips?Are they as hyped as SIDs are?Kind regardsMichael Quote
stryd_one Posted October 14, 2007 Report Posted October 14, 2007 Normally you have to have some documentation in the wiki for a post in this forum, but I think that given you have a semi-working PCB we can overlook that ;) But please share it soon! Quote
nILS Posted October 14, 2007 Author Report Posted October 14, 2007 s1: Yeah, I did read the "read before you post"-thread =) It's just not anything *new* worth documenting here yet. I will put it all down in the wiki when I get a bit further.Wild_Weasel: I bought a "Ballblazer" cartridge for the ATARI 7800 on eBay for ~$5. The commando "Commando" cartridge has a Pokey chip inside as well. Most of the 8bit ATARI computers have one inside, they're a lot more expansive though. You can buy the chips at a lot of outlet type stores (www.batescomponents.com, www.loadparts.com, ...) for about $5-7 a chip. Problem with that is, you have to order >100 chips. Quote
SLP Posted October 14, 2007 Report Posted October 14, 2007 Problem with that is, you have to order >100 chips.If the POKEY will get as famous as the SID, that won't be a problem Quote
Jaicen Posted October 14, 2007 Report Posted October 14, 2007 I think you can rest assured that's not likely to happen anytime soon! The Pokey is a very limited chip for musical applications. Doesn't it have problems in terms of pitch? Personally, I think it has some limited application for bass sounds and chiptune leads, but not much else. Still, if it was simple enough to build I think it would be a neat toy. Quote
nILS Posted October 14, 2007 Author Report Posted October 14, 2007 SLP: I seriously doubt that the pokey will become anything as hyped as the SID is =) It *is* a pretty simple chip. Yet I find it to create some nice sounds if handled right. Since availability of the pokey is great due to ATARI's overproduction right before the crash, not being able to order bulks isn't that big a problem.jaicen: That is very true =) Especially the NTSC version clocked at ~1.79MHz has serious problems with the pitch. I did some calculations today (thanks stryd ;)) and found the PAL version at ~1.77MHz to be way more accurate. At the moment I'm running the pokey on 1.8432 since it was the closest crystal available w/o any frequency dividers - the pitch difference is noticeable =)About the "simple to build" part: Well, the core module is obviously the same and the pokey module is extremely close to the SID board. What would/will keep this simple is the fact that the CS (which is really the only "hard to build" thing) will be a lot smaller and simpler than for the SID. Basically, all you would need is 5x8 buttons to control the 5 relevant registers - that's it =) This is obviously not the most usable version, but it gives you an idea of the dimension we're talking about. Quote
nILS Posted October 18, 2007 Author Report Posted October 18, 2007 Some minor updates: Since the PAL version isn't that much better when it comes to the pitch and due to the fact that it is virtually impossible to get a hand on a matching crystal, I'm going with the NTSC version. (Thx to SmashTV, stryd_one, jimp and DrBunsen for looking for alternative solutions)Port of my test application (screenshot below) has been ported to C for easier translation to the PIC.Since there's got to be a stereo version I'm looking into ways to drive (at least) 2 pokeys from a core atm.EDIT: I attached the pokey test app so you guys can fiddle around with it, too. Apparently I'm not the only one: sd2000/sparx has a Pokey board as well ;-)Cheerio,nILSpokey_test_app.zippokey_test_app.zip Quote
/tilted/ Posted October 18, 2007 Report Posted October 18, 2007 You can buy the chips at a lot of outlet type stores (www.batescomponents.com, www.loadparts.com, ...) for about $5-7 a chip. Problem with that is, you have to order >100 chips.Not here:http://www.mikesarcade.com/cgi-bin/store.pl?sku=CO12294 Quote
nILS Posted October 18, 2007 Author Report Posted October 18, 2007 Thanks tilted. I must have come across that page earlier, cause when I got there it had 3 pokeys in the shopping basket =) Quote
Jaicen Posted October 18, 2007 Report Posted October 18, 2007 I don't think it actually matters wether you use NSTC or PAL, if you're not going to be clocking it to a display. As long as you can get the timing fixed, you should be able to get it in tune more or less. Quote
nILS Posted October 18, 2007 Author Report Posted October 18, 2007 jaicen: "More or less" is exactly the problem. I really wanted to go for "more" rather than "less" The pokey uses a divide-by-n counter to generate the output frequency from the oscillator it's clocked with. Therefore, there's a direct correllation between Fosc and Fout.In "default mode" the clock frequency gets internally divided by 28 leaving you with ~64kHz as Finternal. The formula for the output frequency in that case is rather simple:Fout = Finternal / (AUDF+1) * 2AUDF being a register holding a byte determining the frequency. Even though the difference in the Finternal is rather small between NTSC and PAL (633337.39Hz for PAL, 63920.45Hz for NTSC), NTSC tends to be a little bit more off. Not enough to justify going through custom-crystal-shaving or anything like that though. Quote
nILS Posted October 22, 2007 Author Report Posted October 22, 2007 I finally put sth. in the wiki (http://www.midibox.org/dokuwiki/midibox_pokey). It needs to and will be extended :)For everyone interested, the first of the pictures below shows what the preliminary version of the mbPokey board looks like. A later version will probably sport a serial out to allow for multiple pokeys.The second one is a picture of the schematic that shows how to hook up a pokey to a printer port on a PC (this is the schematic assuming a 1.77Mhz or 1.79Mhz crystal. It works "kinda" well with a 1.8432Mhz crystal, which is widely available).EDIT: Some feedback on the first schematic would be greatly appreciated. Quote
/tilted/ Posted October 23, 2007 Report Posted October 23, 2007 The second one is a picture of the schematic that shows how to hook up a pokey to a printer port on a PC (this is the schematic assuming a 1.77Mhz or 1.79Mhz crystal. It works "kinda" well with a 1.8432Mhz crystal, which is widely available).Have you tried diving an OPL3 crystal?The OPL3 board uses a 14.318 MHz crystal.14.318 / 8 = 1.78975...also, I hope later today to upload a crystal to oscillator schem onthe wiki. stand by. Quote
nILS Posted October 23, 2007 Author Report Posted October 23, 2007 Have you tried diving an OPL3 crystal?The OPL3 board uses a 14.318 MHz crystal.Yes, we've discussed that in the chat. There's no need to use a 14.318Mhz crystal and divide it by 8 (for instance by using 3 flip flops), since 3.579545Mhz oscillators are widely available and only need to be divided by two (one flip flop) as seen in the first schematic.Using a crystal and building an oscillator circuit has been discussed as well, but it doesn't really lead to any better results as basically all crystal "speeds" come as oscillators, as well.So, the bottom line is that I think adding a single IC (a dual D-Flip-Flop (i.e. 74HC74)) to the circuit is the best and easiest solution. Quote
stryd_one Posted October 23, 2007 Report Posted October 23, 2007 Yes, we've discussed that in the chat. Did we ever! LOL ;D Quote
nILS Posted October 23, 2007 Author Report Posted October 23, 2007 Did we ever! LOL ;DI should have put "extensively" or something similar in that sentence :D Quote
nILS Posted October 23, 2007 Author Report Posted October 23, 2007 The attachment is an excel table that calculates the output frequency depending on the crystal. Possible values for columns A and E are B2 / 28, B2 / 114 and B2 (for the left side, atm being PAL) B2 is the clock frequency. Happy fiddling tilted =)Pokey_Note_Table.zipPokey_Note_Table.zip Quote
nILS Posted October 24, 2007 Author Report Posted October 24, 2007 At the moment I'm trying to set up the Core -> Pokey module data transfer. I figure it's going to be similar to what TK did in the SID app.Buuuut, I'm kinda stuck. So here's for all code gurus:The parallel output source:#define ACTIVE 0 #define INACTIVE 1#define STROBE 2#define PORT 0x378#define PORTCONTROL PORT#define PORTDATA PORT + 1void WritePokey(unsigned char addr, unsigned char byte){ PLatchAddress(addr); PLatchData(byte); PChipSelect(STROBE);}void PLatchData(unsigned char val){ Pokey_Out(PORTCONTROL, 0); Pokey_Out(PORTDATA, val); Pokey_Out(PORTCONTROL, 2); Pokey_Out(PORTCONTROL, 0);} // PLatchDatavoid PLatchAddress(int add){ Pokey_Out(PORTCONTROL, 0); Pokey_Out(PORTDATA, add); Pokey_Out(PORTCONTROL, 8); Pokey_Out(PORTCONTROL, 0);} // PLatchAddressvoid PChipSelect(int mode){ if (mode == INACTIVE) Pokey_Out(PORTCONTROL,0); if (mode == ACTIVE) Pokey_Out(PORTCONTROL,1); if (mode == STROBE) { Pokey_Out(PORTCONTROL,1); Pokey_Out(PORTCONTROL,0); }} // PChipSelect[/code]This is basically what I need to port to serial output for the Core.Any pointers would be greatly appreciated =) Quote
nILS Posted October 24, 2007 Author Report Posted October 24, 2007 So far what's happened is I took the source from the SID v1.7303 (sid_sr.inc) and thinned it out a bit (taking out the WT and reducing it to the 10 registers needed). This is the result so far:;; MIDIbox POKEY; POKEY Shift Register Service Routine;; ==========================================================================;; Copyright 1998-2006 Thorsten Klose (tk@midibox.org); Licensed for personal non-commercial use only.; All other rights reserved.;; ==========================================================================;; define the pins to which the MBHPS_POKEY module is connected;SID_SR_LAT_SCLK EQU LATDSID_SR_PIN_SCLK EQU 5 ; Pin D.5SID_SR_LAT_RCLK EQU LATCSID_SR_PIN_RCLK EQU 4 ; Pin C.4SID_SR_LAT_OUT EQU LATDSID_SR_PIN_OUT EQU 6 ; Pin D.6SID_SR_LAT_WR EQU LATCSID_SR_PIN_WR EQU 5 ; Pin C.5;; --------------------------------------------------------------------------;; Initialize the MBHP_POKEY module;; --------------------------------------------------------------------------SID_SR_Init ;; reset the POKEY clrf MIOS_PARAMETER1 clrf MIOS_PARAMETER2 call SID_SR_Write movlw 0x0F movwf MIOS_PARAMETER1 movlw 0x03 movwf MIOS_PARAMETER2 rgoto SID_SR_Write ;; reset will be released with first call of SID_SR_Handler;; --------------------------------------------------------------------------;; Check for changes in POKEY registers, transfer values to SID;; --------------------------------------------------------------------------SID_SR_Handler IFSET SID_STAT, SID_STAT_ENGINE_DISABLE, return_SID_SR_HandlerSID_SR_Start TABLE_ADDR SID_SR_REGWRITE_TABLE ; contains order of register accesses movlw 0x0A ; number of registers (0x0A) movwf TMP1 ; TMP1 is the loop counter lfsr FSR0, SID_BASE ; store base address of SID registers in FSR0 lfsr FSR1, SID_SHADOW_BASE ; store base address of shadow registers in FSR1 IRQ_DISABLE ; disable interruptsSID_SR_Loop tblrd*+ movf TABLAT, W movff PLUSW0, MIOS_PARAMETER2 ; store value of SID in MIOS_PARAMETER1 and increment FSR0 IFSET SID_STAT, SID_STAT_FORCE_REFRESH, rgoto SID_SR_Transfer; don't skip if refresh has been forced movf PLUSW1, W ; get content of appr. shadow register IFNEQ MIOS_PARAMETER2, ACCESS, rgoto SID_SR_Transfer ; transfer to SID if not equal rgoto SID_SR_Next ; skip following code if equalSID_SR_Transfer ;; register change: write value into shadow register and transfer it to SID movf TABLAT, W movff MIOS_PARAMETER2, PLUSW1 ; store value in shadow register movf TABLAT, W ; extract address offset iorlw 0xe0 ; (note: reset line must stay 1) movwf MIOS_PARAMETER1 ; store in address register rcall SID_SR_Write ; transfer to SIDSID_SR_Next decfsz TMP1, F ; decrement loop counter until it is zero rgoto SID_SR_Loop return;; --------------------------------------------------------------------------;; SID Write: write to SID register;; --------------------------------------------------------------------------SID_SR_Write ;; SID signals: ;; MIOS_PARAMETER2[7..0]: Data ;; MIOS_PARAMETER1[4..0]: Address ;; MIOS_PARAMETER1[5] : Reset ;; temporary used as counter: MIOS_PARAMETER3 bcf SID_SR_LAT_SCLK, SID_SR_PIN_SCLK ; clear clock ;; superfast transfer with unrolled loop (takes some memory, but guarantees the ;; lowest system load :)SID_SR_WRITE_BIT MACRO reg, bit bcf SID_SR_LAT_OUT, SID_SR_PIN_OUT ; set out pin depending on register content (reg.bit) btfsc reg, bit bsf SID_SR_LAT_OUT, SID_SR_PIN_OUT bsf SID_SR_LAT_SCLK, SID_SR_PIN_SCLK ; rising clock edge bcf SID_SR_LAT_SCLK, SID_SR_PIN_SCLK ; falling clock edge ENDM SID_SR_WRITE_BIT MIOS_PARAMETER2, 0 SID_SR_WRITE_BIT MIOS_PARAMETER2, 1 SID_SR_WRITE_BIT MIOS_PARAMETER2, 2 SID_SR_WRITE_BIT MIOS_PARAMETER2, 3 SID_SR_WRITE_BIT MIOS_PARAMETER2, 4 SID_SR_WRITE_BIT MIOS_PARAMETER2, 5 SID_SR_WRITE_BIT MIOS_PARAMETER2, 6 SID_SR_WRITE_BIT MIOS_PARAMETER2, 7 SID_SR_WRITE_BIT MIOS_PARAMETER1, 0 SID_SR_WRITE_BIT MIOS_PARAMETER1, 1 SID_SR_WRITE_BIT MIOS_PARAMETER1, 2 SID_SR_WRITE_BIT MIOS_PARAMETER1, 3 SID_SR_WRITE_BIT MIOS_PARAMETER1, 4 SID_SR_WRITE_BIT MIOS_PARAMETER1, 5 SID_SR_WRITE_BIT MIOS_PARAMETER1, 6 SID_SR_WRITE_BIT MIOS_PARAMETER1, 7 bsf SID_SR_LAT_RCLK, SID_SR_PIN_RCLK ; latch SID values bcf SID_SR_LAT_OUT, SID_SR_PIN_OUT ; clear out pin (standby) bcf SID_SR_LAT_RCLK, SID_SR_PIN_RCLK ; release latch ;; synchronize with rising edge of SID clock to avoid setup or hold violation ;; note: due to pipeline effects, the "bcf" will be executed 3 instruction cycles after ;; the polling loop. Therefore we are waiting for the falling edge IFCLR PORTC, 2, bra $-2 ; wait for falling clock edge IFSET PORTC, 2, bra $-2 bcf SID_SR_LAT_WR, SID_SR_PIN_WR ; enable write (MBHP_SID: chip select) bra $+2 ; to ensure compatibility with on-board oscillator, bra $+2 ; wait for 1.2 uS (> one SID clock cycle) bra $+2 bra $+2 bra $+2 bra $+2 bsf SID_SR_LAT_WR, SID_SR_PIN_WR ; disable write (MBHP_SID: chip select) return;; --------------------------------------------------------------------------;; SID Phase sync: called by the SID_SR_Handler after a register update;; expects pointer to SID_Vx_CTRL in FSR0 and to the appr. shadow register in FSR1;; checks if test bit set - if so, clears the test bit, sets the gate bit;; and transfers the updated control register to the SID;; --------------------------------------------------------------------------SID_SR_OscPhaseSync IFCLR INDF0, 3, return ; no phase sync if test bit not set bcf INDF0, 3 ; clear test bit bsf INDF0, 0 ; set gate bit ;; transfer new value into shadow register movf INDF0, W ; transfer new value into shadow register movwf INDF1 ;; and transfer it to the SID movwf MIOS_PARAMETER2 ; data movf FSR0L, W ; extract address offset addlw -(SID_BASE & 0xff) iorlw 0xe0 ; (note: reset line must stay 1) movwf MIOS_PARAMETER1 ; address rgoto SID_SR_Write;; --------------------------------------------------------------------------;; This routine writes to the SR register;; used by SID_SW_Note in sid_sw.inc;; expecting offset to AD register in WREG, and data in MIOS_PARAMETER2;; --------------------------------------------------------------------------SID_SR_Write_SR iorlw 0xe0 ; refresh SID AD register movwf MIOS_PARAMETER1 ; address rgoto SID_SR_Write;; --------------------------------------------------------------------------SID_SR_REGWRITE_TABLE ;; order in which the SID registers are written ;; note that the control register (which contains the gate flag) is not written before ;; the other OSC registers have been initialized db 0x01, 0x00, 0x03, 0x02, 0x05, 0x04 db 0x07, 0x06, 0x08, 0x0F, 0x0c, 0x0d[/code] Quote
/tilted/ Posted October 25, 2007 Report Posted October 25, 2007 So, the bottom line is that I think adding a single IC (a dual D-Flip-Flop (i.e. 74HC74)) to the circuit is the best and easiest solution.Sorry to drop in with more hardware stuff, but might i suggest a 74HC393 Dual 4-bit Binary Counter instead of a dual d-flip-flop.as there are two four-bit counters, you can divide the clock source by up to 256. I guess this means you could use a clock source up to tens or hundreds of MHz... I'm just saying this because pitch seems to be a serious concern with this chip. Quote
nILS Posted October 25, 2007 Author Report Posted October 25, 2007 /tilted/: Right. We could do that, but since there are 2x[desiredMhz] and 8x[desiredMhz] oscillators all over the place I don't think, that this will be necessary. I'll probably replace the Dual Flip Flop with Quad Flip Flop and some jumpers to allow using 1x, 2x, 4x and 8x [desiredMhz] oscillators. It's a matter of taste really. But this should give us enough room to optimize the circuit =) Quote
idiotcountry2 Posted November 1, 2007 Report Posted November 1, 2007 Hi Nils,I know you are just getting the single POKEY implementation down, but Atari developed a Quad Pokey chip (and the ever popular Quad Pokey eliminator board which replaced the single Quad Pokey chip with four individual Pokeys). Four Pokeys can do quite a bit sonically. Please investigate :)Please see the MAME source code for the Pokey implementation. There are some undocumented commands, etc.http://www.mamedev.org/source/src/emu/sound/pokey.txt.htmlhttp://www.mamedev.org/source/src/emu/sound/pokey.h.htmlhttp://www.mamedev.org/source/src/emu/sound/pokey.c.htmlThe SID stuff is also interesting...http://www.mamedev.org/source/src/emu/sound/index.htmltm Quote
nILS Posted November 2, 2007 Author Report Posted November 2, 2007 idiotcountry2: I heard and read a bit about that, and will surely check it out in more detail. Thanks for the hints! Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.