Asmusr Posted February 8, 2018 Share Posted February 8, 2018 I'm working on emulating cassette tape in JS99er.net. My question is, once the 9901 timer has generated and interrupt, what does it take to re-enable the countdown to generate another? According to Nouspikel, you need to to enter and leave timer mode, perhaps even write at least one bit to the clock register, but the cassette save routine only seems to be using SBZ 0 to restart the timer, even though the TMS9901 is already in I/O mode. Thanks, Rasmus Quote Link to comment Share on other sites More sharing options...
+mizapf Posted February 8, 2018 Share Posted February 8, 2018 TMS9901 specification (found on Whtech), pages 5 and 8 The clock functions as an interval timer by decrementing to zero, issuing an interrupt, and restarting at the programmed start value. When the clock interrupt is active, the clock mask (mask bit 3) must be written into (with either a "1" or a "0") to clear the interrupt. If a value other than the initially programmed is required, a new 14-bit clock start value is similarly programmed by executing a CRU write operation to the same locations. During programming the decrementer is restarted with the current start value after each start bit is written. A timer restart can be easily implemented by writing a single bit to any of the clock bits. Quote Link to comment Share on other sites More sharing options...
Asmusr Posted February 9, 2018 Author Share Posted February 9, 2018 If a value other than the initially programmed is required. ... A timer restart can be easily implemented by writing a single bit to any of the clock bits. Thanks. The question is what if you don't need a value other than the initially programmed? Do you still need to change something in the clock register or can you just clear the interrupt (SBO 3) and it will generate another one? Nouspikel says "The decrementer will not generate any more interrupts after that one, unless re-enabled by entering and exiting timer mode.", is that correct? Quote Link to comment Share on other sites More sharing options...
+mizapf Posted February 9, 2018 Share Posted February 9, 2018 (edited) Maybe write a sample program? [Edit: In MAME's implementation, the timer interrupt is latched. That is, it remains asserted until you clear it. For that reason, there cannot be another interrupt until you clear it. See https://github.com/mamedev/mame/blob/master/src/devices/machine/tms9901.cpp . It's already many years ago that I had a look at that piece of code.] Edited February 9, 2018 by mizapf Quote Link to comment Share on other sites More sharing options...
apersson850 Posted February 9, 2018 Share Posted February 9, 2018 The timer will run regardless of what you do. But if you don't clear the interrupt after it happened, you'll not see any action from the 9901. It can't generate a new interrupt until you've cleared the old. But count, it will. Quote Link to comment Share on other sites More sharing options...
Asmusr Posted February 9, 2018 Author Share Posted February 9, 2018 Maybe write a sample program? Isn't that difficult since the interrupt is hardwired to the cassette ISR? Quote Link to comment Share on other sites More sharing options...
Asmusr Posted February 9, 2018 Author Share Posted February 9, 2018 The timer will run regardless of what you do. But if you don't clear the interrupt after it happened, you'll not see any action from the 9901. It can't generate a new interrupt until you've cleared the old. But count, it will. Yes that's also my understanding now. So I guess Nouspikel's page is wrong or at least confusing. Quote Link to comment Share on other sites More sharing options...
+mizapf Posted February 9, 2018 Share Posted February 9, 2018 Isn't that difficult since the interrupt is hardwired to the cassette ISR? No, the interrupt is not hardwired, since after the 9901 there is only the INTREQ* line of the 9900, and there you cannot tell where the interrupt came from. But you're partly right ... there is another issue. Have a look at the interrupt handler: 0900: LIMI >0000 0904: LWPI >83E0 0908: CLR R12 090A: COC @>0032,R14 090E: JNE >0914 0910: B @>1404 0914: TB 2 0916: JNE >094A 0918: LI R12,>0F00 091C: SBO 1 091E: SBZ 0 0920: AI R12,>0100 0924: CI R12,>2000 0928: JEQ >0946 092A: SBO 0 092C: CB @>4000,@>000D 0932: JNE >091E 0934: MOV @>400C,R2 0938: JEQ >091E 093A: MOV R2,R0 093C: MOV @>0002(R2),R2 0940: BL *R2 0942: MOV *R0,R2 0944: JMP >0938 0946: B @>0AB8 ... 0AB0: MOV @>83C4,R12 0AB4: JEQ >0AB8 0AB6: BL *R12 0AB8: CLR R8 0ABA: LWPI >83C0 0ABE: RTWP The handler decides that it is a cassette interrupt by checking the flag in R14 (090A). This is set when the cassette routine is initialized. So suppose you trigger the counter interrupt outside of the cassette routine (without setting that bit in R14), then this handler will be called. It finds the bit reset and continues with 0914. There it checks whether it was the VDP. Since it was the decrementer, it continues at 0918 and searches through the DSRs for ISRs. When done, it skips the rest and returns. It won't leave you a chance to call an own interrupt handler (0AB6). Quote Link to comment Share on other sites More sharing options...
Asmusr Posted February 9, 2018 Author Share Posted February 9, 2018 It won't leave you a chance to call an own interrupt handler (0AB6). Well, there's this solution on Nouspikel's site, but I haven't tried it: Jeff Brown's solutionThis solution was suggested to me by Jeff Brown, the man behind the interrupt mod. His idea is very elegant: if we fail to acknowledge VDP interrupts any further interrupt will be considered as VDP, so we could use the "interrupt hook" address >83C4 to branch to our own routine after any interrupt type. Only problem: VDP interrupts are acknowledged by the ISR in the console ROMs, and this is done before it calls our routine. Fortunately, there is a way out: reseting the interrupt is done by reading the VDP status at >8802, which is coded as MOVB @>FC00(R15),@>837B in the console ROMs. R15 in the GPL workspace contains the address of the VDP "read address" port >8C02. So all we need to do is to scramble this value, and the console ISR won't be able to clear interrupts any longer.Of course, there are unwanted side-effects to this techniques: We won't be able to detect genuine VDP interrupts. So if you need automated sound list processing, sprite automotion, or a functional <quit> key, you'll have to code these within your program. Any routine that expects to find >8C02 in R15 of the GPL workspace won't work properly. This may include some of the routines in the console ROMs (such as the GPL intepreter). Again, you will need to have your own version of these if you need them. This being said, click here for a complete listing of Jeff's solution. Quote Link to comment Share on other sites More sharing options...
+mizapf Posted February 9, 2018 Share Posted February 9, 2018 This "solution" sounds pretty painful to me. Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted February 9, 2018 Share Posted February 9, 2018 (edited) Jeff Brown's interrupt solution is the basis for how I implemented TIMXT's RS232 ring buffer. The result was being able to capture incoming data at 38.4K. I haven't used the 9901 timer aspect (yet) but that is on my list for keyboard buffering and some simple sound generation. So yes, the solution is viable (edit: to the extent that I have tested and used it with the external bus interrupts) For Disk IO, I restore R15 and make a few adjustments to DSRLNK before calling the DSR. Edited February 9, 2018 by InsaneMultitasker Quote Link to comment Share on other sites More sharing options...
apersson850 Posted February 9, 2018 Share Posted February 9, 2018 I've used the timer interrupt to schedule task switching in assembly programs. But I can do that easily, since my 16-bit wide RAM expansion is 64 Kbytes, and can overlap console ROM if I like to. So I can easily change the interrupt vectors, as needed. 1 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted February 13, 2018 Author Share Posted February 13, 2018 JS99er.net version 5.12 now has support for loading from and saving to CS1. The file format is audio 'wav' files that should be compatible with real hardware. Loading of files from other sources works best if the background noise level is low. I have not tried it with lots of files yet, but it works with many of the files from ftp://ftp.whtech.com/Cassettes/rawWAVfilesincluding the attached. I have tried to implement this without cheating too much. The original ROM routines are used for saving and loading but I had to patch a few bytes to control the timing. I'm also doing some processing of audio samples in order to implement the CRU interface for reading from and writing to the tape. While the audio you hear is provided in real time the CRU read interface is only making bits (or flux changes) available on demand, so the TI may finish loading before the audio has ended and vice versa. 3DLABY.wav 5 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted February 13, 2018 Author Share Posted February 13, 2018 If the emulator doesn't load it's probably a browser caching issue. Try to click F12 to open the console, choose the Network tab, click in 'disable cache' and reload the page. Quote Link to comment Share on other sites More sharing options...
+arcadeshopper Posted February 13, 2018 Share Posted February 13, 2018 where do you select the tape file? open file? nevermind I found the tab Greg Quote Link to comment Share on other sites More sharing options...
Retrospect Posted February 13, 2018 Share Posted February 13, 2018 (edited) Love it! brilliant The tape works, I'm going to be creating some CS1 tape games. Maybe's one of us open up a new thread for CS1 games? EDIT: I've opened up a thread for tape games. There's two in there already from me. Edited February 13, 2018 by Retrospect 1 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted February 13, 2018 Author Share Posted February 13, 2018 I tried to load a wav file into a real TI from the ear plug of a PC, but even though I turned the volume up to 100% there was no audio on the TI. I think I managed to do this a few years ago, but I don't remember if there was some trick to make it work? Quote Link to comment Share on other sites More sharing options...
+arcadeshopper Posted February 13, 2018 Share Posted February 13, 2018 I tried to load a wav file into a real TI from the ear plug of a PC, but even though I turned the volume up to 100% there was no audio on the TI. I think I managed to do this a few years ago, but I don't remember if there was some trick to make it work? the pc plug is stereo, the ti is mono, you may have to pull it out "a bit" to get audio.. or use a stereo to mono adapter .. I use a stereo to rca adapter then rca to mono on one channel to ensure one signal Quote Link to comment Share on other sites More sharing options...
Sinphaltimus Posted February 13, 2018 Share Posted February 13, 2018 the pc plug is stereo, the ti is mono, you may have to pull it out "a bit" to get audio.. or use a stereo to mono adapter .. I use a stereo to rca adapter then rca to mono on one channel to ensure one signal I wonder if the radio shack cassette adaptor I have does that on its own. I just used my cell phone to load up a cassette game "Dealer" from the other topic and it worked, I heard the audio also. Or possibly that my VLC player plays mono through both channels by default, I dunno but that would have thrown me for a loop as well if it didn't work. 2 Quote Link to comment Share on other sites More sharing options...
LASooner Posted February 13, 2018 Share Posted February 13, 2018 try setting, your audio balance to full left, and see if that helps. Also make sure you have an audio enhancements turned off, like virtual surround, or enhanced bass. Quote Link to comment Share on other sites More sharing options...
Asmusr Posted February 14, 2018 Author Share Posted February 14, 2018 Using alligator clips, if I connect the audio output from the PC to the tip of the jack on the white cable and the ground on the red cable I hear audio on the TI. Likewise if I connect to the red tip and white ground or to the two tips. But if i connect to the white tip and the white ground I don't hear anything. The audio is not very load in any case and I'm getting read errors. Could there be a problem with my cable? It looks like a genuine TI cable. Quote Link to comment Share on other sites More sharing options...
+arcadeshopper Posted February 14, 2018 Share Posted February 14, 2018 do you have a cassette tape player to test with? I've found some soundcards put out lousy sound/volume Quote Link to comment Share on other sites More sharing options...
Asmusr Posted February 14, 2018 Author Share Posted February 14, 2018 do you have a cassette tape player to test with? I've found some soundcards put out lousy sound/volume No I don't have a cassette player, but I have just ordered one from ebay. I do believe the output volume from my PC is too low, but I'm more confused about why I need to swap the connections to get any audio? I would really like to be able to load my 4K game into a real TI from cassette, it's so authentic. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted February 14, 2018 Share Posted February 14, 2018 No I don't have a cassette player, but I have just ordered one from ebay. I do believe the output volume from my PC is too low, but I'm more confused about why I need to swap the connections to get any audio? I would really like to be able to load my 4K game into a real TI from cassette, it's so authentic. I seem to remember a thread where this was discussed and ISTR a problem with the grounds. ...lee Quote Link to comment Share on other sites More sharing options...
Opry99er Posted February 14, 2018 Share Posted February 14, 2018 A small set of powered speakers with a headphone jack fixes this. Also, make sure your TI is grounded. I did this by making sure the P Box was plugged into the side port. See the video below. Some of it will be useful to you, some likely wont. Hope this helps 3 Quote Link to comment Share on other sites More sharing options...
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.
Note: Your post will require moderator approval before it will be visible.