10REM> TSDP0 20MODE7 30VDU23,1,0;0;0;0; 40DIM mcode &500 :REM: space for machine code 50DIM buff 40 :REM: TSDP buffer 60PROCmcode :REM: assemble machine code 70ttx$=CHR$(141)+CHR$(132)+CHR$(157)+CHR$(131)+"Television Service Data Packet 0 "+CHR$(156) 80PRINTTAB(0,1)ttx$ 90PRINTTAB(0,2)ttx$ 100INPUTTAB(10,5)"TV channel (1-4) = "answer$ 110channel?0=EVAL("&"+LEFT$(answer$,1))+&1B 120IF channel?0 < &1C THEN channel?0 = &1C 130IF channel?0 > &1F THEN channel?0 = &1F 140PRINTTAB(5,9)"TSDP type =" 150PRINTTAB(5,10)"Initial page =" 160PRINTTAB(5,11)"Channel code = &" 170PRINTTAB(5,12)"Programme =" 180PRINTTAB(5,13)"Mod. Julian date =" 190PRINTTAB(5,14)"Day/Month/Year =" 200PRINTTAB(5,15)"Time =" 210PRINTTAB(5,16)"GMT" 220PRINTTAB(5,17)"Message =" 230CALL mcode :REM: enable TTX interrupts 240ONERROR GOTO 280 250REPEAT 260IF grabflag?0=0 PROCdisplay 270UNTIL FALSE 280CALL mcode :REM: disable TTX interrupts 290VDU31,0,21,23,1,1;0;0;0; 300END 310DEFPROCdisplay 320PRINTTAB(17,9);buff?0 330b0=((buff?4)AND8)<>0:REM: bit 0 of magazine number 340b1=((buff?6)AND4)<>0:REM: bit 1 of magazine number 350b2=((buff?6)AND8)<>0:REM: bit 2 of magazine number 360init=0:REM: initial magazine number 370IF b0 init=1 380IF b1 init=init+2 390IF b2 init=init+4 400PRINTTAB(20,10);~init;:REM: initial magazine 410PRINT;~buff?2;~buff?1;:REM: initial page 420PRINT;" ";~((buff?6)AND3);~buff?5;~((buff?4)AND7);~buff?3:REM: initial sub-page 430VDU31,21,11:PROChex(buff?7):REM: channel high byte 440PROChex(buff?8):REM: channel low byte 450VDU31,17,12 :REM: print programme 460FOR byte=16 TO 19 470VDU (buff?byte OR &80) :REM: set bit 7 for printing 480NEXT 490VDU31,24,13 :REM: modified Julian date 500PROChex(((buff?10)-&01)AND15):REM: 10000's 510full$=part$ 520PROChex((buff?11)-&11):REM: 1000's and 100's 530full$=full$+part$ 540PROChex((buff?12)-&11):REM: 10's and 1's 550full$=full$+part$ 560J%=VAL(full$) 570Y%=(100*(J%-15078.2))DIV36525 580M%=INT((J%-14956.1-INT(365.25*Y%))/30.6001) 590D%=J%-14956-INT(365.25*Y%)-INT(30.6*M%) :REM: day 600IF M%<14 THEN K%=0 ELSE K%=1 610M%=M%-1-12*K% :REM: month 620Y%=Y%+K%+1900 :REM: year 630PRINTTAB(22,14);D%;"/";M%;"/";Y% :REM: day/month/year 640VDU31,12,15 :REM: print time 650PROChex((buff?13)-&11):REM: hours 660PRINT;":"; 670PROChex((buff?14)-&11):REM: minutes 680PRINT;":"; 690PROChex((buff?15)-&11):REM: seconds 700IF buff?9 = &85 PRINTTAB(5,16)"Add 1 hr for BST" :REM: &81=GMT 710VDU31,15,17 :REM: print message 720FOR byte=20 TO 39 730VDU (buff?byte OR &80) :REM: set bit 7 for printing 740NEXT 750VDU7 760grabflag?0=2 :REM: grabflag = searching 770ENDPROC 780DEFPROChex(N%):REM: print both nybbles of a hex. number 790L%=N% MOD 16 800H%=N% DIV 16 810PRINT;~H%;~L%; 820part$=STR$(H%)+STR$(L%) 830ENDPROC 840DEFPROCmcode 850packet=&70 :REM: row number of current packet 860magazine=&71 :REM: magazine number of current page 870grabflag=&72 :REM: page grabber flag 880channel=&73 :REM: TV channel 890savereg=&FC :REM: interrupt accumulator save register 900irq2v=&206 :REM: irq2 vector 910ttxcontrol=&FC10 :REM: TTX control register, write only 920ttxstatus=&FC10 :REM: TTX status register, read only 930rowreg=&FC11 :REM: TTX row register, write only 940datareg=&FC12 :REM: TTX data register, read & write 950statclr=&FC13 :REM: TTX clear status register, read & write 960FOR pass=0 TO 2 STEP 2 970P%=mcode 980[OPT pass 990LDA #&02 1000STA grabflag \ grabflag = searching 1010LDX irq2v \ load secondary interrupt vector 1020LDY irq2v+1 1030CPY #interrupt DIV 256 1040BEQ disable 1050STX oldirq2v \ save secondary interrupt vector 1060STY oldirq2v+1 1070LDX #interrupt MOD 256 \ install new interrupt routine 1080LDY #interrupt DIV 256 1090SEI \ disable interrupts when altering vector 1100STX irq2v 1110STY irq2v+1 1120CLI \ re-enable interrupts 1130LDA channel \ load (channel number + #&1C) 1140STA ttxcontrol \ enable TTX 1150RTS \ return to BASIC 1160.disable 1170LDA #&00 1180STA ttxcontrol \ disable TTX 1190LDX oldirq2v \ load original vector 1200LDY oldirq2v+1 1210SEI \ disable interrupts when altering vector 1220STX irq2v \ restore original vector 1230STY irq2v+1 1240CLI \ re-enable interrupts 1250RTS \ return to BASIC 1260.interrupt 1270BIT ttxstatus \ poll TTX hardware 1280BMI ttxinter \ branch if TTX interrupt 1290JMP (oldirq2v) \ not TTX interrupt 1300.ttxinter 1310LDA savereg \ interrupt accumulator save register 1320PHA \ push interrupt accumulator save register 1330TXA 1340PHA \ push X 1350TYA 1360PHA \ push Y 1370LDA grabflag \ has TSDP been grabbed? 1380BEQ clearstatus \ clear status and RTI if TSDP grabbed 1390CLD \ clear decimal flag 1400LDY #&00 \ start with row 0 1410.readttxt 1420STY rowreg \ try rows 0 to 15 1430LDA datareg \ load framing code (#&27) 1440BEQ emptyrow \ if zero try next row 1450TYA 1460PHA \ save row number 1470JSR readpacket 1480PLA 1490TAY \ restore row number 1500.emptyrow 1510INY \ increment row number 1520CPY #&10 \ try rows 0 - 15 1530BNE readttxt 1540.clearstatus 1550LDA #&00 1560LDY #&0F \ clear 16 rows in adaptor 1570.clearloop 1580STY rowreg 1590STA datareg 1600DEY 1610BPL clearloop 1620STA statclr \ clear status flags before returning 1630PLA 1640TAY \ restore Y 1650PLA 1660TAX \ restore X 1670PLA 1680STA savereg \ restore interrupt accumulator save register 1690RTI \ return from interrupt 1700.readpacket 1710LDA grabflag \ just checking 1720BEQ return 1730LDY datareg \ read magazine number 1740LDA hamtable,Y \ de-ham it 1750BMI return \ stop loading if error 1760STA magazine \ save magazine number 1770LDY datareg \ read packet number 1780LDA hamtable,Y \ de-ham it 1790BMI return \ stop loading if error 1800STA packet \ save packet number 1810LDA magazine \ load magazine number 1820CMP #&08 \ bit 3 of mag. number is bit 0 of packet number 1830ROL packet \ 5 bit packet number 1840AND #&07 \ use only bits 0-2 1850CMP #&00 \ is this magazine 0? 1860BNE return \ return ifInte