RS232-Midiplayer und passender USB-Treiber

ZX-Team Forum
Antworten
Benutzeravatar
siggi
User
Beiträge: 2319
Registriert: 06.12.2005, 08:34
Wohnort: D, Hessen, tiefste Werreraa
Kontaktdaten:

RS232-Midiplayer und passender USB-Treiber

Beitrag von siggi » 13.03.2018, 22:09

So, jetzt wo es erstmal klappt, hier der Midiplayer und passender USB-Treiber (für ZXNU VDRIVE2-Interface!).

Der Midiplayer stimmt noch nicht 100%ig mit der Abspielgeschwindigkeit auf PC überein (das kann vielleicht noch durch Korrektuen in NOVA behoben werden), aber es passt meist ganz gut.

Der Player geht davon aus, daß der USB-Treiber (bzw. UFM mit dem Treiber) bei 8K liegen und daß Joachims RS232-Karte mit Standardadressen benutzt wird. Wenn das nicht so ist, kann auf BASIC-Ebene das alles durch Patchen oder Änderungen im BASIC-Programm angepasst werden (dazu kommt noch mehr).

Hier erstmal der Player:



Und hier der ASDIS-Source des Treibers in A$ (noch mit "Arbeitsnamen" USBT2-13). Neues beim Label LOAD6 und READM:
USBT2-13.P
(10.47 KiB) 17-mal heruntergeladen
Und hier das Listing:

Code: Alles auswählen

          2000;===========================
          2000;USB-ZX81                   
          2000;VON THOMAS LIENHARD        
          2000;PORTIERT ZU ASDIS          
          2000;VON J.MERKL                
          2000;;                          
          2000;---------------------------
          2000;V1.0.0                     
          2000;GRUNDVERSION T.LIENHARD    
          2000;;                          
          2000;V1.1.0                     
          2000;FEHLERMELDUNGEN EINGEBAUT  
          2000;2.EINSPRUNGADR. FUER BASIC 
          2000;MIT FEHLERCODERUECKMELDUNG 
          2000;;                          
          2000;V1.2.0                     
          2000;VARIABLE VERLAGERT         
          2000;;                          
          2000;V1.2.1                     
          2000;KORREKTUREN: SIGGI         
          2000;V1.2.2                     
          2000;DATEILAENGE IN SYSVAR      
          2000;COORD(16438/39)            
          2000;V1.2.3                     
          2000;D,XXXX KOMMANDO HINZU      
          2000;V1.2.4 ZAHLEN NUN DEZIMAL  
          2000;V1.2.5 SPEED OPTIMIERT     
          2000;       EINSPRUNG M/C       
          2000;V1.2.6 BREAK CHECK         
          2000;V1.3.0 MEFISDOS SYNTAX, REN
          2000;V1.3.1 CD ZEIGT NEUE DIR AN
          2000;V1.3.1 BREAK AUCH MIT 6    
          2000;V1.3.3                     
          2000;V1.3.4-NU FUER ZXNU, TIMING
          2000;V2.0.0 STREAMING,LAENGE IN 
          2000;XPTR(16408/09)             
          2000;===========================
          2000     JP UFM         C3B82B  
          2003     JP USB2        C30721  
          2006     JP USB3        C31B21  
          2009     JP USB1        C30E21  
          200C     JP READM       C3222A  
          200F;---------------------------
          200F;VARIABLE                   
          200F     009=$09                
          2018FILNA215=$D7                
          20EFSSTAT001=$01                
          20F0RBYTE001=$01                
          20F1RSTAT001=$01                
          20F2     002=$02                
          20F4STAL 001=$01                
          20F5STAH 001=$01                
          20F6SIZEL001=$01                
          20F7SIZEH001=$01                
          20F8     012=$0C                
          2104MBACK001=$01                
          2105ERRNR002=$02                
          2107;---------------------------
          2107;;                          
          2107USB2 XOR A          AF      
          2108     LD (ERRNO),A   323240  
          210B     INC A          3C      
          210C     JR NUSB        1804    
          210E;;                          
          210EUSB1 CALL $02E7     CDE702  
          2111     XOR A          AF      
          2112NUSB LD (MBACK),A   320421  
          2115;SET RETURN ADDRESS TO BASIC
          2115     LD HL,R2BAS    217221  
          2118     PUSH HL        E5      
          2119     JR USB         1811    
          211B;;                          
          211bUSB3 XOR A          AF      
          211C     LD (ERRNO),A   323240  
          211F     INC A          3C      
          2120     LD (MBACK),A   320421  
          2123;SET RETURN ADDRESS TO MC   
          2123     LD HL,R2MC     217821  
          2126     PUSH HL        E5      
          2127;READ COMMAND FROM PRINTER  
          2127;BUFFER                     
          2127     LD HL,PRBUF    213C40  
          212A     JR USBMC       1803    
          212C;;                          
          212CUSB  CALL NAME      CDA322  
          212FUSBMCLD A,(HL)      7E      
          2130     CP $2D         FE2D    
          2132     JP Z,HLP       CA8021  
          2135     CP $0F         FE0F    
          2137     JP Z,HLP       CA8021  
          213A; AB NUN ZUGRIFF AUF STICK  
          213A     CALL INIT      CD5429  
          213D     LD A,(HL)      7E      
          213E     INC HL         23      
          213F     CP $2E         FE2E    
          2141     JP Z,INFO1     CAC523  
          2144     CP $38         FE38    
          2146     JP Z,SAVE1     CAEB25  
          2149     CP $31         FE31    
          214B     JP Z,LOAD1     CAF026  
          214E     CP $29         FE29    
          2150     JP Z,DIR1      CA6224  
          2153     CP $30         FE30    
          2155     JP Z,DIR1      CA6224  
          2158     CP $3B         FE3B    
          215A     JP Z,DIR1      CA6224  
          215D     CP $2A         FE2A    
          215F     JP Z,ERAS1     CA1E28  
          2162     CP $37         FE37    
          2164     JP Z,REN1      CAD925  
          2167;;                          
          2167     LD DE,TXA      11BA22  
          216A     LD (ERRNR),DE  ED530521
          216E     JP ERROR       C38323  
          2171;;                          
          2171;JUMP TO M/C OR R2BAS       
          2171BASICRET            C9      
          2172;;                          
          2172;JUMP TO BASIC              
          2172R2BASCALL SLOW      CD0702  
          2175     XOR A          AF      
          2176     RST 08         CF      
          2177     FF                     
          2178;;                          
          2178;JUMP TO M/C                
          2178R2MC LD A,(ERRNO)   3A3240  
          217B     OR A           B7      
          217C     CALL NZ,CLBUF  C49C23  
          217F     RET            C9      
          2180;;                          
          2180HLP  LD HL,HLPTX    218E21  
          2183HLP1 LD A,(HL)      7E      
          2184     CP $FF         FEFF    
          2186     JR Z,BASIC     28E9    
          2188     PUSH HL        E5      
          2189     RST 10         D7      
          218a     POP HL         E1      
          218B     INC HL         23      
          218C     JR HLP1        18F5    
          218E;;                          
          218EHLPTXINFO   "I"             
          2198     HALT           76      
          2199     DIR    "D"             
          21A3     HALT           76      
          21A4     CHDIR  "D VERZ"        
          21B3     HALT           76      
          21B4     DIR X  "D,<NUM>"       
          21C4     HALT           76      
          21C5     MKDIR  "V VERZ"        
          21D4     HALT           76      
          21D5     RMDIR  "K VERZ"        
          21E4     HALT           76      
          21e5     LOAD   "L DATEI.P"     
          21F7     HALT           76      
          21F8     BLOAD  "L DATEI.B,<ADR>
          2210     HALT           76      
          2211     SAVE   "S DATEI.P"     
          2223     HALT           76      
          2224     BSAVE  "S DATEI.B,<ADR>
          223C     <LEN>"                 
          2242     HALT           76      
          2243     ERASE  "E DATEI.P"     
          2255     HALT           76      
          2256     RENAME "R NAME NAME"   
          226A     HALT           76      
          226B     HELP   "H"             
          2275     HALT           76      
          2276     HALT           76      
          2277     ABBRUCH MIT "A" ODER "6
          228F     HALT           76      
          2290     HALT           76      
          2291     V2.0.0 FUER ZXNU       
          22A1     HALT           76      
          22A2     FF                     
          22A3;;                          
          22A3NAME RST 20         E7      
          22A4     CALL $0F55     CD550F  
          22A7     LD A,($4001)   3A0140  
          22AA     ADD A,A        87      
          22AB     JP M,$0D9A     FA9A0D  
          22AE     POP HL         E1      
          22AF     RET NC         D0      
          22B0     PUSH HL        E5      
          22B1     CALL $02E7     CDE702  
          22b4     CALL $13F8     CDF813  
          22B7     LD H,D         62      
          22B8     LD L,E         6B      
          22B9     RET            C9      
          22BA;;                          
          22BATXA  0112                   
          22BC     ungueltiger befehl     
          22CETXB  0216                   
          22D0     ungueltiger dir-befehl 
          22E6TXC  0317                   
          22E8     file/dir nicht gefunden
          22FFTXD  040B                   
          2301     device voll            
          230CTXE  0513                   
          230E     file/dir noch offen    
          2321TXF  060A                   
          2323     ladefehler             
          232DTXG  0716                   
          232F     device nicht vorhanden 
          2345TXH  0805                   
          2347     break                  
          234CTXI  090E                   
          234E     dir nicht leer         
          235CTXX  00000000000000000000   
          2366     00000000000000000000   
          2370     00000000000000000000   
          237A     0000                   
          237C;;                          
          237CBRKERLD DE,TXH      114523  
          237F     LD (ERRNR),DE  ED530521
          2383;;                          
          2383ERRORLD A,(MBACK)   3A0421  
          2386     CP $01         FE01    
          2388     JR NZ,NERR     2009    
          238A     LD HL,(ERRNR)  2A0521  
          238D     LD A,(HL)      7E      
          238E     LD (ERRNO),A   323240  
          2391     JR ERROB       1803    
          2393NERR CALL TXOUT     CDAA23  
          2396;;                          
          2396ERROBCALL CLBUF     CD9C23  
          2399     JP BASIC       C37121  
          239C;;                          
          239CCLBUFCALL READB     CDA729  
          239F     JR Z,CLBUF     28FB    
          23A1     CALL WAIT      CDDE25  
          23A4     CALL READB     CDA729  
          23A7     RET NZ         C0      
          23a8     JR CLBUF       18F2    
          23AA;;                          
          23AATXOUTLD DE,(DFILE)  ED5B0C40
          23AE     INC DE         13      
          23AF     PUSH DE        D5      
          23B0     LD BC,$0020    012000  
          23B3     LD HL,TXX      215C23  
          23B6     LDIR           EDB0    
          23B8     POP DE         D1      
          23B9     LD HL,(ERRNR)  2A0521  
          23BC     INC HL         23      
          23BD     LD A,(HL)      7E      
          23BE     LD B,$00       0600    
          23C0     LD C,A         4F      
          23C1     INC HL         23      
          23C2     LDIR           EDB0    
          23c4     RET            C9      
          23C5;;                          
          23C5INFO1LD A,$12       3E12    
          23C7     CALL SENDB     CDE129  
          23CA     LD A,CR        3E0D    
          23CC     CALL SENDB     CDE129  
          23CFINFO2CALL READB     CDA729  
          23D2     LD A,(RSTAT)   3AF120  
          23D5     CP $01         FE01    
          23D7     JP Z,INFO2     CACF23  
          23DA     CALL WAIT      CDDE25  
          23DDINFO3CALL READB     CDA729  
          23E0     CALL READB     CDA729  
          23E3     CALL READB     CDA729  
          23E6     CALL READB     CDA729  
          23E9     CALL READB     CDA729  
          23ec     LD A,$94       3E94    
          23EE     CALL SENDB     CDE129  
          23F1     LD A,CR        3E0D    
          23F3     CALL SENDB     CDE129  
          23F6INFORCALL WAIT      CDDE25  
          23F9     CALL READB     CDA729  
          23FC     CP $55         FE55    
          23FE     JR NZ,INFOR    20F6    
          2400INFOSLD E,A         5F      
          2401     CALL TEX1      CD9528  
          2404     CALL READB     CDA729  
          2407     CP $3E         FE3E    
          2409     JR Z,INFOE     2802    
          240B     JR INFOS       18F3    
          240DINFOECALL READB     CDA729  
          2410     CALL WAIT      CDDE25  
          2413     CALL WAIT      CDDE25  
          2416     LD A,$13       3E13    
          2418     CALL SENDB     CDE129  
          241B     LD A,CR        3E0D    
          241D     CALL SENDB     CDE129  
          2420INFOVCALL WAIT      CDDE25  
          2423     CALL READB     CDA729  
          2426     CP CR          FE0D    
          2428     JR Z,INFOV     28F6    
          242AINFOWLD E,A         5F      
          242B     CALL TEX1      CD9528  
          242E     CALL READB     CDA729  
          2431     CP $3E         FE3E    
          2433     JR Z,INFOX     2802    
          2435     JR INFOW       18F3    
          2437INFOXCALL READB     CDA729  
          243a     JP BASIC       C37121  
          243D;;                          
          243DADR1 INC HL         23      
          243E     CALL GETBC     CD4624  
          2441     LD (STAL),BC   ED43F420
          2445     RET            C9      
          2446;;                          
          2446;;                          
          2446GETBCLD BC,$0000    010000  
          2449GNUM LD A,(HL)      7E      
          244A     SUB $1C        D61C    
          244C     RET C          D8      
          244D     CP $0A         FE0A    
          244F     RET NC         D0      
          2450     PUSH HL        E5      
          2451     LD H,B         60      
          2452     LD L,C         69      
          2453     ADD HL,HL      29      
          2454     ADD HL,HL      29      
          2455     ADD HL,HL      29      
          2456     ADD HL,BC      09      
          2457     ADD HL,BC      09      
          2458     LD B,$00       0600    
          245A     LD C,A         4F      
          245B     ADD HL,BC      09      
          245C     LD B,H         44      
          245D     LD C,L         4D      
          245E     POP HL         E1      
          245F     INC HL         23      
          2460     JR GNUM        18E7    
          2462;;                          
          2462DIR1 CP $3B         FE3B    
          2464     JR Z,DIMAK     282A    
          2466     CP $30         FE30    
          2468     JR Z,DIERA     282B    
          246A     LD A,(HL)      7E      
          246B     CP $0B         FE0B    
          246D     JR Z,DIRS      282B    
          246F     CP $1A         FE1A    
          2471     JP Z,DIRM      CA0E25  
          2474     CP $00         FE00    
          2476     JR Z,DICHG     2809    
          2478     LD HL,TXB      21CE22  
          247B     LD (ERRNR),HL  220521  
          247E     JP ERROR       C38323  
          2481;;                          
          2481DICHGLD A,(MBACK)   3A0421  
          2484     OR A           B7      
          2485     JR NZ,DICH1    2004    
          2487;PUSH SHOWDIR ADD ON STACK  
          2487;TO SHOW NEW DIR AFTERWARDS 
          2487     LD DE,DIRS     119A24  
          248A     PUSH DE        D5      
          248BDICH1LD C,$02       0E02    
          248D     JP DIGO        C36325  
          2490DIMAKLD C,$06       0E06    
          2492     JP DIGO        C36325  
          2495DIERALD C,$05       0E05    
          2497     JP DIGO        C36325  
          249A;;                          
          249ADIRS LD B,$13       0613    
          249C     LD A,$01       3E01    
          249E     CALL SENDB     CDE129  
          24A1     LD A,CR        3E0D    
          24a3     CALL SENDB     CDE129  
          24A6DIRR CALL READW     CD532A  
          24A9     CALL BRKCK     CD142A  
          24AC     JP Z,BRKER     CA7C23  
          24AF     LD A,(RSTAT)   3AF120  
          24B2     CP $01         FE01    
          24B4     JR Z,DIRR      28F0    
          24B6     LD A,(RBYTE)   3AF020  
          24B9     CP $3E         FE3E    
          24BB     JR Z,DIRE      280B    
          24BD     CP CR          FE0D    
          24BF     JR Z,DIRC      280D    
          24C1DIRP LD E,A         5F      
          24C2     CALL TEX1      CD9528  
          24C5     JP DIRR        C3A624  
          24C8DIRE CALL CLBUF     CD9C23  
          24cb     JP BASIC       C37121  
          24CEDIRC DEC B          05      
          24CF     JR NZ,DIRP     20F0    
          24D1     LD E,CR        1E0D    
          24D3     CALL TEX1      CD9528  
          24D6     LD E,CR        1E0D    
          24D8     CALL TEX1      CD9528  
          24DB     LD E,$3C       1E3C    
          24DD     CALL TEX1      CD9528  
          24E0     LD E,$43       1E43    
          24E2     CALL TEX1      CD9528  
          24E5     LD E,$52       1E52    
          24E7     CALL TEX1      CD9528  
          24EA     LD E,$3E       1E3E    
          24EC     CALL TEX1      CD9528  
          24EF     CALL SLOW      CD0702  
          24f2DIRW CALL BRKCK     CD142A  
          24F5     JP Z,BRKER     CA7C23  
          24F8     CALL GTKEY     CDBB02  
          24FB     EX DE,HL       EB      
          24FC     LD HL,$FDBF    21BFFD  
          24FF     AND A          A7      
          2500     SBC HL,DE      ED52    
          2502     JR NZ,DIRW     20EE    
          2504     CALL RCLS      CD2A0A  
          2507     LD B,$13       0613    
          2509     LD A,(RBYTE)   3AF020  
          250C     JR DIRP        18B3    
          250E;;                          
          250EDIRM CALL ADR1      CD3D24  
          2511     LD A,(TXC)     3AE622  
          2514     LD (ERRNO),A   323240  
          2517     LD BC,$0000    010000  
          251A     LD A,$01       3E01    
          251C     CALL SENDB     CDE129  
          251F     LD A,CR        3E0D    
          2521     CALL SENDB     CDE129  
          2524CIRR CALL READW     CD532A  
          2527     CALL BRKCK     CD142A  
          252A     JP Z,BRKER     CA7C23  
          252D     LD A,(RSTAT)   3AF120  
          2530     CP $01         FE01    
          2532     JR Z,CIRR      28F0    
          2534     LD A,(RBYTE)   3AF020  
          2537     CP $3E         FE3E    
          2539     JR Z,CIRE      281F    
          253B     CP CR          FE0D    
          253D     JR Z,CIRC      2821    
          253fCIRP LD E,A         5F      
          2540     LD A,(STAL)    3AF420  
          2543     CP C           B9      
          2544     JR NZ,CIRR     20DE    
          2546     LD A,(STAH)    3AF520  
          2549     CP B           B8      
          254A     JR NZ,CIRR     20D8    
          254C     LD A,E         7B      
          254D     CP CR          FE0D    
          254F     JR Z,CIRR      28D3    
          2551     CALL TEX1      CD9528  
          2554     XOR A          AF      
          2555     LD (ERRNO),A   323240  
          2558     JR CIRR        18CA    
          255ACIRE CALL CLBUF     CD9C23  
          255D     JP BASIC       C37121  
          2560CIRC INC BC         03      
          2561     JR CIRP        18DC    
          2563;;                          
          2563DIGO PUSH BC        C5      
          2564     INC HL         23      
          2565     LD DE,FILNA    111820  
          2568DIGO2LD A,(HL)      7E      
          2569     CP $0B         FE0B    
          256B     JR Z,DIGO3     2808    
          256D     CALL ZXASC     CD4529  
          2570     LD (DE),A      12      
          2571     INC HL         23      
          2572     INC DE         13      
          2573     JR DIGO2       18F3    
          2575DIGO3LD A,CR        3E0D    
          2577     LD (DE),A      12      
          2578     POP BC         C1      
          2579     LD A,C         79      
          257A     CALL SENDB     CDE129  
          257D     LD A,$20       3E20    
          257F     CALL SENDB     CDE129  
          2582     LD HL,FILNA    211820  
          2585DIGO4LD A,(HL)      7E      
          2586     PUSH AF        F5      
          2587     CALL SENDB     CDE129  
          258A     INC HL         23      
          258B     POP AF         F1      
          258C     CP CR          FE0D    
          258E     JR NZ,DIGO4    20F5    
          2590DIGO5CALL READW     CD532A  
          2593     CALL BRKCK     CD142A  
          2596     JP Z,BRKER     CA7C23  
          2599     LD A,(RSTAT)   3AF120  
          259C     CP $01         FE01    
          259E     JR Z,DIGO5     28F0    
          25A0     LD A,(RBYTE)   3AF020  
          25A3     CP $3E         FE3E    
          25A5     JR Z,DIGOK     282C    
          25A7     CP $43         FE43    
          25A9     JR NZ,NDIG1    2005    
          25AB     LD DE,TXC      11E622  
          25AE     JR NDIG        1819    
          25B0NDIG1CP $44         FE44    
          25B2     JR NZ,NDIG2    2005    
          25B4     LD DE,TXD      11FF22  
          25B7     JR NDIG        1810    
          25B9NDIG2CP $46         FE46    
          25BB     JR NZ,NDIG3    2005    
          25bd     LD DE,TXE      110C23  
          25C0     JR NDIG        1807    
          25C2NDIG3CP $4E         FE4E    
          25C4     JR NZ,DIGO5    20CA    
          25C6     LD DE,TXI      114C23  
          25C9NDIG LD (ERRNR),DE  ED530521
          25CD     CALL CLBUF     CD9C23  
          25D0     JP ERROR       C38323  
          25D3DIGOKCALL READB     CDA729  
          25D6     JP BASIC       C37121  
          25D9;;                          
          25D9REN1 LD C,$0C       0E0C    
          25DB     JP REERA       C32028  
          25DE;;                          
          25DEWAIT PUSH BC        C5      
          25DF     PUSH AF        F5      
          25e0     LD B,$FF       06FF    
          25E2     XOR A          AF      
          25E3WAIT1DEC B          05      
          25E4     CP B           B8      
          25E5     JP NZ,WAIT1    C2E325  
          25E8     POP AF         F1      
          25E9     POP BC         C1      
          25EA     RET            C9      
          25EB;;                          
          25EBSAVE1PUSH HL        E5      
          25EC     LD HL,(ELINE)  2A1440  
          25EF     LD BC,$4009    010940  
          25F2     LD (STAL),BC   ED43F420
          25F6     AND A          A7      
          25F7     SBC HL,BC      ED42    
          25F9     LD (SIZEL),HL  22F620  
          25fc     POP HL         E1      
          25FD     LD DE,FILNA    111820  
          2600     INC HL         23      
          2601SAVE3LD A,(HL)      7E      
          2602     CP $0B         FE0B    
          2604     JR Z,SAVE2     281B    
          2606     CP $1A         FE1A    
          2608     JR Z,SAVEM     280C    
          260A     CP $00         FE00    
          260C     JR Z,SAVEM     2808    
          260E     CALL ZXASC     CD4529  
          2611     LD (DE),A      12      
          2612     INC HL         23      
          2613     INC DE         13      
          2614     JR SAVE3       18EB    
          2616SAVEMCALL ADR1      CD3D24  
          2619     INC HL         23      
          261A     CALL GETBC     CD4624  
          261D     LD (SIZEL),BC  ED43F620
          2621SAVE2LD A,CR        3E0D    
          2623     LD (DE),A      12      
          2624     CALL WAIT      CDDE25  
          2627     LD A,$09       3E09    
          2629     CALL SENDB     CDE129  
          262C     LD A,$20       3E20    
          262E     CALL SENDB     CDE129  
          2631     LD HL,FILNA    211820  
          2634SAVE4LD A,(HL)      7E      
          2635     PUSH AF        F5      
          2636     CALL SENDB     CDE129  
          2639     INC HL         23      
          263A     POP AF         F1      
          263b     CP CR          FE0D    
          263D     JR NZ,SAVE4    20F5    
          263FSAVEWCALL BRKCK     CD142A  
          2642     JP Z,BRKER     CA7C23  
          2645     CALL READW     CD532A  
          2648     CP $3E         FE3E    
          264A     JR NZ,SAVEW    20F3    
          264C     CALL READB     CDA729  
          264F;;                          
          264F     LD A,$28       3E28    
          2651     CALL SENDB     CDE129  
          2654     LD A,$20       3E20    
          2656     CALL SENDB     CDE129  
          2659     XOR A          AF      
          265A     CALL SENDB     CDE129  
          265D     XOR A          AF      
          265e     CALL SENDB     CDE129  
          2661     XOR A          AF      
          2662     CALL SENDB     CDE129  
          2665     XOR A          AF      
          2666     CALL SENDB     CDE129  
          2669     LD A,CR        3E0D    
          266B     CALL SENDB     CDE129  
          266E     CALL READW     CD532A  
          2671     CALL READB     CDA729  
          2674;;                          
          2674     LD A,$08       3E08    
          2676     CALL SENDB     CDE129  
          2679     LD A,$20       3E20    
          267B     CALL SENDB     CDE129  
          267E     XOR A          AF      
          267F     CALL SENDB     CDE129  
          2682     XOR A          AF      
          2683     CALL SENDB     CDE129  
          2686     LD A,(SIZEH)   3AF720  
          2689     CALL SENDB     CDE129  
          268C     LD A,(SIZEL)   3AF620  
          268F     CALL SENDB     CDE129  
          2692     LD A,CR        3E0D    
          2694     CALL SENDB     CDE129  
          2697     LD HL,(STAL)   2AF420  
          269A     LD BC,(SIZEL)  ED4BF620
          269ESAVE5CALL BRKCK     CD142A  
          26A1     JP Z,BRKER     CA7C23  
          26A4     LD A,(HL)      7E      
          26A5     CALL SENDB     CDE129  
          26A8     CP $08         FE08    
          26AA     JR Z,SAVE5     28F2    
          26ac     INC HL         23      
          26AD     DEC BC         0B      
          26AE     XOR A          AF      
          26AF     CP B           B8      
          26B0     JR NZ,SAVE5    20EC    
          26B2     CP C           B9      
          26B3     JR NZ,SAVE5    20E9    
          26B5SAVE6CALL BRKCK     CD142A  
          26B8     JP Z,BRKER     CA7C23  
          26BB     CALL READB     CDA729  
          26BE     CP $3E         FE3E    
          26C0     JR NZ,SAVE6    20F3    
          26C2     CALL READB     CDA729  
          26C5     LD A,$0A       3E0A    
          26C7     CALL SENDB     CDE129  
          26CA     LD A,$20       3E20    
          26cc     CALL SENDB     CDE129  
          26CF     LD HL,FILNA    211820  
          26D2SAVE7LD A,(HL)      7E      
          26D3     PUSH AF        F5      
          26D4     CALL SENDB     CDE129  
          26D7     INC HL         23      
          26D8     POP AF         F1      
          26D9     CP CR          FE0D    
          26DB     JR NZ,SAVE7    20F5    
          26DDSAVE8CALL BRKCK     CD142A  
          26E0     JP Z,BRKER     CA7C23  
          26E3     CALL READW     CD532A  
          26E6     CP $3E         FE3E    
          26E8     JR NZ,SAVE8    20F3    
          26EA     CALL READB     CDA729  
          26ED     JP BASIC       C37121  
          26f0;;                          
          26F0LOAD1LD A,$40       3E40    
          26F2     LD (STAH),A    32F520  
          26F5     LD A,$09       3E09    
          26F7     LD (STAL),A    32F420  
          26FA     LD DE,FILNA    111820  
          26FD     INC HL         23      
          26FELOAD3LD A,(HL)      7E      
          26FF     CP $0B         FE0B    
          2701     JR Z,LOAD2     2813    
          2703     CP $1A         FE1A    
          2705     JR Z,LOADM     280C    
          2707     CP $00         FE00    
          2709     JR Z,LOADM     2808    
          270B     CALL ZXASC     CD4529  
          270E     LD (DE),A      12      
          270f     INC HL         23      
          2710     INC DE         13      
          2711     JR LOAD3       18EB    
          2713LOADMCALL ADR1      CD3D24  
          2716LOAD2LD A,CR        3E0D    
          2718     LD (DE),A      12      
          2719     CALL WAIT      CDDE25  
          271C     CALL READB     CDA729  
          271F     CALL READB     CDA729  
          2722     CALL READB     CDA729  
          2725     LD A,$01       3E01    
          2727     CALL SENDB     CDE129  
          272A     LD A,$20       3E20    
          272C     CALL SENDB     CDE129  
          272F     LD HL,FILNA    211820  
          2732LOAD4LD A,(HL)      7E      
          2733     PUSH AF        F5      
          2734     CALL SENDB     CDE129  
          2737     INC HL         23      
          2738     POP AF         F1      
          2739     CP CR          FE0D    
          273B     JR NZ,LOAD4    20F5    
          273DLOADNCALL READB     CDA729  
          2740     CALL BRKCK     CD142A  
          2743     JP Z,BRKER     CA7C23  
          2746     LD A,(RSTAT)   3AF120  
          2749     CP $01         FE01    
          274B     JR Z,LOADN     28F0    
          274DLODN1CALL READB     CDA729  
          2750     CALL BRKCK     CD142A  
          2753     JP Z,BRKER     CA7C23  
          2756     LD A,(RSTAT)   3AF120  
          2759     CP $01         FE01    
          275B     JR Z,LODN1     28F0    
          275DLOAD5CALL READB     CDA729  
          2760     CALL BRKCK     CD142A  
          2763     JP Z,BRKER     CA7C23  
          2766     LD A,(RSTAT)   3AF120  
          2769     CP $01         FE01    
          276B     JR Z,LOAD5     28F0    
          276D     LD A,(RBYTE)   3AF020  
          2770     CP CR          FE0D    
          2772     JR NZ,NLOAD    200A    
          2774     LD DE,TXF      112123  
          2777     LD (ERRNR),DE  ED530521
          277B     JP ERROR       C38323  
          277ENLOADCP $20         FE20    
          2780     JR NZ,LOAD5    20DB    
          2782     CALL READB     CDA729  
          2785     LD (SIZEL),A   32F620  
          2788     LD (COORL),A   323640  
          278B     CALL READB     CDA729  
          278E     LD (SIZEH),A   32F720  
          2791     LD (COORH),A   323740  
          2794     CALL READB     CDA729  
          2797     LD (XPTRL),A   321840  
          279A     CALL READB     CDA729  
          279D     LD (XPTRH),A   321940  
          27A0     CALL READB     CDA729  
          27A3     CALL READB     CDA729  
          27A6LOADXCALL BRKCK     CD142A  
          27A9     JP Z,BRKER     CA7C23  
          27AC     CALL READB     CDA729  
          27AF     JR NZ,LOADX    20F5    
          27b1;CHECK FOR ADDRESS 0        
          27B1     LD BC,(STAL)   ED4BF420
          27B5     LD A,B         78      
          27B6     OR C           B1      
          27B7     JR NZ,COMRD    2004    
          27B9;COMMAND "OPR"              
          27B9     LD A,$0E       3E0E    
          27BB     JR COMOR       1802    
          27BD;COMMAND "RD"               
          27BDCOMRDLD A,$04       3E04    
          27BFCOMORCALL SENDB     CDE129  
          27C2     LD A,$20       3E20    
          27C4     CALL SENDB     CDE129  
          27C7     LD HL,FILNA    211820  
          27CALOAD6LD A,(HL)      7E      
          27CB     PUSH AF        F5      
          27cc     CALL SENDB     CDE129  
          27CF     INC HL         23      
          27D0     POP AF         F1      
          27D1     CP CR          FE0D    
          27D3     JR NZ,LOAD6    20F5    
          27D5;STREAMING IF ADDR=0        
          27D5     LD BC,(STAL)   ED4BF420
          27D9     LD A,B         78      
          27DA     OR C           B1      
          27DB     JP Z,BASIC     CA7121  
          27DE; NORMAL LOAD               
          27DELOADYCALL READW     CD532A  
          27E1     CALL BRKCK     CD142A  
          27E4     JP Z,BRKER     CA7C23  
          27E7     LD A,(RSTAT)   3AF120  
          27EA     CP $01         FE01    
          27ec     JR Z,LOADY     28F0    
          27EE     LD A,(RBYTE)   3AF020  
          27F1     LD HL,(STAL)   2AF420  
          27F4     LD BC,(SIZEL)  ED4BF620
          27F8LOAD7LD (HL),A      77      
          27F9     INC HL         23      
          27FA     DEC BC         0B      
          27FB     XOR A          AF      
          27FC     CP B           B8      
          27FD     JR NZ,LOAD8    200A    
          27FF     CP C           B9      
          2800     JR NZ,LOAD8    2007    
          2802;REWRITE ERROR CODE         
          2802     XOR A          AF      
          2803     LD (ERRNO),A   323240  
          2806     JP BASIC       C37121  
          2809LOAD8CALL READB     CDA729  
          280C     CALL BRKCK     CD142A  
          280F     JP Z,BRKER     CA7C23  
          2812     LD A,(RSTAT)   3AF120  
          2815     CP $01         FE01    
          2817     JR Z,LOAD8     28F0    
          2819     LD A,(RBYTE)   3AF020  
          281C     JR LOAD7       18DA    
          281E;;                          
          281EERAS1LD C,$07       0E07    
          2820REERALD DE,FILNA    111820  
          2823     INC HL         23      
          2824ERAS2LD A,(HL)      7E      
          2825     CP $0B         FE0B    
          2827     JR Z,ERAS3     2808    
          2829     CALL ZXASC     CD4529  
          282c     LD (DE),A      12      
          282D     INC HL         23      
          282E     INC DE         13      
          282F     JR ERAS2       18F3    
          2831ERAS3LD A,CR        3E0D    
          2833     LD (DE),A      12      
          2834     PUSH BC        C5      
          2835     CALL WAIT      CDDE25  
          2838     POP BC         C1      
          2839     LD A,C         79      
          283A     CALL SENDB     CDE129  
          283D     LD A,$20       3E20    
          283F     CALL SENDB     CDE129  
          2842     LD HL,FILNA    211820  
          2845ERAS4LD A,(HL)      7E      
          2846     PUSH AF        F5      
          2847     CALL SENDB     CDE129  
          284A     INC HL         23      
          284B     POP AF         F1      
          284C     CP CR          FE0D    
          284E     JR NZ,ERAS4    20F5    
          2850ERAS5CALL READW     CD532A  
          2853     CALL BRKCK     CD142A  
          2856     JP Z,BRKER     CA7C23  
          2859     LD A,(RSTAT)   3AF120  
          285C     CP $01         FE01    
          285E     JR Z,ERAS5     28F0    
          2860     LD A,(RBYTE)   3AF020  
          2863     CP $3E         FE3E    
          2865     JR Z,EROK      2823    
          2867     CP $43         FE43    
          2869     JR NZ,NER1     2005    
          286b     LD DE,TXC      11E622  
          286E     JR ERERR       1810    
          2870NER1 CP $44         FE44    
          2872     JR NZ,NER2     2005    
          2874     LD DE,TXD      11FF22  
          2877     JR ERERR       1807    
          2879NER2 CP $46         FE46    
          287B     JR NZ,ERAS5    20D3    
          287D     LD DE,TXE      110C23  
          2880ERERRLD (ERRNR),DE  ED530521
          2884     CALL CLBUF     CD9C23  
          2887     JP ERROR       C38323  
          288A;;                          
          288AEROK CALL READB     CDA729  
          288D     JP BASIC       C37121  
          2890;;                          
          2890TEX  BIT 7,(IY+$08) FDCB087E
          2894     RET Z          C8      
          2895;;                          
          2895TEX1 LD A,($403A)   3A3A40  
          2898     CP $03         FE03    
          289A     RET C          D8      
          289B;;                          
          289B     LD A,E         7B      
          289C     PUSH BC        C5      
          289D     PUSH HL        E5      
          289E     RES 7,A        CBBF    
          28A0     LD C,A         4F      
          28A1     AND $60        E660    
          28A3ASCZXJR Z,CTCHR     2811    
          28A5     BIT 6,C        CB71    
          28A7     JR Z,CDCON     2802    
          28a9     RES 5,C        CBA9    
          28ABCDCONXOR A          AF      
          28AC     LD B,A         47      
          28AD     LD HL,ASCZX    21A328  
          28B0     ADD HL,BC      09      
          28B1     LD A,(HL)      7E      
          28B2     RST 10         D7      
          28B3     POP HL         E1      
          28B4     POP BC         C1      
          28B5     RET            C9      
          28B6CTCHRLD A,C         79      
          28B7     CP CR          FE0D    
          28B9     JR NZ,NOCR     2003    
          28BB     LD A,$76       3E76    
          28BD     RST 10         D7      
          28BENOCR POP HL         E1      
          28bf     POP BC         C1      
          28C0     RET            C9      
          28C1     NOP            00      
          28C2     NOP            00      
          28C3     001B0B0C0D18150B       
          28CB     101117151A161B18       
          28D3     1C1D1E1F20212223       
          28DB     24250E191314120F       
          28E3     A6262728292A2B2C       
          28EB     2D2E2F3031323334       
          28F3     35363738393A3B3C       
          28FB     3D3E3F1018110E16       
          2903     NOP            00      
          2904     NOP            00      
          2905;;                          
          2905ASCII2020202020202020202020 
          2910     2223247E3F28293E3C3D   
          291A     2B2D2A5C3B2C2E         
          2921     30313233343536373839   
          292B     4142434445464748494A4B 
          2936     4C4D4E4F50515253545556 
          2941     5758595A               
          2945;;                          
          2945ZXASCPUSH BC        C5      
          2946     PUSH HL        E5      
          2947     LD HL,ASCII    210529  
          294A     LD B,$00       0600    
          294C     AND $3F        E63F    
          294E     LD C,A         4F      
          294F     ADD HL,BC      09      
          2950     LD A,(HL)      7E      
          2951     POP HL         E1      
          2952     POP BC         C1      
          2953     RET            C9      
          2954;;                          
          2954INIT CALL FAST      CDE702  
          2957     CALL CLBUF     CD9C23  
          295A     LD A,CR        3E0D    
          295C     CALL SENDB     CDE129  
          295F     LD A,$53       3E53    
          2961     CALL SENDB     CDE129  
          2964     LD A,$43       3E43    
          2966     CALL SENDB     CDE129  
          2969     LD A,$53       3E53    
          296B     CALL SENDB     CDE129  
          296E     LD A,CR        3E0D    
          2970     CALL SENDB     CDE129  
          2973     CALL WAIT      CDDE25  
          2976INITWCALL WAIT      CDDE25  
          2979     CALL BRKCK     CD142A  
          297C     JR Z,INIBR     2825    
          297E     CALL READB     CDA729  
          2981     CP $3E         FE3E    
          2983     JR NZ,INITW    20F1    
          2985     CALL CLBUF     CD9C23  
          2988     LD A,CR        3E0D    
          298A     CALL SENDB     CDE129  
          298D     CALL READW     CD532A  
          2990     CP $3E         FE3E    
          2992     JR NZ,INIER    2004    
          2994     CALL CLBUF     CD9C23  
          2997     RET            C9      
          2998;;                          
          2998INIERLD DE,TXG      112D23  
          299b     LD (ERRNR),DE  ED530521
          299F;    DROP RETURN ADDRESS    
          299F     POP AF         F1      
          29A0     JP ERROR       C38323  
          29A3;;                          
          29A3;;BREAK: DROP RETUR ADDRESS 
          29A3INIBRPOP AF         F1      
          29A4     JP BRKER       C37C23  
          29A7;;                          
          29A7;;                          
          29A7READBEXX            D9      
          29A8     LD C,PORT      0E5F    
          29AA     LD B,IPOFF     064C    
          29AC     IN D,(C)       ED50    
          29AE     LD B,IPS1      064F    
          29B0     IN D,(C)       ED50    
          29b2     IN D,(C)       ED50    
          29B4     LD B,IPS0      064E    
          29B6     IN D,(C)       ED50    
          29B8     LD E,$08       1E08    
          29BA;BIT 0..7                   
          29BARDBLPIN D,(C)       ED50    
          29BC     RL D           CB12    
          29BE     RLA            17      
          29BF     DEC E          1D      
          29C0     JR NZ,RDBLP    20F8    
          29C2;;                          
          29C2;8 BITS COLLECTED   20F3    
          29C2     LD (RBYTE),A   32F020  
          29C5     LD E,A         5F      
          29C6     XOR A          AF      
          29C7     LD B,IPS0      064E    
          29c9     IN D,(C)       ED50    
          29CB     RL D           CB12    
          29CD     RLA            17      
          29CE     LD B,IPOFF     064C    
          29D0     IN B,(C)       ED40    
          29D2     OR A           B7      
          29D3     LD A,$00       3E00    
          29D5     JR Z,REB2      2801    
          29D7     INC A          3C      
          29D8REB2 LD (RSTAT),A   32F120  
          29DB     LD A,E         7B      
          29DC     LD (RBYTE),A   32F020  
          29DF     EXX            D9      
          29E0     RET            C9      
          29E1;;                          
          29E1;;                          
          29e1SENDBEXX            D9      
          29E2     LD C,PORT      0E5F    
          29E4     LD B,IPOFF     064C    
          29E6     IN B,(C)       ED40    
          29E8     LD B,IPS1      064F    
          29EA     IN B,(C)       ED40    
          29EC     LD B,IPS0      064E    
          29EE     IN B,(C)       ED40    
          29F0     LD B,IPS0      064E    
          29F2     IN B,(C)       ED40    
          29F4     LD E,$08       1E08    
          29F6     LD D,IPS0      164E    
          29F8WRBLPLD B,D         42      
          29F9     ADD A,A        87      
          29FA     JR NC,WRBEN    3001    
          29FC     INC B          04      
          29fdWRBENIN B,(C)       ED40    
          29FF     DEC E          1D      
          2A00     JR NZ,WRBLP    20F6    
          2A02     XOR A          AF      
          2A03     LD B,IPS0      064E    
          2A05     IN B,(C)       ED40    
          2A07     JP P,WROK      F20C2A  
          2A0A     LD A,$08       3E08    
          2A0CWROK LD B,IPOFF     064C    
          2A0E     IN B,(C)       ED40    
          2A10     BIT 3,A        CB5F    
          2A12     EXX            D9      
          2A13     RET            C9      
          2A14;;                          
          2A14BRKCKLD A,$FD       3EFD    
          2A16     IN A,$FE       DBFE    
          2a18     BIT 0,A        CB47    
          2A1A     RET Z          C8      
          2A1B     LD A,$EF       3EEF    
          2A1D     IN A,$FE       DBFE    
          2A1F     BIT 4,A        CB67    
          2A21     RET            C9      
          2A22;;                          
          2A22READMJR NC,READ1    3022    
          2A24;CLEAR BUFFER FIRST         
          2A24     CALL CLBUF     CD9C23  
          2A27;REQEST (BC) BYTES)         
          2A27;COMMAND "RDF"              
          2A27     LD A,$0B       3E0B    
          2A29     CALL SENDB     CDE129  
          2A2C     LD A,$20       3E20    
          2A2E     CALL SENDB     CDE129  
          2a31;SEND BYTE COUNT (MSB..LSB) 
          2A31     XOR A          AF      
          2A32     CALL SENDB     CDE129  
          2A35     CALL SENDB     CDE129  
          2A38     LD A,B         78      
          2A39     CALL SENDB     CDE129  
          2A3C     LD A,C         79      
          2A3D     CALL SENDB     CDE129  
          2A40     LD A,CR        3E0D    
          2A42     CALL SENDB     CDE129  
          2A45     RET            C9      
          2A46;;                          
          2A46;READ ONE BYTE              
          2A46READ1CALL READW     CD532A  
          2A49     LD A,(RBYTE)   3AF020  
          2A4C     RET Z          C8      
          2a4d     PUSH AF        F5      
          2A4E     CALL CLBUF     CD9C23  
          2A51     POP AF         F1      
          2A52     RET            C9      
          2A53;;                          
          2A53READWCALL READB     CDA729  
          2A56     RET Z          C8      
          2A57     CALL BRKCK     CD142A  
          2A5A     JR NZ,READW    20F7    
          2A5C     LD A,$29       3E29    
          2A5E;RESET Z FLAG TO INDICATE   
          2A5E;BREAK                      
          2A5E     INC A          3C      
          2A5F     RET            C9      
          2A60;---------------------------
Und vor Start die Initialisierung der seriellen Schnittstelle auf 31250 Baud (4 MHz-Quarz) nicht vergessen, sonst hängt der Player!

Hier noch 2 Liedchen für erste Test (mit USB-Treiber oder UFM auf Adresse 0 "laden" und dann Player starten. Oder Namen im Player direkt eingeben, wenn Musik im aktuellen Verzeichnis des Sticks liegt).
Songs.zip
(35.36 KiB) 22-mal heruntergeladen
Morgen dann mehr.

Vui Schbass
Siggi
Zuletzt geändert von siggi am 14.03.2018, 09:09, insgesamt 1-mal geändert.
Mein ZX81-Web-Server: online seit 2007
http://zx81-siggi.endoftheinternet.org/index.html

Benutzeravatar
siggi
User
Beiträge: 2319
Registriert: 06.12.2005, 08:34
Wohnort: D, Hessen, tiefste Werreraa
Kontaktdaten:

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von siggi » 14.03.2018, 08:53

Hier noch was zum Aufruf des USB-Treibers, wenn man eine Datei häppchenweise lesen will.
Voraussetzung ist, daß die Datei schon zum Lesen ("OPR" -> USB-Kommando "L dingens.bin 0") schon geöffnet ist.

Man muß dann dem Treiber erstmal mitteilen, wie viele Bytes man lesen will.
Dazu lädt man die gewünschte Anzahl ins BC Register und setzt das Carry-Flag! Dies zeigt dem Treiber an, daß nun ein "RDF"-Kommando zum VDRIVE2 geschickt werden muß. Nun springt man in den Treiber (via die Sprungtabelle am Anfang des Treibers) zur Routine "READM". Da im BC-Register 16 Bit unterzubringen sind, können also maximal 64kByte angefordert werden (die Datei kann aber größer sein: Länge 32 Bit!).

Anschließend kann man dann die Bytes (jedes einzeln) abholen. Man ruft dazu wieder die READM-Routine auf, diesmal mit gelöschtem Carry-Flag! Dann weiß der Treiber, daß er ein Byte vom VDRIVE2 lesen soll.
Das gelesene Byte kommt im A-Register zurück. Das ZERO-Flag ist gelöscht, wenn alles geklappt hat. Es ist gesetzt, wenn im Treiber BREAK (Taste "A" oder "6") gedrückt wurde (wenn das der Fall ist, ruft der Treiber gleich noch die CLBUF-Routine auf und liest den Puffer des VDRIVE2 leer, damit er wieder im Kommandomodus ist).

Bitte beachten: der VDRIVE2 erkennt/meldet kein Dateiende! Wenn man das Dateiende nicht am Datenstrom erkennen kann (der MIDI-Player erkennt das an der Frame-Nummer $FFFFFF), dann muß man die gelesenen Bytes mitzählen. Die Länge der Datei wird ja beim Öffnen in die Systemvariablen COORDS (Low 16 Bit, wie auch bei älteren Treibern) und XPTR (High 16 Bit) abgelegt. Man muß also bei großen Dateien 32-bittig mitzählen (das habe ich mir im Treiber selbst erspart wegen Performance)!

Wenn man über das Dateiende hinaus liest, sendet der VDRIVE2 Füllbytes, bis die angeforderte Anzahl Bytes gelesen wurde. Erst dann geht er wieder in den Kommandomodus über.

Hier der entsprechende Code-Abschnitt im Treiber:

Code: Alles auswählen

          2A22READMJR NC,READ1    3022    
          2A24;CLEAR BUFFER FIRST         
          2A24     CALL CLBUF     CD9C23  
          2A27;REQEST (BC) BYTES)         
          2A27;COMMAND "RDF"              
          2A27     LD A,$0B       3E0B    
          2A29     CALL SENDB     CDE129  
          2A2C     LD A,$20       3E20    
          2A2E     CALL SENDB     CDE129  
          2a31;SEND BYTE COUNT (MSB..LSB) 
          2A31     XOR A          AF      
          2A32     CALL SENDB     CDE129  
          2A35     CALL SENDB     CDE129  
          2A38     LD A,B         78      
          2A39     CALL SENDB     CDE129  
          2A3C     LD A,C         79      
          2A3D     CALL SENDB     CDE129  
          2A40     LD A,CR        3E0D    
          2A42     CALL SENDB     CDE129  
          2A45     RET            C9      
          2A46;;                          
          2A46;READ ONE BYTE              
          2A46READ1CALL READW     CD532A  
          2A49     LD A,(RBYTE)   3AF020  
          2A4C     RET Z          C8      
          2a4d     PUSH AF        F5      
          2A4E     CALL CLBUF     CD9C23  
          2A51     POP AF         F1      
          2A52     RET            C9      
          2A53;;                    
          
 
Zuletzt geändert von siggi am 14.03.2018, 12:30, insgesamt 1-mal geändert.
Mein ZX81-Web-Server: online seit 2007
http://zx81-siggi.endoftheinternet.org/index.html

Benutzeravatar
siggi
User
Beiträge: 2319
Registriert: 06.12.2005, 08:34
Wohnort: D, Hessen, tiefste Werreraa
Kontaktdaten:

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von siggi » 14.03.2018, 09:20

Upps, ich hatte in den Kommentaren im Midiplayer falsche POKE-Adressen der Einsprünge angegeben, deshalb hier die korrigierte Version incl. Listing.
Beachte: Zeile 1 und 3 enthalten M/C (NOVA2005, Playercode) und werden deshalb hier nicht gelistet:

Code: Alles auswählen

             5>REM 320 BYTE FUERPLAYER AB 17045
            10 REM -------------------
            11 REM READ USB BYTE: cy CLEAR
            12 REM ->z: BYTE IN A; nz: BREAK
            13 REM REQUEST (BC) BYTES: cy  SET
            14 REM DEFAULT: $200C
            15 REM POKE 17050/51:USB-READM
            16 REM -------------------
            17 REM SEND MIDI BYTE IN A
            18 REM POKE 17053/54:UART-OUT
            19 REM -------------------
            20 REM POKE NOVA FOR 50 HZ VIDEO
            30 POKE 16606,180
            34 REM 60 HZ, DISPLAY OK
            35 REM POKE 16606,236
            50 CLS 
            51 REM ENABLE RAM AT 8K (UFM)
            52 POKE 0,4
            55 PRINT "uFM, sTART, eND, filename"
            60 INPUT J$
            62 POKE 16444,11
            65 IF J$="E" THEN STOP 
            70 IF J$="U" THEN RAND USR 8192
            75 IF J$="S" THEN GOTO 100
            85 IF J$="" OR J$="U" THEN GOTO 50
            91 LET L$="L "+J$+" 0"+CHR$ 11
            92 PRINT USR 8195;L$
            93 IF PEEK 16434<>0 THEN GOTO 50
            99 REM CONFIGURE AND START NOVA
           100 RAND USR 16535
           110 POKE 32625,0
           120 POKE 32626,1
           130 RAND USR 32668
           140 CLS 
           150 PRINT "  rs232-midiplayer V0.4 F=000000",,
           199 REM START PLAYER
           200 LET ERR=USR 17046
           209 REM STOP NOVA
           210 PAUSE 1
           220 IF ERR>1 THEN PRINT "ERROR=";ERR
           230 IF ERR=1 THEN PRINT "BREAK OR USB READ ERROR"
           240 IF ERR=0 THEN PRINT "FEDDISCH ;-)"
           250 PAUSE 500
           300 GOTO 50
          7000 RAND LEN A$
          7010 POKE 32768,PEEK 16434
          7020 POKE 32769,PEEK 16435
          7050 FOR F=1 TO LEN A$
          7060 POKE 32769+F,CODE A$(F)
          7070 NEXT F
          7080 CLEAR 
          7090 LET A$=""
          7100 FOR F=1 TO PEEK 32768+256*PEEK 32769
          7110 LET A$=A$+CHR$ PEEK F
          7120 NEXT F
          7200 SAVE "D:TMP/VAR-A$ -V"
          8000 STOP 
          9000 SAVE "D:TMP/MIDIPL16 -J"
Und hier das Listing der Machinencodes in Zeile 3 (bzw. in A$ für ASDIS)

Code: Alles auswählen

          4296;JUMP TABLE                 
          4296     JP MAIN        C39F42  
          4299;;                          
          4299;TO EXTERNAL VDRIVE ROUTINE 
          4299VDRIVJP $200C       C30C20  
          429C;;                          
          429C;TO INTERNAL SEND ROUTINE   
          429CPUTB JP SENDB       C35943  
          429f;;                          
          429F;CLEAR FRAME NUMBER         
          429FMAIN LD HL,FRAMN    219043  
          42A2     LD A,$FF       3EFF    
          42A4     LD (HL),A      77      
          42A5     INC HL         23      
          42A6     LD (HL),A      77      
          42A7     INC HL         23      
          42A8     LD (HL),A      77      
          42A9     CALL VIDWT     CD3043  
          42AC;REQUEST FIRST 5 BYTES      
          42AC     LD BC,$0005    010500  
          42AF     CALL SETSZ     CD8C43  
          42B2;;                          
          42B2;READ NEXT FRAME            
          42B2RNFRACALL GETB      CD8843  
          42b5     JP NZ,ABORT    C26643  
          42B8     LD (FRAMC),A   329343  
          42BB;GET HIGHER BYTES           
          42BB     CALL GETB      CD8843  
          42BE     JP NZ,ABORT    C26643  
          42C1     LD E,A         5F      
          42C2     CALL GETB      CD8843  
          42C5     JP NZ,ABORT    C26643  
          42C8     LD D,A         57      
          42C9     LD (FRAC1),DE  ED539443
          42CD;CHECK FOR END MARK $FFFFFF 
          42CD     LD A,(FRAMC)   3A9343  
          42D0     AND D          A2      
          42D1     AND E          A3      
          42D2     INC A          3C      
          42D3     JR NZ,WNFRA    200A    
          42d5;END MARK $FFFFFF FOUND     
          42D5;READ 2 REMAINING BYTES     
          42D5     CALL GETB      CD8843  
          42D8     CALL GETB      CD8843  
          42DB;SET ERROR CODE "OK"        
          42DB     LD BC,$0000    010000  
          42DE     RET            C9      
          42DF;;                          
          42DF;PROCESS READ FRAME         
          42DFWNFRACALL UPDCT     CD4243  
          42E2     CALL VIDWT     CD3043  
          42E5;;                          
          42E5;CHECK ITS TIME TO PLAY     
          42E5;INC FRAME NUMBER           
          42E5     LD HL,(FRAMN)  2A9043  
          42E8     INC HL         23      
          42e9     LD (FRAMN),HL  229043  
          42EC     LD A,H         7C      
          42ED     OR L           B5      
          42EE     JR NZ,FCOMP    2007    
          42F0     LD A,(FRAN2)   3A9243  
          42F3     INC A          3C      
          42F4     LD (FRAN2),A   329243  
          42F7;;                          
          42F7;COMPARE FRAME NUMBERS      
          42F7FCOMPLD DE,(FRAMC)  ED5B9343
          42FB     AND A          A7      
          42FC     SBC HL,DE      ED52    
          42FE     LD A,H         7C      
          42FF     OR L           B5      
          4300     JR NZ,TESTQ    2036    
          4302     LD HL,FRAN2    219243  
          4305     LD A,(FRAC2)   3A9543  
          4308     SUB (HL)       96      
          4309     JR NZ,TESTQ    202D    
          430B;;                          
          430B;GET BLOCK LENGTH           
          430B     CALL GETB      CD8843  
          430E     JR NZ,ABORT    2056    
          4310     LD C,A         4F      
          4311;;                          
          4311     CALL GETB      CD8843  
          4314     JR NZ,ABORT    2050    
          4316     LD B,A         47      
          4317;;                          
          4317;REQUEST (BC+5) BYTES       
          4317     PUSH BC        C5      
          4318     INC BC         03      
          4319     INC BC         03      
          431A     INC BC         03      
          431B     INC BC         03      
          431C     INC BC         03      
          431D     CALL SETSZ     CD8C43  
          4320     POP BC         C1      
          4321;;                          
          4321;PLAY                       
          4321PLAY CALL GETB      CD8843  
          4324     JR NZ,ABORT    2040    
          4326     CALL PUTB      CD9C42  
          4329     DEC BC         0B      
          432A     LD A,B         78      
          432B     OR C           B1      
          432C     JR NZ,PLAY     20F3    
          432E;;                          
          432e;READ NEXT FRAME            
          432E     JR RNFRA       1882    
          4330;;                          
          4330;WAIT FOR NEXT VIDEO FRAME  
          4330VIDWTLD HL,FRAMS    213440  
          4333     LD A,(HL)      7E      
          4334VIDWLCP (HL)        BE      
          4335     JR Z,VIDWL     28FD    
          4337     RET            C9      
          4338;;                          
          4338;TEST KEY "A" -> QUIT       
          4338TESTQLD A,$FD       3EFD    
          433A     IN A,$FE       DBFE    
          433C     BIT 0,A        CB47    
          433E     JR Z,ABORT     2826    
          4340     JR WNFRA       189D    
          4342;;                          
          4342;UPDATE COUNTER ON SCREEN   
          4342UPDCTLD B,$06       0606    
          4344     LD HL,(DFILE)  2A0C40  
          4347     LD DE,$0020    112000  
          434A     ADD HL,DE      19      
          434BUCASCLD A,(HL)      7E      
          434C     INC A          3C      
          434D     CP $26         FE26    
          434F     JR NZ,USTOR    2002    
          4351     LD A,$1C       3E1C    
          4353USTORLD (HL),A      77      
          4354     RET NZ         C0      
          4355     DEC HL         2B      
          4356     DJNZ UCASC     10F3    
          4358     RET            C9      
          4359;;                          
          4359;SEND BYTE                  
          4359SENDBEXX            D9      
          435A     LD E,A         5F      
          435BSENDWIN A,CONTR     DBEB    
          435D     AND TXEMT      E604    
          435F     JR Z,SENDW     28FA    
          4361     LD A,E         7B      
          4362     OUT DATA,A     D3E3    
          4364     EXX            D9      
          4365     RET            C9      
          4366;;                          
          4366;ABORT SONG                 
          4366ABORTLD A,$F0       3EF0    
          4368     CALL PUTB      CD9C42  
          436B     LD A,$7E       3E7E    
          436d     CALL PUTB      CD9C42  
          4370     LD A,$7F       3E7F    
          4372     CALL PUTB      CD9C42  
          4375     LD A,$09       3E09    
          4377     CALL PUTB      CD9C42  
          437A     LD A,$01       3E01    
          437C     CALL PUTB      CD9C42  
          437F     LD A,$F7       3EF7    
          4381     CALL PUTB      CD9C42  
          4384;SET RETRUN CODE "BREAK"    
          4384BACK LD BC,$0001    010100  
          4387     RET            C9      
          4388;;                          
          4388;READ BYTE INTO A           
          4388;RES CY TO INDICATE "READ"  
          4388GETB AND A          A7      
          4389     JP VDRIV       C39942  
          438C;;                          
          438C;REQUEST (BC) BYTES         
          438C;SET CY TO INDICATE "RDF"   
          438CSETSZSCF            37      
          438D     JP VDRIV       C39942  
          4390;;                          
          4390;VARS                       
          4390FRAMNNOP            00      
          4391     NOP            00      
          4392FRAN2NOP            00      
          4393FRAMCHALT           76      
          4394FRAC1HALT           76      
          4395FRAC2HALT           76      
          4396;;END                       
Alles klar?

Gruß
Siggi
MIDIPL04.P
(4.81 KiB) 17-mal heruntergeladen
Mein ZX81-Web-Server: online seit 2007
http://zx81-siggi.endoftheinternet.org/index.html

Benutzeravatar
siggi
User
Beiträge: 2319
Registriert: 06.12.2005, 08:34
Wohnort: D, Hessen, tiefste Werreraa
Kontaktdaten:

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von siggi » 14.03.2018, 09:31

Und wer den Player mit anderer Hardware (anderer USB-Treiber; andere serielle Schnittstelle für MIDI ) oder mit Treibern auf anderer Adresse verwenden will, hier ein paar Stellen, wo der Player dafür gepatcht werden kann (ist ja auch im BASIC-Programm als Kommentar drin).

Code: Alles auswählen

           11 REM READ USB BYTE: cy CLEAR
            12 REM ->z: BYTE IN A; nz: BREAK
            13 REM REQUEST (BC) BYTES: cy  SET
            14 REM DEFAULT: $200C
            15 REM POKE 17050/51:USB-READM
            16 REM -------------------
            17 REM SEND MIDI BYTE IN A
            18 REM POKE 17053/54:UART-OUT
            19 REM -------------------
 

Auf Adresse 17050/51 kann man die Adresse der READM-Routine des USB-Treibers poken (LSB/HSB)
Auf Adresse 17053/54 kann man die Adresse der SEND-Routine des RS232-Treibers poken (LSB/HSB)

Diese Routinen müssen sich genauso wie die Original-Routinen verhalten (wie oben beschrieben).

Damit könnte man also andere USB-Treiber (auch ZXMore/ZXBlast, mittels noch zu schreibendem USB-Treiberschnittstellenprogramm, z. B. oberhalb 32K) oder andere serielle Schnittstellen (Multiport-Karte, Memotech-RS232-Karte(?), ZxPand :mrgreen: ) für Midi nutzen.

Gruß
Siggi
Mein ZX81-Web-Server: online seit 2007
http://zx81-siggi.endoftheinternet.org/index.html

Benutzeravatar
siggi
User
Beiträge: 2319
Registriert: 06.12.2005, 08:34
Wohnort: D, Hessen, tiefste Werreraa
Kontaktdaten:

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von siggi » 14.03.2018, 11:53

So und hier auch noch das Programm und Batch-Dateien, um MIDI-Dateien auf dem PC zeddy-tauglich zu machen (incl. einer Midi-Datei zum Üben):

CONV.BAT konvertiert eine MIDI-Datei in eine MZX-Datei
CONVALL konvertiert alle Midi-Dateien im aktuellen Verzeichnis in MZX-Dateien (benutzt CONV.BAT)
CONVCVS.BAT konvertiert eine CVS-Datei (generiert von MIDICVS) in eine MZX-Datei.

Micromash.zip
(33.11 KiB) 18-mal heruntergeladen

Allerdings muß man wohl .NET4 von Winzigweich auf seinem Rechner installiert haben, damit Micromash.exe rennt ...

Gruß
Siggi

PS: Wenn einer das auf einem anderem OS benutzen will: den C# Sourcecode kann ich liefern, aber compilieren muß er selbst ...
Mein ZX81-Web-Server: online seit 2007
http://zx81-siggi.endoftheinternet.org/index.html

Benutzeravatar
siggi
User
Beiträge: 2319
Registriert: 06.12.2005, 08:34
Wohnort: D, Hessen, tiefste Werreraa
Kontaktdaten:

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von siggi » 14.03.2018, 12:22

Und zu guter Letzt noch den UFM-8K, der den aktuellen USB-Treiber 2.00 für den NU enthält.
Den kann man auf dem NU nach 8K laden und gleich loslegen.

Gruß
Siggi
UFM-8KNU.P
(13.03 KiB) 15-mal heruntergeladen
Mein ZX81-Web-Server: online seit 2007
http://zx81-siggi.endoftheinternet.org/index.html

Benutzeravatar
Joachim
User
Beiträge: 960
Registriert: 06.11.2004, 20:21

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von Joachim » 14.03.2018, 13:38

Hallo Siggi,
ich bräuchte noch den Schaltplan für die Stromschleife und den Anschluss an ZXserial (sowie die Adressenjumperung bei 4 Mhz). Habe schon gesucht, ob er in einem der Threads ist, aber nichts gefunden. Vielleicht den aus der Präsentation?
Viele Grüße!
Joachim


ZX80, ZX81, ZX-Spectrum, ZX96, ZX2000, ZXmore, ZX81NU, Blauer Engel, AX81

Benutzeravatar
siggi
User
Beiträge: 2319
Registriert: 06.12.2005, 08:34
Wohnort: D, Hessen, tiefste Werreraa
Kontaktdaten:

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von siggi » 14.03.2018, 13:46

Hallo Joachim
der Schaltplan war ja beim Vortag zu sehen. Da ist er drin:
MIDI-Vortrag.zip
(2.45 MiB) 23-mal heruntergeladen
Die Brücke zur Baudrateneinstellung sitzt auf der 4. Position (von oben gezählt, wenn der DIN-Stecker unten ist und die Baudraten Jumperreihe rechts).

Gruß
Siggi
Mein ZX81-Web-Server: online seit 2007
http://zx81-siggi.endoftheinternet.org/index.html

Benutzeravatar
siggi
User
Beiträge: 2319
Registriert: 06.12.2005, 08:34
Wohnort: D, Hessen, tiefste Werreraa
Kontaktdaten:

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von siggi » 14.03.2018, 13:52

Und hier zur Sicherheit noch das MIDIINIT-Programm: es schaltet den Teiler im UART auf 1 UND schaltet RTS ein.
MIDIINIT.P
(1.25 KiB) 18-mal heruntergeladen
Mein ZX81-Web-Server: online seit 2007
http://zx81-siggi.endoftheinternet.org/index.html

Benutzeravatar
ZX-Heinz
User
Beiträge: 1428
Registriert: 05.12.2011, 14:45

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von ZX-Heinz » 14.03.2018, 16:29

Hallo siggi, tolle Sache.
Für die Nachnutzung wäre es schön, die Informationen, die über verschiedene Threads verteilt sind, zu vereinigen. Kannst Du nicht einmal alles Notwendige in kurzer Form zusammen stellen? Und eine kleine Skizze zur Informationsverarbeitung und den nötigen Bausteinen angefangen beim SD-file auf der SD-card bis hin zum Lautsprecher?
Gruß, Heinz

Benutzeravatar
siggi
User
Beiträge: 2319
Registriert: 06.12.2005, 08:34
Wohnort: D, Hessen, tiefste Werreraa
Kontaktdaten:

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von siggi » 14.03.2018, 17:05

Hallo Heinz
in diesem Thread ist alles vorhanden, was man für den Midiplayer so braucht. Ich will hier aber nicht Gott und die Welt beschreiben, nur weil diese mit im Spiel sein könnten und ich diese nur wie üblich benutze (oder hier eine RS232-Karte und das VDRIVE mit USB-Treiber oder UFM). Dafür gibt's eigene Threads, die deren eigene Details beschreiben. Allenfalls würde ich darauf verlinken.

Hier der Arbeitsablauf, wie er bei mir geht.

- RS-232-Karte oder Multio-Karte mit 4Mhz Quarz bestücken und einstellen, so daß 31250 Baud Takt rauskommen. Uart initialisieren (Midinit oder Mserinit)
- UFM-8K (oder USB-Treiber) nach 8K laden (ins RAM dort)
- MIDIPL04 laden und starten
- dort Name der zu spielenden Datei (ebbes.mzx) eingeben oder UFM starten, um damit die Datei auszusuchen und auf Adresse 0 zu laden.
- dann ggf. noch Player starten ("S" eingeben)

Bei mir fallen die MIDI-Bits dann am MIDI-Stecker raus. Wenn da mein Schlüsselbrett angeschlossen ist, wandelt das die Midi-Daten in Töne um. Aber dessen Schaltplan und der Weg zu dessen Lautsprecher verlinke ich hier nicht :wink:

Gruß
Siggi
Mein ZX81-Web-Server: online seit 2007
http://zx81-siggi.endoftheinternet.org/index.html

Benutzeravatar
siggi
User
Beiträge: 2319
Registriert: 06.12.2005, 08:34
Wohnort: D, Hessen, tiefste Werreraa
Kontaktdaten:

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von siggi » 15.03.2018, 08:13

Hallo Joachim
noch ein Tipp zur Midi-Interface-Platine: ich habe da am Midi-Ausgang auch eine grüne LED (über Jumper abtrennbar) angeschlossen. Wenn kein MIDI-Gerät dran hängt, ersetzt sie die LED im Optokoppler des Midigeräts und ich kann direkt sehen, ob Midi-Daten rausgehen.
Hilft manchmal beim Debuggen.

Gruß
Siggi
Mein ZX81-Web-Server: online seit 2007
http://zx81-siggi.endoftheinternet.org/index.html

Benutzeravatar
ZX-Heinz
User
Beiträge: 1428
Registriert: 05.12.2011, 14:45

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von ZX-Heinz » 15.03.2018, 15:13

Danke siggi, das reicht erst mal.
H.

Benutzeravatar
siggi
User
Beiträge: 2319
Registriert: 06.12.2005, 08:34
Wohnort: D, Hessen, tiefste Werreraa
Kontaktdaten:

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von siggi » 18.03.2018, 17:53

So, und hier ein "richtiger" Midiplayer, der "richtige" MIDI-Dateien (in Version 0) frisst und keine vom PC vorverdauten Files braucht. :mrgreen:

Er ist von dem Player hier ( https://www.mikrocontroller.net/topic/48542 ) abgeleitet und für den Zeddy angepaßt.

Da der Zeddy, anders als der Atmel, keine Timer/Counter intern hat, habe ich dazu den NMI benutzt.

Während der Player läuft, werden die NMIs gezählt (in der NMI-Interrupt-Routine) und damit das Timing gemacht (also nun nicht mehr mit NOVA). Da sieht man also kein Bild, kriegt aber was auf die Ohren (wer dennoch ein Bild sehen will, kann sich ja einen Schaltplan des Zeddy währenddessen ansehen :wink: )

Da der Atmel mit 8 MHz läuft, kann er Ticks mit 1 us verarbeiten. Beim Zeddy mit 3,25 MHz habe ich statt dessen den NMI, der mir nach 207 Clocks bzw. 64 us einen Tick liefern kann (falls vom Midi-Timing so erforderlich).

Der Player ist in C geschrieben und hat nix im BASIC-Bereich drin. Um ihn zu benutzen, muß man
- die serielle Schnittstelle initialisiert haben (mit MIDI-Baudrate , MIDIINIT oder MSERINIT)
- die MIDI-Datei (mit neuem USB-Treiber bzw UFM) geöffnet haben ("L dingens.mid 0")

Dann kann man den Player starten, der dann die offene Mididatei liest und abspielt.
Mit A (Abort) kann man abbrechen.

Und so sieht es aus, wenn er fertig ist:

IMG_0040_640x480.JPG
IMG_0040_640x480.JPG (29.05 KiB) 700 mal betrachtet

Hier ist das Programm:

MidiPlay.P
(5.32 KiB) 13-mal heruntergeladen

Und hier der Source-Code

Code: Alles auswählen

//zcc +zx81 -startup=2 -create-app -vn -O2 -o MidiPlay.bin MidiPlayer.c

// ZX81 Midiplayer V0.90
// Ported from
// "Mr.MidiPlayer v1.0" (see https://www.mikrocontroller.net/topic/48542)
// and adapted to ZX81 .
// NMI is used as timer, counting in 64 us ticks @ 3,25 MHz
// Made by Siggi, March 2018
//
// Hardware: ZX81, RS232 board (8251 compatible, ctrl/data at $EB/E3)
//           USB-Interface
// Software: USB-Driver at 8192 (READM-routine at $200C to read an open file)
//

#include <stdlib.h>
#include <zx81.h>
#include <stdio.h>
#include <input.h>


/* globals */
unsigned long OCR1A;          /* Atmel timer register */

unsigned long trk_len = 512;  /* default read block size */

unsigned int block_counter;

unsigned int timer_running;
unsigned long time_stamp_last_event;

/* Variables handled inside interrupt routine: Handle with care!
/* read by interrupt routine */
unsigned char isr_low_count_start;
unsigned int  isr_high_count_start;
/* updated by interrupt routine */
unsigned char isr_low_count;
unsigned int  isr_high_count;
unsigned long isr_time;


/* Prototypes */

void send_all_off();
void key_detect(void);


// MCU initialisieren
void hw_init(void) {
	OCR1A = 2058;                         /* 16 Bit Output Compare Register */
	send_all_off();
}


void __CALLEE__ sendbyte(unsigned short byte)
{
#asm
	POP HL  ; HL = return address
 	POP BC  ; C  = y,  and  remove y from stack (necessary for CALLEE functions)
 	PUSH HL	; return address back to stackLEX (SP),HL
SENDWAIT:
	IN A,($EB)     ;DBEB
        AND 4
        JR Z,SENDWAIT
        LD A, C
        OUT ($E3), A    ;D3E3
#endasm
}


// All midi off
void send_all_off(void)
{
        sendbyte(0xF0);
        sendbyte(0x7E);
        sendbyte(0x7F);
        sendbyte(0x09);
        sendbyte(0x01);
        sendbyte(0xF7);
}

unsigned char fetchbyte(void)
{
	if (block_counter == 0)
	{
	   block_counter = 512;
	   if ((trk_len > 0) && (block_counter > trk_len))
	        block_counter = trk_len;   /* Don't read pastfile end of file */

	   /* request next block from file */
	   #asm
	   ld bc,(_block_counter)
	   scf
	   call $200C
	   #endasm
	   in_Wait(1); /* wait 1 msec to allow VDRIVE to answer */
	}

	/* read 1 char */
	block_counter--;
	trk_len--;

	#asm
	and a		; clear carry
	call $200C
	ld l, a
	ld h, 0         ; HL holds return value
	#endasm
}

void flush_remaning_bytes(void)
{
	while (block_counter > 0)
	{
		fetchbyte();
	}
}

void checkbyte(unsigned char b) {
	if (b != fetchbyte())
	{
		printf("Checkbyte failed: %d\n", b);
		exit(1);
	}
}


char checkstring(unsigned char *buf, unsigned char len) {
	unsigned char b, cnt=0;

	for (cnt=0; cnt<len; cnt++) {
		b = fetchbyte();
		if (b != buf[cnt])
		{
		        printf("Checkstring failed: %d instead of %d\n", b, buf[cnt]);
			return 0;
		}
	}
	return 1;
}

/* global vars used here. Access to globals ist faster than to locals */
unsigned long v;
unsigned char c;
unsigned long fetch_varlen(void) {

	c = fetchbyte();
	v = c;
	if (v & 0x80) {
		v &= 0x7F;
		do {
			c = fetchbyte();
			v = (v << 7) + (c & 0x7F);
		} while (c & 0x80);
	}
  	return v;
}


void key_detect(void) {
#asm
	LD A, $FD
        IN A, ($FE)
        BIT 0, A
        RET NZ
#endasm
	printf("ABORT\n");
        exit(1); /* key "A" has been pressed */
}

/* global vars used here. Access to globals ist faster than to locals */
unsigned long end_time;
void wait_for_deltatime(void)
{
        /* read dt from file */
        /* Note: Timer is runnig and counts also time during file access! */
	end_time = fetch_varlen();

        end_time += time_stamp_last_event;
        do
        {
		key_detect();
#asm
		halt	; time critical section follows
#endasm
		time_stamp_last_event = isr_time;
	}
	while (time_stamp_last_event < end_time);
}

/* start NMI timer. May only be used during FAST mode! */
void start_NMI_Timer(void)
{
#asm
	ex af, af
    	ld a, (_isr_low_count_start)
    	ex af, af
    	ld hl, (_isr_high_count_start)
    	ld (_isr_high_count), hl
    	ld iy, _TIMER_ISR                   ; iy will get ix during assembly for ZX81!
    	out ($FE), a
#endasm
	timer_running = 1;
}

/* stop running NMI timer and restore BASIC SLOW mode */
void stop_NMI_Timer(void)
{
	if (timer_running)
	{
#asm
		out ($FD),a
#endasm
		timer_running = 0;
	}
	zx_slow();
}

/* global vars used here. Access to globals ist faster than to locals */
unsigned char low;
unsigned int high;

/* setup the NMI timer. May be also be used while NMI counter is running */
void setup_NMI_Timer(unsigned long tickLength)
{
	 /* convert Atmel 8 MHz timing into ZX81 NMI timing @ 3,25 MHz: divide by 64 */
        tickLength = tickLength >> 6;

        low = ~((tickLength & 0xFF) + 1); /* bit 0..7 negated (NMI counts A up! */
        high = tickLength >> 8;  /* bit 8..23 */
//	printf("NMI(%ld)\n", tickLength);
	if (timer_running)
#asm
		halt ; update values quickly after interrupt
#endasm
	isr_low_count_start = low;
	isr_high_count_start = high;
}

/* global vars used here. Access to globals ist faster than to locals */
unsigned char ev, len, adp;
unsigned int gl_timeset;
unsigned long temp;

void main(void)
{
	printf("------- MIDIPLAYER V0.90 -------\n\n");
	hw_init();
	gl_timeset = 96;  /* default MIDI timing */
	block_counter = 0;

        /* expected MIDI file header MThd */
 	ev = 0;
	while ((!checkstring("M", 1)) && (ev < 5))
	{
		ev++;
	}

	if (!checkstring("Thd", 3))
	{
		printf("No MIDI file.\n");
		exit (EXIT_FAILURE);
	}

        /* expected length: 6 bytes */
	checkbyte(0);
	checkbyte(0);
	checkbyte(0);
	checkbyte(6);

	/* expected MIDI file version: 0 */
	checkbyte(0);
	if ((ev = fetchbyte()) != 0)
	{
		printf("Wrong MIDI file version: %d\n", ev);
		exit (EXIT_FAILURE);
	}

        /* expected track number: 1 */
	checkbyte(0);
	if ((ev = fetchbyte()) != 1)
	{
		printf("Wrong number of tracks: %d\n", ev);
		exit (EXIT_FAILURE);
	}

        /* fetch MIDI timing of that track */
	gl_timeset = ((unsigned int) fetchbyte()) << 8;
	gl_timeset |= (unsigned int) fetchbyte();

        printf("Global timeset = %d\n", gl_timeset);

        /* calc OCR1A in 2 steps as workaround for Z88DK calc error using constants */
	if (gl_timeset < 0x8000)
	{
		// Delta-Ticks
		OCR1A = 500000;
		OCR1A /= (unsigned long) gl_timeset;
	}
	else
	{
		// SMPTE-Timeformat
		OCR1A = 1000000;
		OCR1A /= (-(char)(gl_timeset>>8))/(unsigned char)gl_timeset;
        }

        /* ZX81 NMI: 16000 = 1 sec, 16 = 1msec , 1 = 207 clock cycles/64 usec */
      	setup_NMI_Timer(OCR1A);

        /* expect MIDI track MTrk and fetch its length */
	checkstring("MTrk", 4);

	temp = (unsigned long)fetchbyte() << 24;
	temp |= (unsigned long)fetchbyte() << 16;
	temp |= (unsigned long)fetchbyte() << 8;
	temp |= (unsigned long)fetchbyte();
	trk_len = temp;

	printf ("Track Length = %ld\n"\
		"Press any key (or A to abort)\n", trk_len);

        do
        {
      		key_detect();
        }
        while (!in_Inkey());
        while (in_Inkey());  /* wait for key released */

        atexit(send_all_off);
        atexit(stop_NMI_Timer);
        atexit(flush_remaning_bytes);

        zx_fast();

        /* Setup timer variables used by NMI routine */
	time_stamp_last_event = isr_time = 0;

	start_NMI_Timer();

	while (trk_len)
	{
		wait_for_deltatime();
		ev = fetchbyte();
		if (ev == 0xFF) {	// META-EVENT
			ev = fetchbyte();
			switch (ev) {
				case 0x2f:	// End Of Track
					checkbyte(0);
					send_all_off();
					flush_remaning_bytes();
					trk_len = 0;
					break;

				case 0x51:	// Tempo Change
					checkbyte(3);
					temp = (unsigned long)fetchbyte() << 16;
					temp |= (unsigned long)fetchbyte() << 8;
					temp |= (unsigned long)fetchbyte();
					OCR1A = temp/gl_timeset;
					setup_NMI_Timer(OCR1A);
					break;

				default:         // Ignore it
					temp = fetch_varlen();
					while (temp) {
						temp--;
						fetchbyte();
					}
			}
		}
		else if (ev == 0xf0) {	// SYSEX
			sendbyte(ev);
			temp = fetch_varlen();
			while (temp) {
				temp--;
				sendbyte(fetchbyte());
			}
		}
		else if (ev >= 0x80) {	// MIDI-EVENT
			sendbyte(ev);
			switch (ev) {
				case 0xf2:
					len = 2;
					break;
				case 0xf3:
					len = 1;
					break;
				default:
					switch (ev & 0xf0) {
						case 0xf0:
							len = 0;
							break;
						case 0xc0:	// ProgramChange
						case 0xd0:	// ChannelAftertouch
							len = 1;
							break;
						case 0x80:	// NoteOff
						case 0x90:	// NoteOn
						case 0xa0:	// PolyphonicAftertouch
						case 0xb0:	// ControlModeChange
						case 0xe0:	// PitchWheel
							len = 2;
							break;
						default:
							printf("Unknown MIDI event %d\n", ev);
							exit(2);
					}
			}
			adp = len;
			while (len) {
				sendbyte(fetchbyte());
				len--;
			}
		}
		else
		{			// Running Status
			sendbyte(ev);
			len = adp-1;
			while (len) {
				sendbyte(fetchbyte());
				len--;
			}
		}
	}
	printf("Feddisch ;-)\n");
	printf("Total time %ld ticks\n", isr_time);
}

/* NMI interrupt routine. Called from ROM via register IX */

TIMER_ISR()
{
#asm
	; NMI is stopped, alternate reg A active and is 0
	; count high byte counter down
        ld hl, (_isr_high_count)
        ld a, h
        or l
        dec hl
        ld (_isr_high_count), hl
        ld a, 0			; reload A for 256 NMIs
        jr nz, ISR_CONT
#endasm

	isr_time++;		// count time since start of track

#asm
	; restart timer
    	ld a, (_isr_low_count_start)
    	ld hl, (_isr_high_count_start)
    	ld (_isr_high_count), hl

ISR_CONT:
    	ex af, af
    	out ($FE), a
	pop hl
	pop de
	pop bc
	pop af
#endasm
}

Aus Performance-Gründen rufe ich die Schnittstellen (USB-Treiber und serielle) direkt aus dem C-Programm auf. Sie sind also erstmal festgelegt auf Joachims RS232-Karte mit Default Adressen und aktuellem USB-Treiber auf 8192.

Wenn andere Ports oder Treiberadressen benötigt werden (bitte Bescheid geben), dann kann ich auch eine Version basten, bei der man das konfigurieren kann (was aber dann zu einem etwas langsameren Zugriff führt).

Viel Spaß damit
Siggi
Mein ZX81-Web-Server: online seit 2007
http://zx81-siggi.endoftheinternet.org/index.html

Benutzeravatar
Joachim
User
Beiträge: 960
Registriert: 06.11.2004, 20:21

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von Joachim » 18.03.2018, 18:44

Hallo Siggi,
du legst ein Wahnsinnstempo vor! Sagenhaft!
Frage: Ich würde die Midi-Geschichte lieber auf auf einem 'normalen' ZX verwenden, also nicht den NU, weil ich da kein VDRIVE dran habe. Wenn ich den USB-Treiber 1.3.3. (nicht für NU) zur neuen Version (die mit dem Streamen) umschreibe, gibt es dann Timingprobleme mit dem Midi-Output, weil das nächste Byte bzw. Block nicht schnell genug gelesen wird?
Viele Grüße!
Joachim


ZX80, ZX81, ZX-Spectrum, ZX96, ZX2000, ZXmore, ZX81NU, Blauer Engel, AX81

Benutzeravatar
siggi
User
Beiträge: 2319
Registriert: 06.12.2005, 08:34
Wohnort: D, Hessen, tiefste Werreraa
Kontaktdaten:

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von siggi » 18.03.2018, 19:03

Hallo Joachim
wenn die Bytes zu langsam eintreffen, könnte sich das auf die Abspielgeschwindigkeit auswirken: da wo im Musik-Stück viel passiert und viele Bytes verschoben werden müssen, könnte sich das dann an dieser Stelle auswirken. Schlimmstenfalls wird das Stück nicht mit gleichmässiger Geschwindigkeit abgespielt.
Bei der alten Version, das die MZX-Dateien abspielt, wäre das unkritischer. Beim C-Programm, das die Midi-Datei direkt abspielt, muß viel mehr als Datenschaufeln zwischen USB und Seriell passieren. Dazu werden weitere Daten vom Stick gelesen (Timing-Info, Tempo ,...) und verarbeitet (aber nicht ausgegeben). Da könnte sich ein langsameres Interface auch auf andere Musikteile auswirken, wo weniger passiert.
Dazu habe ich aber noch keine Erfahrung, das muß mal halt probieren ...

Gruß
Siggi
Mein ZX81-Web-Server: online seit 2007
http://zx81-siggi.endoftheinternet.org/index.html

Benutzeravatar
siggi
User
Beiträge: 2319
Registriert: 06.12.2005, 08:34
Wohnort: D, Hessen, tiefste Werreraa
Kontaktdaten:

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von siggi » 25.03.2018, 10:25

So hier mal wieder der aktuelle Stand (V0.93).
Wie gehabt muß serielle Schnittstelle initialisiert sein und UFM (USB-Treiber) bei 8K liegen. Dann kann man sofort loslegen:
MIDIPL93.P
(5.82 KiB) 13-mal heruntergeladen
Und wer's genau wissen will: hier der Sourcecode

Code: Alles auswählen

//zcc +zx81 -startup=2 -create-app -nv -O2 -o MidiPlay.bin MidiPlayer.c

// ZX81 Midiplayer V0.93
// Ported from
// "Mr.MidiPlayer v1.0" (see https://www.mikrocontroller.net/topic/48542)
// and adapted to ZX81 .
// NMI is used as timer, counting in 64 us ticks @ 3,25 MHz
// Made by Siggi, March 2018
//
// Hardware: ZX81, RS232 board (8251 compatible, ctrl/data at $EB/E3)
//			 USB-Interface
// Software: USB-Driver at 8192 (READM-routine at $200C to read an open file)
//

//#define DEBUG


#include <stdlib.h>
#include <zx81.h>
#include <stdio.h>
#include <input.h>


/* globals */
unsigned long us_per_beat;			/* timing register in microseconds */

unsigned long trk_len = 512;		/* default read block size */

unsigned int block_counter;

unsigned int timer_running;
unsigned long time_stamp_last_event;

/* Variables handled inside interrupt routine: Handle with care!
/* read by interrupt routine */
unsigned char isr_low_count_start;
unsigned int  isr_high_count_start;
/* updated by interrupt routine */
unsigned char isr_low_count;
unsigned int  isr_high_count;
unsigned long isr_time;

unsigned int debug_wait_too_slow;

/* Prototypes */

void send_MIDI_reset();
void key_detect(void);
void cleanup(void);
void setup_NMI_Timer_in_us(unsigned long tickLength);
void start_NMI_Timer(void);
void stop_NMI_Timer(void);

// MCU initialisieren
void hw_init(void)
{
	send_MIDI_reset();
	debug_wait_too_slow = 0;
}


void __FASTCALL__ sendbyte(unsigned short byte)
{
#asm
		; byte is in HL
SENDWAIT:
	IN A,($EB)	   ;DBEB
	AND 4
	JR Z,SENDWAIT
	LD A, L
	OUT ($E3), A	;D3E3
#endasm
}


// All midi off
void send_MIDI_reset(void)
{
	sendbyte(0xF0);
	sendbyte(0x7E);
	sendbyte(0x7F);
	sendbyte(0x09);
	sendbyte(0x01);
	sendbyte(0xF7);
}

unsigned char fetchbyte(void)
{
	if (!block_counter)
	{
		block_counter = 1024;
		/* request next block from file */
		#asm
		ld bc,(_block_counter)
		scf
		call $200C
		#endasm
	}
	/* read 1 char */
	#asm
;	block_counter--;
	ld	hl,(_block_counter)
	dec	hl
	ld	(_block_counter),hl
;	trk_len--;
	ld	hl,(_trk_len)
	ld	de,(_trk_len+2)
	call	l_declong
	ld	(_trk_len),hl
	ld	(_trk_len+2),de
	and a		; clear carry
	call $200C
	ld l, a
	ld h, 0 		; HL holds return value
	#endasm
}

void flush_remaining_bytes(void)
{
	while (block_counter)
	{
		fetchbyte();
	}
}

void checkbyte (unsigned char b)
{
	if (b == fetchbyte())
		return;

	printf("Checkbyte failed: %d\n", b);
	cleanup();
	exit(5);
}


char checkstring(unsigned char *buf, unsigned char len) {
	unsigned char b, cnt=0;

	for (cnt=0; cnt<len; cnt++) {
		b = fetchbyte();
		if (b != buf[cnt])
		{
			printf("Checkstring failed: %d instead of %d\n", b, buf[cnt]);
			return 0;
		}
	}
	return 1;
}

/* global vars used here. Access to globals ist faster than to locals */
unsigned long v;
unsigned char c;

unsigned long fetch_varlen(void)
{
	c = fetchbyte();
	v = c & 0x7F;
	while (c & 0x80)
	{
		/* one more byte follows */
		c = fetchbyte();
		v = (v << 7) + (c & 0x7F);
	}
	return v;
}


void key_detect(void)
{
	#asm
	LD A, $FD
	IN A, ($FE)
	BIT 0, A
	RET NZ
	#endasm
	printf("ABORT\n");
	cleanup();
	exit(1); /* key "A" has been pressed */
}
/* global vars used here. Access to globals ist faster than to locals */
unsigned long end_time;

void wait_for_deltatime(void)
{
	/* read dt from file */
	/* Note: Timer is runnig and counts also time during file access! */
	end_time = fetch_varlen();

	if (end_time) /* do nothing if delay is 0 */
	{
		end_time += time_stamp_last_event;
		do
		{
			key_detect();
			#asm
		re_check:
			ld bc,(_isr_time+2)				; get high bytes of isr_time
			ld de,(_isr_time)				; get low bytes of isr_time
			ld hl,(_isr_time)				; get low bytes again to detect change by NMI (will affect at least low bytes)
			and a							; clear carry bit
			sbc hl, de						; check for no change
			jr nz, re_check					; try again if NMI occurred
			ld (_time_stamp_last_event), de	; store low bytes
			ld (_time_stamp_last_event+2), bc ; store high bytes
			#endasm
			if (time_stamp_last_event == end_time)
				return;
			if (time_stamp_last_event > end_time)
			{
				debug_wait_too_slow++;
				return;
			}
			#asm
			halt		; wait for next time slice
			#endasm
		}
		while(1);
	}
}

/* start NMI timer */
void start_NMI_Timer(void)
{
	zx_fast();
	#asm
	ex af, af
	ld a, (_isr_low_count_start)			; set alternate A with low counter
	ex af, af
	ld hl, (_isr_high_count_start)			; setup high counter
	ld (_isr_high_count), hl
	ld iy, _TIMER_ISR						; iy will get ix during assembly for ZX81!
	out ($FE), a							; start NMI generator
	#endasm
	timer_running = 1;
}

/* stop running NMI timer and restore BASIC SLOW mode */
void stop_NMI_Timer(void)
{
	if (timer_running)
	{
		timer_running = 0;
	}
	zx_slow();
}

/* global vars used here. Access to globals ist faster than to locals */
unsigned char low;
unsigned int high;

/* setup the NMI timer in unit usec. May be also be used while NMI counter is running */
void setup_NMI_Timer_in_us(unsigned long tickLength)
{
	 /* convert microseconds into ZX81 NMI timing @ 3,25 MHz:
	 /* do some timing corrections and the divide by 64 (64 usec/NMI) */
	if (tickLength & 0xFFFFFE00) /* > 512 */
		tickLength -= 150;
	else
		tickLength -= 96;
	tickLength = tickLength >> 6;
#ifdef DEBUG
	if (!tickLength)
		printf("Warning: NMI ticklen 0\n");
#endif
#ifdef DEBUG
	if (tickLength > 1000000)
		printf("Warning: ticklen > 1000000\n");
#endif
	// ticklen	|low	|high
	//	0			0		0	invalid -> 256
	//  1			FF		0
	//	2			FE		0
	//	254			02		0
	//	255			01		0
	//	256			00		0	NMI counts A to 0 -> reload value is 0 for next 256 NMIs
	//	257			FF		1	count 1 by A and 256 by high
	//	258			FE		1	count 2 by A and 256 by high
	//	511			01		1
	//	512			00		1
	//	513			FF		2

	low = 256 - (unsigned int) (tickLength & 0xFF); /* bit 0..7  */
	high = (tickLength - 1) >> 8;  /* bit 8..23 */
#ifdef DEBUG
	printf("NMIs(%lu),L=%u,H=%u\n", tickLength, low, high);
#endif
	if (timer_running)
	{
		#asm
		halt ; update values handled in interrupt routine quickly after interrupt
		#endasm
	}
	isr_low_count_start = low;
	isr_high_count_start = high;
	if (!timer_running)
	{
		/* update also current state of high counter */
		isr_high_count = high;
	}
}

/* global vars used here. Access to globals ist faster than to locals */
unsigned char ev, len, adp;
unsigned int gl_BeatsPerMin_BPM;
unsigned long temp;

void main(void)
{
	printf("---- ZX81 MIDIPLAYER V0.93 ----\n\n");
	hw_init();
	gl_BeatsPerMin_BPM = 120;  /* default MIDI timing */
	us_per_beat = 500000L;     /* correspondens to beat length 0,5 sec = 1/120 min */

	/* for file buffer handling */
	block_counter = 0;

	/* expected MIDI file header MThd */
	ev = 0;
	while ((!checkstring("M", 1)) && (ev < 4))
	{
		ev++;
	}

	if (!checkstring("Thd", 3))
	{
		printf("No MIDI file.\n");
		cleanup();
		exit (2);
	}

		/* expected length: 6 bytes */
	checkbyte(0);
	checkbyte(0);
	checkbyte(0);
	checkbyte(6);

	/* expected MIDI file version: 0 */
	checkbyte(0);
	if ((ev = fetchbyte()) != 0)
	{
		printf("Wrong MIDI file version: %d\n", ev);
		cleanup();
		exit (3);
	}

	/* expected track number: 1 */
	checkbyte(0);
	if ((ev = fetchbyte()) != 1)
	{
		printf("Wrong number of tracks: %d\n", ev);
		cleanup();
		exit (4);
	}

	/* fetch MIDI timing of that track */
	gl_BeatsPerMin_BPM = ((unsigned int) fetchbyte()) << 8;
	gl_BeatsPerMin_BPM |= (unsigned int) fetchbyte();

	printf("Global timeset = %u\n", gl_BeatsPerMin_BPM);

	/* calc us_per_beat in 2 steps as workaround for Z88DK calc error using constants */
	if (gl_BeatsPerMin_BPM < 0x8000)
	{
		// Delta-Ticks (in usec for one minute
		us_per_beat = 60000000;   /* microseconds in one minute */
		us_per_beat /= gl_BeatsPerMin_BPM;
	}
	else
	{
		// SMPTE-Timeformat
		us_per_beat = 60000000;   /* microseconds in one minute */
		us_per_beat /= (-(char)(gl_BeatsPerMin_BPM>>8))/((unsigned char)gl_BeatsPerMin_BPM);
		printf("SMPTE time format is used.\n");
	}
#if 0
	/* calc OCR1A in 2 steps as workaround for Z88DK calc error using constants */
	if (gl_BeatsPerMin_BPM < 0x8000)
	{
		// Delta-Ticks
		OCR1A = 500000;
		OCR1A /= (unsigned long) gl_BeatsPerMin_BPM;
	}
	else
	{
		// SMPTE-Timeformat
		OCR1A = 1000000;
		OCR1A /= (-(char)(gl_BeatsPerMin_BPM>>8))/(unsigned char)gl_BeatsPerMin_BPM;
	}
#endif
	printf("Beat length in us = %lu\n", us_per_beat);

	/* expect MIDI track MTrk and fetch its length */
	checkstring("MTrk", 4);

	temp = (unsigned long)fetchbyte() << 24;
	temp |= (unsigned long)fetchbyte() << 16;
	temp |= (unsigned long)fetchbyte() << 8;
	temp |= (unsigned long)fetchbyte();
	trk_len = temp;

	printf ("Track Length = %lu\n"\
	"Press any key (or A to abort)\n", trk_len);
	do
	{
		key_detect();
	}
	while (!in_Inkey());
	while (in_Inkey());  /* wait for key released */

	/* Setup timer variables used by NMI routine */
	time_stamp_last_event = isr_time = 0;

	/* ZX81 NMI: 16000 = 1 sec, 16 = 1msec , 1 = 207 clock cycles/64 usec */
	setup_NMI_Timer_in_us(us_per_beat);

	start_NMI_Timer();

	while (trk_len)
	{
		wait_for_deltatime();
		ev = fetchbyte();
		if (ev == 0xFF) {	// META-EVENT
			ev = fetchbyte();
			switch (ev) {
				case 0x2f:	// End Of Track
					checkbyte(0);
					trk_len = 0;
					break;

				case 0x51:	// Tempo Change
					checkbyte(3);
//					temp = (unsigned long)fetchbyte() << 16;
//					temp |= (unsigned long)fetchbyte() << 8;
//					temp |= (unsigned long)fetchbyte();
					#asm
					call _fetchbyte		; H is 0, L holds value
					ld (_temp+2), HL	; update temp+3 and temp+2
					call _fetchbyte
					ld a, l
					ld (_temp+1), a
					call _fetchbyte
					ld a, l
					ld (_temp), a
					#endasm
					us_per_beat = temp / gl_BeatsPerMin_BPM;

#ifdef DEBUG
					printf("Tempo=%lu,BPM=%u,usec=%lu\n", temp, gl_BeatsPerMin_BPM, us_per_beat);
#endif
					setup_NMI_Timer_in_us(us_per_beat);
					break;

				default:		 // Ignore unknown META-EVENT
					temp = fetch_varlen();
					while (temp--)
					{
						fetchbyte();
					}
			}
		}
		else if (ev == 0xf0)
		{	// SYSEX
			sendbyte(ev);
			temp = fetch_varlen();
			while (temp--)
			{
				sendbyte(fetchbyte());
			}
		}
		else if (ev & 0x80)
		{	// MIDI-EVENT
			sendbyte(ev);
			switch (ev)
			{
				case 0xf2:
					len = 2;
					break;
				case 0xf3:
					len = 1;
					break;
				default:
					switch (ev & 0xf0)
					{
						case 0xf0:
							len = 0;
							break;
						case 0xc0:	// ProgramChange
						case 0xd0:	// ChannelAftertouch
							len = 1;
							break;
						case 0x80:	// NoteOff
						case 0x90:	// NoteOn
						case 0xa0:	// PolyphonicAftertouch
						case 0xb0:	// ControlModeChange
						case 0xe0:	// PitchWheel
							len = 2;
							break;
						default:
							printf("Unknown MIDI event type %d\n", ev);
							cleanup();
							exit(7);
//no break?
					}
//no break?
			}
			adp = len;
			while (len--) {
				sendbyte(fetchbyte());
			}
		}
		else
		{	// Running Status
			sendbyte(ev);
			len = adp-1;
			while (len--)
				sendbyte(fetchbyte());
		}
	}
	printf("Feddisch ;-)\n");
	printf("Total time %lu ticks\n", isr_time);
	cleanup();
	exit(0);
}

void cleanup(void)
{
	send_MIDI_reset();
	stop_NMI_Timer();
	flush_remaining_bytes();
	printf("Delay overruns:%u\n", debug_wait_too_slow);
}


/* NMI interrupt routine. Called from ROM via register IX */

TIMER_ISR()
{
	#asm
	; NMI is stopped, alternate reg A active and is 0
	; restart NMI to count own runtime
	out ($FE), a

	; count high byte counter down
	ld hl, (_isr_high_count)
	ld a, h
	or l
	dec hl
	ld (_isr_high_count), hl
	ld a, 0 		; reload A for next 256 NMIs
	jr nz, ISR_CONT
;	isr_time++; 	// count time since start of track
	ld	hl,(_isr_time)
	ld	de,(_isr_time+2)
	call	l_inclong
	ld	(_isr_time),hl
	ld	(_isr_time+2),de
	; restart timer
	ld a, (_isr_low_count_start)
	ld hl, (_isr_high_count_start)
	ld (_isr_high_count), hl

ISR_CONT:
	ex af, af
;	out ($FE), a
	pop hl
	pop de
	pop bc
	pop af
	#endasm
}

Viel Spaß
Siggi
Mein ZX81-Web-Server: online seit 2007
http://zx81-siggi.endoftheinternet.org/index.html

Benutzeravatar
bodo
User
Beiträge: 319
Registriert: 14.02.2007, 17:21
Kontaktdaten:

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von bodo » 29.03.2018, 22:00

siggi hat geschrieben:
14.03.2018, 11:53
[…] den C# [Sourcecode …]
Natürlich muss Musik-Software in dieser Sprache geschrieben werden! :lol:
B0D0: Real programmers do it in hex.

Benutzeravatar
siggi
User
Beiträge: 2319
Registriert: 06.12.2005, 08:34
Wohnort: D, Hessen, tiefste Werreraa
Kontaktdaten:

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von siggi » 30.03.2018, 17:16

Erstmal fröhliches Ostereiersuchen (und Bemalen, mit oder ohne Zeddy :wink: )

Hier nun der Midiplayer V 1.00, zusammen mit einem Basic-Programm zum einfacheren Bedienen.

Ich habe im Player noch viele Taktzyklen einsparen können und habe dafür an die Stellen, wo der Zeddy nichts tut, außer auf ein Timeout zu warten, ein paar Gimmicks eingebaut.
An anderen Stellen habe ich auch noch Gimmicks eingebaut, die aber normalerweise nicht eingeschaltet sind, weil sie Zeit fressen können und das Abspielen runterbremsen könnten.

Erstmal zur Bedienung. Der Player läuft im "Auslieferungszustand" nach Start erstmal in ein Menü, um Gimmicks ein oder auszuschalten.
Da deren Zustand in "static" Variablen abgelegt wird, bleiben diese beim nächsten Start (oder nach Abspeichern des Programms) erhalten und werden beim nächsten Start dann ohne weitere Fragen wieder so eingestellt. Damit kann man den Player voreinstellen und z. B. in ein BASIC-Programm einbetten, das z. B. die Directory nach Midi-Files durchsucht und diese dem Player zum Abspielen geöffnet übergibt, der sie dann ohne weitere Rückfragen abspielt.
Wer dennoch die Einstellungen wieder ändern will, kommt wieder ins Menü, wenn der nach Start des Players irgend eine Taste gedrückt hält.

Im Menü kann man dann einstellen:
-SPEED (Default 100%). Damit kann man die Abspielgeschwindigkeit in Auflösung von ca. 3% erhöhen/erniedrigen. Das kann sinnvoll sein, wenn man bei einen schnellen Stück mit dem Tanzen nicht hinterher kommt (wie damals bei meinem Rock 'n' Roll-Training :D)
-DIAG (Default OFF): dadurch werden zur Laufzeit TEMPO-Änderungen und Timer-Registereinstellungen ausgegeben (wichtig zum Debuggen für mich). Aber erst nach Ende des Stück kann man die dann sehen.
-TEXT (Default OFF): dadurch wird Text im MIDI-File (Titel, Instument, Songtext) aus der MIDI-Datei auf den Bildschirm ausgegeben. Aber erst nach Ende des Stück kann man die dann sehen.

Wenn der Player dann läuft, kann man durch Tastendruck auf die Tasten 6/7 die Abspielgeschwindigkeit absenken/erhöhen, mit 8 verdoppeln, mit 9 halbieren und mit 0 auf Normalgeschwindigkeit einstellen. Bleibt man bei 6/7 auf der Taste permanent drauf, hängt der Player und die Musik fest.

Nach Ende des Stück wird die Länge des Stücks in Ticks ausgegeben und angezeigt, wie viele Delays (>0) der Zeddy ausgeführt hat und wie oft der Zeddy ein vorgegebenes Delay nicht einhalten konnte (weil zu langsam). Letzterer Wert wird auch von der Schnelligkeit des USB-Dateizugriffs beeinflußt (Joachim!).

Hier sind ein paar Meßwerte von mir, die als Anhaltspunkte dienen können, wenn man den Player mit einem anderen USB-Treiber benutzen will:

Scorpions Wind of Change: 8291/92
Rhapsody: 38333/5375
Rocky Horror Pickture Show 6916/ 825

Letzeres Musikstück ist nicht zu lang und eignet sich gut zum Testen der Performance.

Hier diese Stücke zum Vergleichen:
Testsongs.zip
(200.81 KiB) 11-mal heruntergeladen
Hier der Player im Basic-Programm:
MIDIPL10.P
(8.17 KiB) 10-mal heruntergeladen
Und hier der nackte Player ohne Rahmenprogramm:
MidiPlay.P
(7.73 KiB) 11-mal heruntergeladen
Und hier der Source

Code: Alles auswählen

//zcc +zx81 -startup=2 -create-app -Cz--disable-autorun -v -O2 -o MidiPlay.bin MidiPlayer.c

// ZX81 Midiplayer V1.00
// Ported from
// "Mr.MidiPlayer v1.0" (see https://www.mikrocontroller.net/topic/48542)
// and adapted to ZX81 .
// NMI is used as timer, counting in 64 us ticks @ 3,25 MHz
// Made by Siggi, March 2018
//
// Hardware: ZX81, RS232 board (8251 compatible, ctrl/data at $EB/E3)
//			 USB-Interface
// Software: USB-Driver at 8192 (READM-routine at $200C to read an open file)
//

#include <stdlib.h>
#include <zx81.h>
#include <stdio.h>
#include <input.h>

/* globals */
unsigned long us_per_beat;			/* timing register in microseconds */

unsigned long trk_len;

unsigned int block_counter;

unsigned int timer_running;
unsigned long time_stamp_last_event;

/* Variables handled inside interrupt routine: Handle with care!
/* read by interrupt routine */
unsigned int isr_low_count_start;
unsigned int isr_high_count_start;
/* updated by interrupt routine */
unsigned int  isr_low_count;
unsigned int  isr_high_count;
unsigned long isr_time;

/* Variables used for analysis/debugging */
static unsigned char debug_enabled = 0;		/* must be char due to speed! */
unsigned int debug_wait_too_slow;
unsigned long debug_min_ticks;
unsigned long debug_max_ticks;
unsigned long debug_min_delays;
unsigned long debug_max_delays;
unsigned int debug_delay_calls;

/* Variables used for gimmicks */
static unsigned char speed_nominator = 0;	/* must be char due to speed! */
int new_nominator;

static char text_enabled = 0;				/* must be char due to speed! */

/* For handling of the startup behaviour */
static unsigned int last_cmd = 0;

/* Prototypes */

void send_MIDI_reset();
void cleanup(void);
void setup_NMI_Timer_in_us(unsigned long tickLength);
void start_NMI_Timer(void);
void stop_NMI_Timer(void);
void break_detected(void);

// MCU initialisieren
void hw_init(void)
{
	send_MIDI_reset();
	debug_min_ticks=0XFFFFFFFF;
	debug_max_ticks=0;
	debug_min_delays=0XFFFFFFFF;
	debug_max_delays=0;
	debug_wait_too_slow = 0;
	debug_delay_calls = 0;
}


void __FASTCALL__ sendbyte(unsigned short byte)
{
#asm
		; byte is in HL
SENDWAIT:
	IN A,($EB)	   ;DBEB
	AND 4
	JR Z,SENDWAIT
	LD A, L
	OUT ($E3), A	;D3E3
#endasm
}


// All midi off
void send_MIDI_reset(void)
{
	sendbyte(0xF0);
	sendbyte(0x7E);
	sendbyte(0x7F);
	sendbyte(0x09);
	sendbyte(0x01);
	sendbyte(0xF7);
}

unsigned int fetchbyte(void)
{
	if (!block_counter)
	{
		block_counter = 4096;
		/* request next block from file */
		#asm
		ld bc,(_block_counter)
		scf
		call $200C
		#endasm
	}
	/* read 1 char, decrement counter */
	--block_counter;

	#asm
	and a					; clear carry
	call $200C
	ld l, a
	ld h, 0 				; HL holds return value
	ret z
	#endasm
	block_counter = 0;		// ABORT detected: clear block counter
	break_detected();		// keypress A has been detected
}

void flush_remaining_bytes(void)
{
	while (block_counter)
	{
		fetchbyte();
	}
}

void checkbyte (unsigned int b)
{
	if (b == fetchbyte())
		return;

	printf("Checkbyte failed: %d\n", b);
	cleanup();
	exit(5);
}


char checkstring(unsigned char *buf, unsigned int len) {
	unsigned char b, cnt=0;

	for (cnt=0; cnt<len; cnt++) {
		b = fetchbyte();
		if (b != buf[cnt])
		{
			printf("Checkstring failed: %d instead of %d\n", b, buf[cnt]);
			return 0;
		}
	}
	return 1;
}

/* global vars used here. Access to globals ist faster than to locals */
unsigned long v;
unsigned int c;

unsigned long fetch_varlen(void)
{
	c = fetchbyte();
	v = c & 0x7F;
	while (c & 0x80)
	{
		/* one more byte follows */
		c = fetchbyte();
		v = (v << 7) + (c & 0x7F);
	}
	return v;
}

void break_detected(void)
{
	printf("ABORT\n");
	cleanup();
	exit(1); /* key "A" has been pressed */
}


/* global vars used here. Access to globals ist faster than to locals */
unsigned long end_time;

void wait_for_deltatime(void)
{
	/* read dt from file */
	/* Note: Timer is runnig and counts also time during file access! */
	end_time = fetch_varlen();

	if (end_time) /* do nothing if delay is 0 */
	{
		++debug_delay_calls;
		if (debug_enabled)
		{
       		if (end_time < debug_min_delays)
       			debug_min_delays = end_time;
       		if (end_time > debug_max_delays)
       			debug_max_delays = end_time;
        }
		end_time += time_stamp_last_event;

		#asm
	re_check:
		ld bc,(_isr_time+2)				; get high bytes of isr_time
		ld de,(_isr_time)				; get low bytes of isr_time
		ld hl,(_isr_time)				; get low bytes again to detect change by NMI (will affect at least low bytes)
		and a							; clear carry bit
		sbc hl, de						; check for no change
		jr nz, re_check					; try again if NMI occurred
		ld (_time_stamp_last_event), de	; store low bytes
		ld (_time_stamp_last_event+2), bc ; store high bytes
		#endasm

		if (time_stamp_last_event == end_time)
			return;
		if (time_stamp_last_event > end_time)
		{
			++debug_wait_too_slow;
			return;
		}
			/* here we have time for gimmicks: check keys for speed manipulation */
		#asm
		ld a,$EF        	; bit 4 low: decode keyboard line 6-0
		in a,($FE)
		bit 4, a
		jr nz, chk7          ; key 6
		#endasm
		;  /*less speed */
		if (speed_nominator)
			++speed_nominator;
		else
			speed_nominator = 33;
		setup_NMI_Timer_in_us(us_per_beat);;
		in_WaitForNoKey();  /* wait for key released */
		#asm
		jr keyend

chk7:
		bit 3, a
		jr nz, chk8          ; key 7
		#endasm
		;  /* more speed */
		if (speed_nominator)
			--speed_nominator;
		else
			speed_nominator = 31;
		setup_NMI_Timer_in_us(us_per_beat);
		in_WaitForNoKey();  /* wait for key released */
		#asm
		jr keyend

chk8:
		bit 2, a
		jr nz, chk9          ; key 8
		#endasm
		;	/* double speed */
		speed_nominator = 16;
		setup_NMI_Timer_in_us(us_per_beat);
		#asm
		jr keyend

chk9:
		bit 1, a
		jr nz, chk0          ; key 9
		#endasm
		;	/* half speed */
		speed_nominator = 64;
		setup_NMI_Timer_in_us(us_per_beat);
		#asm
		jr keyend

chk0:
		bit 0, a
		jr nz, keyend          ; key 0
		#endasm
		;	/* normal speed */
		speed_nominator = 0;
		setup_NMI_Timer_in_us(us_per_beat);
		#asm

keyend:
		#endasm

		if (speed_nominator == 32)
			speed_nominator = 0;

		#asm
		jp re_check
		#endasm
	}
}

/* start NMI timer */
void start_NMI_Timer(void)
{
	zx_fast();
	#asm
	ex af, af
	ld a, (_isr_low_count_start)			; set alternate A with low counter
	ex af, af
	ld hl, (_isr_high_count_start)			; setup high counter
	ld (_isr_high_count), hl
	ld iy, _TIMER_ISR						; iy will get ix during assembly for ZX81!
	out ($FE), a							; start NMI generator
	#endasm
	timer_running = 1;
}

/* stop running NMI timer and restore BASIC SLOW mode */
void stop_NMI_Timer(void)
{
	if (timer_running)
	{
		timer_running = 0;
	}
	zx_slow();
}

/* global vars used here. Access to globals ist faster than to locals */
unsigned int low;
unsigned int high;

/* setup the NMI timer in unit usec. May be also be used while NMI counter is running */
void setup_NMI_Timer_in_us(unsigned long tickLength)
{
	if (debug_enabled)
	{
		if (tickLength < debug_min_ticks)
			debug_min_ticks = tickLength;
		if (tickLength > debug_max_ticks)
			debug_max_ticks = tickLength;
    }
	/*	convert to other speed */
	if (speed_nominator)
	{
		tickLength = (tickLength * speed_nominator) >> 5; /* denominator is 32 */
	}
	 /* convert microseconds into ZX81 NMI timing @ 3,25 MHz:
	 /* do some timing corrections and the divide by 64 (64 usec/NMI) */
	if (tickLength & 0xFFFFFE00) /* > 512 */
		tickLength -= 150;
	else
		tickLength -= 96;

	tickLength = tickLength >> 6;

	if(debug_enabled)
	{
		if (!tickLength)
			printf("Warning: NMI ticklen 0\n");
		if (tickLength > 1000000)
			printf("Warning: ticklen > 1000000\n");
	}
	// ticklen	|low	|high
	//	0			0		0	invalid -> 256
	//  1			FF		0
	//	2			FE		0
	//	254			02		0
	//	255			01		0
	//	256			00		0	NMI counts A to 0 -> reload value is 0 for next 256 NMIs
	//	257			FF		1	count 1 by A and 256 by high
	//	258			FE		1	count 2 by A and 256 by high
	//	511			01		1
	//	512			00		1
	//	513			FF		2

	low = 256 - (unsigned int) (tickLength & 0xFF); /* bit 0..7  */
	high = (tickLength - 1) >> 8;  /* bit 8..23 */
	if (debug_enabled)
		printf("NMIs(%lu),L=%u,H=%u\n", tickLength, low, high);
	if (timer_running)
	{
		#asm
		halt ; update values handled in interrupt routine quickly after interrupt
		#endasm
	}
	isr_low_count_start = low;
	isr_high_count_start = high;
	if (!timer_running)
	{
		/* update also current state of high counter */
		isr_high_count = high;
	}
}

/* global vars used here. Access to globals ist faster than to locals */
unsigned char ev;     /* must be char due to speed! */
unsigned int len, adp;
unsigned int gl_BeatsPerMin_BPM;
unsigned long temp;
unsigned char loop;  /* must be char due to speed! */

void main(void)
{
	printf("[ zx81 rs232 MIDIPLAYER v1.00 ]\n\n");
	hw_init();
	gl_BeatsPerMin_BPM = 120;  /* default MIDI timing */
	us_per_beat = 500000L;     /* correspondens to beat length 0,5 sec = 1/120 min */

	/* for file buffer handling */
	block_counter = 0;

	/* expected MIDI file header "MThd" */
	ev = 0;
	while ((!checkstring("M", 1)) && (ev < 4))
	{
		++ev;
	}

	if (!checkstring("Thd", 3))
	{
		printf("No MIDI file.\n");
		cleanup();
		exit (2);
	}

	/* expected length: 6 bytes as 32 bit number */
	checkbyte(0);
	checkbyte(0);
	checkbyte(0);
	checkbyte(6);

	/* expected MIDI file version: 0 */
	checkbyte(0);
	if ((ev = fetchbyte()) != 0)
	{
		printf("Wrong MIDI file version: %d\n", ev);
		cleanup();
		exit (3);
	}

	/* expected track number: 1 */
	checkbyte(0);
	if ((ev = fetchbyte()) != 1)
	{
		printf("Wrong number of tracks: %d\n", ev);
		cleanup();
		exit (4);
	}

	/* fetch MIDI timing of that track */
	gl_BeatsPerMin_BPM = ((unsigned int) fetchbyte()) << 8;
	gl_BeatsPerMin_BPM |= (unsigned int) fetchbyte();

	printf("global timeset = %u\n", gl_BeatsPerMin_BPM);

	/* calc us_per_beat in 2 steps as workaround for Z88DK calc error using constants */
	if (gl_BeatsPerMin_BPM < 0x8000)
	{
		// Delta-Ticks (in usec for one minute
		us_per_beat = 60000000;   /* microseconds in one minute */
		us_per_beat /= gl_BeatsPerMin_BPM;
	}
	else
	{
		// SMPTE-Timeformat
		us_per_beat = 60000000;   /* microseconds in one minute */
		us_per_beat /= (-(char)(gl_BeatsPerMin_BPM>>8))/((unsigned char)gl_BeatsPerMin_BPM);
		printf("SMPTE time format is used.\n");
	}

	printf("beat length in us = %lu\n", us_per_beat);

	/* expect MIDI track "MTrk" and fetch its length */
	checkstring("MTrk", 4);

	temp = (unsigned long)fetchbyte() << 24;
	temp |= (unsigned long)fetchbyte() << 16;
	temp |= (unsigned long)fetchbyte() << 8;
	temp |= (unsigned long)fetchbyte();
	trk_len = temp;
	printf ("track length = %lu\n", trk_len);

    if (in_Inkey())
    {
    	last_cmd = 0; /* If key pressed during startup forget old status */
    }

    if (!last_cmd)
    {
    	loop = 1;
		in_WaitForNoKey();
		while (loop)
		{
			if (speed_nominator)
				new_nominator = 3200/speed_nominator;
			else
				new_nominator = 100;

			printf("current status:\ndiag is %s, speed: %d\n"\
					"text is %s\n",
				debug_enabled ? "ON" : "OFF", new_nominator, text_enabled ? "ENABLED" : "OFF");
			printf("press any key or\nAbort, Diag, Speed, Text\n");
			do
			{
				ev = in_Inkey();
			}
			while (!ev);
			switch (ev)
			{
				case 'D':
					debug_enabled = !debug_enabled;
					break;

				case 'T':
					text_enabled = !text_enabled;
					break;

				case 'S':
					{
						unsigned char buffer[20];
						printf("keys to set speed are:\n6/7 to dec/inc speed\n8/9/0 double/half/normal speed\n");
						printf("enter speed in percent\n(<ret> for %u):", new_nominator);
						gets(buffer);
						if (*buffer)
							new_nominator = atoi(buffer);
						if (new_nominator)
							speed_nominator = 3200/new_nominator;
					}
					break;

				case 'A':
					break_detected();
					break;

				default:
					loop = 0;
					break;
			}
			last_cmd = ev; 		/* save command for next run */
		}
	}
	/* Setup timer variables used by NMI routine */
	time_stamp_last_event = isr_time = 0;

	/* ZX81 NMI: 16000 = 1 sec, 16 = 1msec , 1 = 207 clock cycles/64 usec */
	setup_NMI_Timer_in_us(us_per_beat);
	start_NMI_Timer();

	loop = 1;
	while (loop)
	{
		wait_for_deltatime();
		ev = fetchbyte();
		if (ev == 0xFF)
		{	// META-EVENT
			switch (fetchbyte()) /* Get meta event */
			{
				case 0x2f:	// End Of Track
					checkbyte(0);
					loop = 0;
					break;

				case 0x51:	// Tempo Change
					checkbyte(3);
//					temp = (unsigned long)fetchbyte() << 16;
//					temp |= (unsigned long)fetchbyte() << 8;
//					temp |= (unsigned long)fetchbyte();
					#asm
					call _fetchbyte		; H is 0, L holds value
					ld (_temp+2), HL	; update temp+3 and temp+2
					call _fetchbyte
					ld a, l
					ld (_temp+1), a
					call _fetchbyte
					ld a, l
					ld (_temp), a
					#endasm
					us_per_beat = temp / gl_BeatsPerMin_BPM;

					if (debug_enabled)
						printf("Tempo=%lu,BPM=%u,usec=%lu\n", temp, gl_BeatsPerMin_BPM, us_per_beat);
					setup_NMI_Timer_in_us(us_per_beat);
					break;

				case 0x05: /* Lyric */
				case 0x03: /* Sequence/Track name */
				case 0x04: /* Instrument name */
                    if (text_enabled)  // show text
                    {
						temp = fetch_varlen();
						while (temp--)
						{
							putchar(fetchbyte());
						}
						putchar(' ');
	                    break;
					}
					/* fall trough to ignore text */
				default:		 // Ignore unknown META-EVENT
					temp = fetch_varlen();
					while (temp--)
					{
						fetchbyte();
					}
					break;
			}
		}
		else if (ev == 0xf0)
		{	// SYSEX
			sendbyte(ev);
			temp = fetch_varlen();
			while (temp--)
			{
				sendbyte(fetchbyte());
			}
		}
		else if (ev & 0x80)
		{	// MIDI-EVENT
			sendbyte(ev);
			switch (ev)
			{
				case 0xf2:
					len = 2;
					break;
				case 0xf3:
					len = 1;
					break;
				default:
					switch (ev & 0xf0)
					{
						case 0xf0:
							len = 0;
							break;
						case 0xc0:	// ProgramChange
						case 0xd0:	// ChannelAftertouch
							len = 1;
							break;
						case 0x80:	// NoteOff
						case 0x90:	// NoteOn
						case 0xa0:	// PolyphonicAftertouch
						case 0xb0:	// ControlModeChange
						case 0xe0:	// PitchWheel
							len = 2;
							break;
						default:
							printf("Unknown MIDI event type %d\n", ev);
							cleanup();
							exit(7);
							break;
					}
					break;
			}
			adp = len;
			while (len--) {
				sendbyte(fetchbyte());
			}
		}
		else
		{	// Running Status
			sendbyte(ev);
			len = adp-1;
			while (len--)
				sendbyte(fetchbyte());
		}
	}
	printf("\nFEDDISCH :)\n");
	printf("total time %lu ticks\n", isr_time);
	cleanup();
	exit(0);
}

void cleanup(void)
{
	send_MIDI_reset();
	stop_NMI_Timer();
	flush_remaining_bytes();
	printf("delays/overrun:%u/%u\n", debug_delay_calls, debug_wait_too_slow);
	if (debug_enabled)
	{
		printf("min ticks(us):%lu,max:%lu\n", debug_min_ticks, debug_max_ticks);
		printf("min delay:%lu,max:%lu\n", debug_min_delays, debug_max_delays);
	}
}


/* NMI interrupt routine. Called from ROM via register IX */

TIMER_ISR()
{
	#asm
	; NMI is stopped, alternate reg A active and is 0
	; restart NMI to count own runtime
	out ($FE), a

	; count high byte counter down
	ld hl, (_isr_high_count)
	ld a, h
	or l
	dec hl
	ld (_isr_high_count), hl
	ld a, 0 		; reload A for next 256 NMIs
	jr nz, ISR_CONT
	#endasm
	++isr_time; 	// count time since start of track
	#asm
	; restart timer
	ld a, (_isr_low_count_start)
	ld hl, (_isr_high_count_start)
	ld (_isr_high_count), hl

ISR_CONT:
	ex af, af
	pop hl
	pop de
	pop bc
	pop af
	#endasm
}
Gruß und viel Spaß damit
Siggi
Mein ZX81-Web-Server: online seit 2007
http://zx81-siggi.endoftheinternet.org/index.html

Benutzeravatar
siggi
User
Beiträge: 2319
Registriert: 06.12.2005, 08:34
Wohnort: D, Hessen, tiefste Werreraa
Kontaktdaten:

Re: RS232-Midiplayer und passender USB-Treiber: Playall

Beitrag von siggi » 31.03.2018, 19:54

Zu guter letzt nun auch ein PLAYALL-Programm, das alle *.mid-Dateien im aktuellen Verzeichnis des USB-Stick abspielt.
Es werden alle Nicht-MIDI-Dateien übergangen. Die Dateien werden so abgespielt, wie sie in der Directory vorgefunden werden (es wird also nichts sortiert).

Zum Programmstart wird Nummer im Directory-Eintrag erfragt, ab der nach MIDI-Dateien gesucht werden soll (Minimum ist 1).
Am Ende oder bei BREAK wird die Nummer des Directory-Eintrags ausgegeben, bis zu der man vorgedrungen ist.
Dort kann man später dann ja weitermachen, wenn man sich die Nummer gemerkt hat :mrgreen:

Viel Spaß damit
PLAYALL.P
(9.03 KiB) 11-mal heruntergeladen
Gruß
Siggi
Mein ZX81-Web-Server: online seit 2007
http://zx81-siggi.endoftheinternet.org/index.html

Benutzeravatar
siggi
User
Beiträge: 2319
Registriert: 06.12.2005, 08:34
Wohnort: D, Hessen, tiefste Werreraa
Kontaktdaten:

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von siggi » 10.05.2018, 21:24

So, ich habe jetzt auch mal ein Video aufgenommen, wo der Zeddy ein Midi-Stück abspielt:

https://youtu.be/kD9Tkxjx7yg

Hat denn sonst noch jemand was mit dem Midi-Player gemacht?

Gruß
Siggi
Mein ZX81-Web-Server: online seit 2007
http://zx81-siggi.endoftheinternet.org/index.html

Benutzeravatar
Joachim
User
Beiträge: 960
Registriert: 06.11.2004, 20:21

Re: RS232-Midiplayer und passender USB-Treiber

Beitrag von Joachim » 10.05.2018, 22:18

Hallo Siggi,
ich bin dabei, mir die Midi-Geschichte aufzubauen. Deshalb auch die USB-Treiberanpassung, bei der ich leider ein bißchen fest stecke. Vielleicht baue ich erst alles mit dem NU auf.
Viele Grüße!
Joachim


ZX80, ZX81, ZX-Spectrum, ZX96, ZX2000, ZXmore, ZX81NU, Blauer Engel, AX81

Antworten