[{"data":1,"prerenderedAt":3473},["ShallowReactive",2],{"blogvtx5000-part-4-comms-routines":3,"blogMore-Technology":3460,"comments-vtx5000-part-4-comms-routines":3472},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"tags":11,"category":15,"excerpt":16,"body":36,"_type":3451,"_id":3452,"_source":3453,"_file":3454,"_stem":3455,"_extension":3456,"url":3457,"wordCount":3458,"minutes":962,"commentCount":3459},"/blog/2026/2026-05-06-vtx5000-part-4-comms-routines","2026",false,"en","VTX5000: Part 4 - Comms routines","In part 3 we saw how the VTX5000's 8K ROM is structured and how the BASIC program drives the terminal. Now we'll look at the Z80 machine code that handles the real-time work: talking to the 8251 USART, managing the ring buffers, and scanning the keyboard with its Prestel-specific remapping.","2026-05-06T10:19:24.727Z",[12,13,14],"ZX Spectrum","vintage computing","Z80","Technology",{"type":17,"children":18},"root",[19,31],{"type":20,"tag":21,"props":22,"children":23},"element","p",{},[24,27,29],{"type":25,"value":26},"text","In ",{"type":25,"value":28},"part 3",{"type":25,"value":30}," we saw how the VTX5000's 8K ROM is structured and how the BASIC program drives the terminal. Now we'll look at the Z80 machine code that handles the real-time work: talking to the 8251 USART, managing the ring buffers, and scanning the keyboard with its Prestel-specific remapping.",{"type":20,"tag":21,"props":32,"children":33},{},[34],{"type":25,"value":35},"Now that all the memory tests, housekeeping and trampolines are setup it's time to get interfacing!",{"type":17,"children":37,"toc":3439},[38,49,53,60,65,72,353,359,639,645,830,836,857,978,983,988,993,999,2200,2206,2219,2349,2370,2375,2381,2386,2522,2565,2571,2576,2745,2750,2772,2785,2791,2796,2815,2893,2910,3049,3054,3074,3080,3085,3102,3136,3261,3267,3280,3293,3409,3422,3428,3433],{"type":20,"tag":21,"props":39,"children":40},{},[41,42,48],{"type":25,"value":26},{"type":20,"tag":43,"props":44,"children":46},"a",{"href":45},"/blog/2026/04/16/vtx5000-part-3-software-rom/",[47],{"type":25,"value":28},{"type":25,"value":30},{"type":20,"tag":21,"props":50,"children":51},{},[52],{"type":25,"value":35},{"type":20,"tag":54,"props":55,"children":57},"h3",{"id":56},"the-intel-8251",[58],{"type":25,"value":59},"The Intel 8251",{"type":20,"tag":21,"props":61,"children":62},{},[63],{"type":25,"value":64},"The 8251 has a bunch of bits that can be set for commands and configuration:",{"type":20,"tag":66,"props":67,"children":69},"h4",{"id":68},"command-flags",[70],{"type":25,"value":71},"Command flags",{"type":20,"tag":73,"props":74,"children":75},"table",{},[76,106],{"type":20,"tag":77,"props":78,"children":79},"thead",{},[80],{"type":20,"tag":81,"props":82,"children":83},"tr",{},[84,91,96,101],{"type":20,"tag":85,"props":86,"children":88},"th",{"align":87},"left",[89],{"type":25,"value":90},"Bit",{"type":20,"tag":85,"props":92,"children":93},{"align":87},[94],{"type":25,"value":95},"Mask",{"type":20,"tag":85,"props":97,"children":98},{"align":87},[99],{"type":25,"value":100},"Name",{"type":20,"tag":85,"props":102,"children":103},{"align":87},[104],{"type":25,"value":105},"Meaning when set",{"type":20,"tag":107,"props":108,"children":109},"tbody",{},[110,147,174,206,233,268,295,326],{"type":20,"tag":81,"props":111,"children":112},{},[113,119,129,134],{"type":20,"tag":114,"props":115,"children":116},"td",{"align":87},[117],{"type":25,"value":118},"7",{"type":20,"tag":114,"props":120,"children":121},{"align":87},[122],{"type":20,"tag":123,"props":124,"children":126},"code",{"className":125},[],[127],{"type":25,"value":128},"$80",{"type":20,"tag":114,"props":130,"children":131},{"align":87},[132],{"type":25,"value":133},"Hunt mode",{"type":20,"tag":114,"props":135,"children":136},{"align":87},[137,139,145],{"type":25,"value":138},"In synchronous mode, enter hunt for ",{"type":20,"tag":123,"props":140,"children":142},{"className":141},[],[143],{"type":25,"value":144},"SYN",{"type":25,"value":146}," characters",{"type":20,"tag":81,"props":148,"children":149},{},[150,155,164,169],{"type":20,"tag":114,"props":151,"children":152},{"align":87},[153],{"type":25,"value":154},"6",{"type":20,"tag":114,"props":156,"children":157},{"align":87},[158],{"type":20,"tag":123,"props":159,"children":161},{"className":160},[],[162],{"type":25,"value":163},"$40",{"type":20,"tag":114,"props":165,"children":166},{"align":87},[167],{"type":25,"value":168},"Internal reset",{"type":20,"tag":114,"props":170,"children":171},{"align":87},[172],{"type":25,"value":173},"Reset the 8251 state machine; the next byte is configuration mode",{"type":20,"tag":81,"props":175,"children":176},{},[177,182,191,196],{"type":20,"tag":114,"props":178,"children":179},{"align":87},[180],{"type":25,"value":181},"5",{"type":20,"tag":114,"props":183,"children":184},{"align":87},[185],{"type":20,"tag":123,"props":186,"children":188},{"className":187},[],[189],{"type":25,"value":190},"$20",{"type":20,"tag":114,"props":192,"children":193},{"align":87},[194],{"type":25,"value":195},"RTS",{"type":20,"tag":114,"props":197,"children":198},{"align":87},[199,201],{"type":25,"value":200},"Assert ",{"type":20,"tag":123,"props":202,"children":204},{"className":203},[],[205],{"type":25,"value":195},{"type":20,"tag":81,"props":207,"children":208},{},[209,214,223,228],{"type":20,"tag":114,"props":210,"children":211},{"align":87},[212],{"type":25,"value":213},"4",{"type":20,"tag":114,"props":215,"children":216},{"align":87},[217],{"type":20,"tag":123,"props":218,"children":220},{"className":219},[],[221],{"type":25,"value":222},"$10",{"type":20,"tag":114,"props":224,"children":225},{"align":87},[226],{"type":25,"value":227},"Error reset",{"type":20,"tag":114,"props":229,"children":230},{"align":87},[231],{"type":25,"value":232},"Clear parity, overrun and framing error flags",{"type":20,"tag":81,"props":234,"children":235},{},[236,241,250,255],{"type":20,"tag":114,"props":237,"children":238},{"align":87},[239],{"type":25,"value":240},"3",{"type":20,"tag":114,"props":242,"children":243},{"align":87},[244],{"type":20,"tag":123,"props":245,"children":247},{"className":246},[],[248],{"type":25,"value":249},"$08",{"type":20,"tag":114,"props":251,"children":252},{"align":87},[253],{"type":25,"value":254},"Send break",{"type":20,"tag":114,"props":256,"children":257},{"align":87},[258,260,266],{"type":25,"value":259},"Force the ",{"type":20,"tag":123,"props":261,"children":263},{"className":262},[],[264],{"type":25,"value":265},"TxD",{"type":25,"value":267}," line low",{"type":20,"tag":81,"props":269,"children":270},{},[271,276,285,290],{"type":20,"tag":114,"props":272,"children":273},{"align":87},[274],{"type":25,"value":275},"2",{"type":20,"tag":114,"props":277,"children":278},{"align":87},[279],{"type":20,"tag":123,"props":280,"children":282},{"className":281},[],[283],{"type":25,"value":284},"$04",{"type":20,"tag":114,"props":286,"children":287},{"align":87},[288],{"type":25,"value":289},"Rx enable",{"type":20,"tag":114,"props":291,"children":292},{"align":87},[293],{"type":25,"value":294},"Enable the receiver",{"type":20,"tag":81,"props":296,"children":297},{},[298,303,312,317],{"type":20,"tag":114,"props":299,"children":300},{"align":87},[301],{"type":25,"value":302},"1",{"type":20,"tag":114,"props":304,"children":305},{"align":87},[306],{"type":20,"tag":123,"props":307,"children":309},{"className":308},[],[310],{"type":25,"value":311},"$02",{"type":20,"tag":114,"props":313,"children":314},{"align":87},[315],{"type":25,"value":316},"DTR",{"type":20,"tag":114,"props":318,"children":319},{"align":87},[320,321],{"type":25,"value":200},{"type":20,"tag":123,"props":322,"children":324},{"className":323},[],[325],{"type":25,"value":316},{"type":20,"tag":81,"props":327,"children":328},{},[329,334,343,348],{"type":20,"tag":114,"props":330,"children":331},{"align":87},[332],{"type":25,"value":333},"0",{"type":20,"tag":114,"props":335,"children":336},{"align":87},[337],{"type":20,"tag":123,"props":338,"children":340},{"className":339},[],[341],{"type":25,"value":342},"$01",{"type":20,"tag":114,"props":344,"children":345},{"align":87},[346],{"type":25,"value":347},"Tx enable",{"type":20,"tag":114,"props":349,"children":350},{"align":87},[351],{"type":25,"value":352},"Enable the transmitter",{"type":20,"tag":66,"props":354,"children":356},{"id":355},"configuration-mode-flags",[357],{"type":25,"value":358},"Configuration mode flags",{"type":20,"tag":73,"props":360,"children":361},{},[362,387],{"type":20,"tag":77,"props":363,"children":364},{},[365],{"type":20,"tag":81,"props":366,"children":367},{},[368,373,377,382],{"type":20,"tag":85,"props":369,"children":370},{"align":87},[371],{"type":25,"value":372},"Bit(s)",{"type":20,"tag":85,"props":374,"children":375},{"align":87},[376],{"type":25,"value":95},{"type":20,"tag":85,"props":378,"children":379},{"align":87},[380],{"type":25,"value":381},"Meaning in async mode",{"type":20,"tag":85,"props":383,"children":384},{"align":87},[385],{"type":25,"value":386},"Notes",{"type":20,"tag":107,"props":388,"children":389},{},[390,447,477,514,567],{"type":20,"tag":81,"props":391,"children":392},{},[393,398,407,412],{"type":20,"tag":114,"props":394,"children":395},{"align":87},[396],{"type":25,"value":397},"7-6",{"type":20,"tag":114,"props":399,"children":400},{"align":87},[401],{"type":20,"tag":123,"props":402,"children":404},{"className":403},[],[405],{"type":25,"value":406},"$C0",{"type":20,"tag":114,"props":408,"children":409},{"align":87},[410],{"type":25,"value":411},"Stop bit length",{"type":20,"tag":114,"props":413,"children":414},{"align":87},[415,421,423,429,431,437,439,445],{"type":20,"tag":123,"props":416,"children":418},{"className":417},[],[419],{"type":25,"value":420},"00",{"type":25,"value":422}," = invalid, ",{"type":20,"tag":123,"props":424,"children":426},{"className":425},[],[427],{"type":25,"value":428},"01",{"type":25,"value":430}," = 1 stop bit, ",{"type":20,"tag":123,"props":432,"children":434},{"className":433},[],[435],{"type":25,"value":436},"10",{"type":25,"value":438}," = 1.5 stop bits, ",{"type":20,"tag":123,"props":440,"children":442},{"className":441},[],[443],{"type":25,"value":444},"11",{"type":25,"value":446}," = 2 stop bits",{"type":20,"tag":81,"props":448,"children":449},{},[450,454,462,467],{"type":20,"tag":114,"props":451,"children":452},{"align":87},[453],{"type":25,"value":181},{"type":20,"tag":114,"props":455,"children":456},{"align":87},[457],{"type":20,"tag":123,"props":458,"children":460},{"className":459},[],[461],{"type":25,"value":190},{"type":20,"tag":114,"props":463,"children":464},{"align":87},[465],{"type":25,"value":466},"Parity enable",{"type":20,"tag":114,"props":468,"children":469},{"align":87},[470,475],{"type":20,"tag":123,"props":471,"children":473},{"className":472},[],[474],{"type":25,"value":302},{"type":25,"value":476}," = parity enabled",{"type":20,"tag":81,"props":478,"children":479},{},[480,484,492,497],{"type":20,"tag":114,"props":481,"children":482},{"align":87},[483],{"type":25,"value":213},{"type":20,"tag":114,"props":485,"children":486},{"align":87},[487],{"type":20,"tag":123,"props":488,"children":490},{"className":489},[],[491],{"type":25,"value":222},{"type":20,"tag":114,"props":493,"children":494},{"align":87},[495],{"type":25,"value":496},"Even parity select",{"type":20,"tag":114,"props":498,"children":499},{"align":87},[500,505,507,512],{"type":20,"tag":123,"props":501,"children":503},{"className":502},[],[504],{"type":25,"value":302},{"type":25,"value":506}," = even parity, ",{"type":20,"tag":123,"props":508,"children":510},{"className":509},[],[511],{"type":25,"value":333},{"type":25,"value":513}," = odd parity",{"type":20,"tag":81,"props":515,"children":516},{},[517,522,531,536],{"type":20,"tag":114,"props":518,"children":519},{"align":87},[520],{"type":25,"value":521},"3-2",{"type":20,"tag":114,"props":523,"children":524},{"align":87},[525],{"type":20,"tag":123,"props":526,"children":528},{"className":527},[],[529],{"type":25,"value":530},"$0C",{"type":20,"tag":114,"props":532,"children":533},{"align":87},[534],{"type":25,"value":535},"Character length",{"type":20,"tag":114,"props":537,"children":538},{"align":87},[539,544,546,551,553,558,560,565],{"type":20,"tag":123,"props":540,"children":542},{"className":541},[],[543],{"type":25,"value":420},{"type":25,"value":545}," = 5 bits, ",{"type":20,"tag":123,"props":547,"children":549},{"className":548},[],[550],{"type":25,"value":428},{"type":25,"value":552}," = 6 bits, ",{"type":20,"tag":123,"props":554,"children":556},{"className":555},[],[557],{"type":25,"value":436},{"type":25,"value":559}," = 7 bits, ",{"type":20,"tag":123,"props":561,"children":563},{"className":562},[],[564],{"type":25,"value":444},{"type":25,"value":566}," = 8 bits",{"type":20,"tag":81,"props":568,"children":569},{},[570,575,584,589],{"type":20,"tag":114,"props":571,"children":572},{"align":87},[573],{"type":25,"value":574},"1-0",{"type":20,"tag":114,"props":576,"children":577},{"align":87},[578],{"type":20,"tag":123,"props":579,"children":581},{"className":580},[],[582],{"type":25,"value":583},"$03",{"type":20,"tag":114,"props":585,"children":586},{"align":87},[587],{"type":25,"value":588},"Baud rate factor",{"type":20,"tag":114,"props":590,"children":591},{"align":87},[592,597,599,604,606,612,614,619,620,626,627,632,633],{"type":20,"tag":123,"props":593,"children":595},{"className":594},[],[596],{"type":25,"value":420},{"type":25,"value":598}," = sync mode, ",{"type":20,"tag":123,"props":600,"children":602},{"className":601},[],[603],{"type":25,"value":428},{"type":25,"value":605}," = ",{"type":20,"tag":123,"props":607,"children":609},{"className":608},[],[610],{"type":25,"value":611},"1x",{"type":25,"value":613},", ",{"type":20,"tag":123,"props":615,"children":617},{"className":616},[],[618],{"type":25,"value":436},{"type":25,"value":605},{"type":20,"tag":123,"props":621,"children":623},{"className":622},[],[624],{"type":25,"value":625},"16x",{"type":25,"value":613},{"type":20,"tag":123,"props":628,"children":630},{"className":629},[],[631],{"type":25,"value":444},{"type":25,"value":605},{"type":20,"tag":123,"props":634,"children":636},{"className":635},[],[637],{"type":25,"value":638},"64x",{"type":20,"tag":66,"props":640,"children":642},{"id":641},"status-register-flags",[643],{"type":25,"value":644},"Status register flags",{"type":20,"tag":73,"props":646,"children":647},{},[648,667],{"type":20,"tag":77,"props":649,"children":650},{},[651],{"type":20,"tag":81,"props":652,"children":653},{},[654,658,662],{"type":20,"tag":85,"props":655,"children":656},{"align":87},[657],{"type":25,"value":90},{"type":20,"tag":85,"props":659,"children":660},{"align":87},[661],{"type":25,"value":95},{"type":20,"tag":85,"props":663,"children":664},{"align":87},[665],{"type":25,"value":666},"Function",{"type":20,"tag":107,"props":668,"children":669},{},[670,690,710,730,750,770,790,810],{"type":20,"tag":81,"props":671,"children":672},{},[673,677,685],{"type":20,"tag":114,"props":674,"children":675},{"align":87},[676],{"type":25,"value":333},{"type":20,"tag":114,"props":678,"children":679},{"align":87},[680],{"type":20,"tag":123,"props":681,"children":683},{"className":682},[],[684],{"type":25,"value":342},{"type":20,"tag":114,"props":686,"children":687},{"align":87},[688],{"type":25,"value":689},"Transmitter Ready: Goes high when the transmit buffer/register is empty and ready to accept the next data character from the CPU.",{"type":20,"tag":81,"props":691,"children":692},{},[693,697,705],{"type":20,"tag":114,"props":694,"children":695},{"align":87},[696],{"type":25,"value":302},{"type":20,"tag":114,"props":698,"children":699},{"align":87},[700],{"type":20,"tag":123,"props":701,"children":703},{"className":702},[],[704],{"type":25,"value":311},{"type":20,"tag":114,"props":706,"children":707},{"align":87},[708],{"type":25,"value":709},"Receiver Ready: Goes high when the receiver has a character assembled and ready to be read by the CPU.",{"type":20,"tag":81,"props":711,"children":712},{},[713,717,725],{"type":20,"tag":114,"props":714,"children":715},{"align":87},[716],{"type":25,"value":275},{"type":20,"tag":114,"props":718,"children":719},{"align":87},[720],{"type":20,"tag":123,"props":721,"children":723},{"className":722},[],[724],{"type":25,"value":284},{"type":20,"tag":114,"props":726,"children":727},{"align":87},[728],{"type":25,"value":729},"Transmitter Empty: Goes high in synchronous mode when the transmitter has no characters to send and the USART is sending sync characters. In asynchronous mode, it indicates the line has returned to the mark state.",{"type":20,"tag":81,"props":731,"children":732},{},[733,737,745],{"type":20,"tag":114,"props":734,"children":735},{"align":87},[736],{"type":25,"value":240},{"type":20,"tag":114,"props":738,"children":739},{"align":87},[740],{"type":20,"tag":123,"props":741,"children":743},{"className":742},[],[744],{"type":25,"value":249},{"type":20,"tag":114,"props":746,"children":747},{"align":87},[748],{"type":25,"value":749},"Parity Error: Goes high if the received data character does not match the parity selected by the mode instruction.",{"type":20,"tag":81,"props":751,"children":752},{},[753,757,765],{"type":20,"tag":114,"props":754,"children":755},{"align":87},[756],{"type":25,"value":213},{"type":20,"tag":114,"props":758,"children":759},{"align":87},[760],{"type":20,"tag":123,"props":761,"children":763},{"className":762},[],[764],{"type":25,"value":222},{"type":20,"tag":114,"props":766,"children":767},{"align":87},[768],{"type":25,"value":769},"Overrun Error: Goes high if the CPU does not read the previous character before the next one is received, causing data loss.",{"type":20,"tag":81,"props":771,"children":772},{},[773,777,785],{"type":20,"tag":114,"props":774,"children":775},{"align":87},[776],{"type":25,"value":181},{"type":20,"tag":114,"props":778,"children":779},{"align":87},[780],{"type":20,"tag":123,"props":781,"children":783},{"className":782},[],[784],{"type":25,"value":190},{"type":20,"tag":114,"props":786,"children":787},{"align":87},[788],{"type":25,"value":789},"Framing Error: Goes high in asynchronous mode if the stop bit of a received character is missing or invalid.",{"type":20,"tag":81,"props":791,"children":792},{},[793,797,805],{"type":20,"tag":114,"props":794,"children":795},{"align":87},[796],{"type":25,"value":154},{"type":20,"tag":114,"props":798,"children":799},{"align":87},[800],{"type":20,"tag":123,"props":801,"children":803},{"className":802},[],[804],{"type":25,"value":163},{"type":20,"tag":114,"props":806,"children":807},{"align":87},[808],{"type":25,"value":809},"Sync Detect / Break Detect: Indicates the detection of the sync character in synchronous mode, or a break condition in asynchronous mode.",{"type":20,"tag":81,"props":811,"children":812},{},[813,817,825],{"type":20,"tag":114,"props":814,"children":815},{"align":87},[816],{"type":25,"value":118},{"type":20,"tag":114,"props":818,"children":819},{"align":87},[820],{"type":20,"tag":123,"props":821,"children":823},{"className":822},[],[824],{"type":25,"value":128},{"type":20,"tag":114,"props":826,"children":827},{"align":87},[828],{"type":25,"value":829},"Data Set Ready: Reflects the inverted status of the active-low DSR input pin from the modem or peripheral device.",{"type":20,"tag":54,"props":831,"children":833},{"id":832},"hardware-initialisation",[834],{"type":25,"value":835},"Hardware Initialisation",{"type":20,"tag":21,"props":837,"children":838},{},[839,841,847,849,855],{"type":25,"value":840},"Before the modem can do anything, the 8251 needs to be initialized and the ",{"type":20,"tag":123,"props":842,"children":844},{"className":843},[],[845],{"type":25,"value":846},"HW_INIT",{"type":25,"value":848}," routine at ",{"type":20,"tag":123,"props":850,"children":852},{"className":851},[],[853],{"type":25,"value":854},"$1424",{"type":25,"value":856}," does just that:",{"type":20,"tag":858,"props":859,"children":864},"pre",{"className":860,"code":861,"language":862,"meta":863,"style":863},"language-z80 shiki shiki-themes everforest-light dracula","HW_INIT:\n    LD A,$82            ; Hunt mode + DTR asserted\n    OUT ($FF),A         ; Write to 8251 command register\n    RES 5,(IY+$01)      ; Clear Spectrum's \"new key\" flag\n    LD A,$40            ; Internal reset command \n    OUT ($FF),A         ; Reset the 8251\n    ; ... timing NOPs ...\n    XOR A\n    OUT ($FE),A         ; Set border to black\n    LD A,(IX+$07)       ; Load configured mode register value\n    OUT ($FF),A         ; Write mode to 8251\n    LD (IX+$1B),$64     ; Set idle timeout to 100 (decimal)\n","z80","",[865],{"type":20,"tag":123,"props":866,"children":867},{"__ignoreMap":863},[868,879,888,897,906,915,924,933,942,951,960,969],{"type":20,"tag":869,"props":870,"children":873},"span",{"class":871,"line":872},"line",1,[874],{"type":20,"tag":869,"props":875,"children":876},{},[877],{"type":25,"value":878},"HW_INIT:\n",{"type":20,"tag":869,"props":880,"children":882},{"class":871,"line":881},2,[883],{"type":20,"tag":869,"props":884,"children":885},{},[886],{"type":25,"value":887},"    LD A,$82            ; Hunt mode + DTR asserted\n",{"type":20,"tag":869,"props":889,"children":891},{"class":871,"line":890},3,[892],{"type":20,"tag":869,"props":893,"children":894},{},[895],{"type":25,"value":896},"    OUT ($FF),A         ; Write to 8251 command register\n",{"type":20,"tag":869,"props":898,"children":900},{"class":871,"line":899},4,[901],{"type":20,"tag":869,"props":902,"children":903},{},[904],{"type":25,"value":905},"    RES 5,(IY+$01)      ; Clear Spectrum's \"new key\" flag\n",{"type":20,"tag":869,"props":907,"children":909},{"class":871,"line":908},5,[910],{"type":20,"tag":869,"props":911,"children":912},{},[913],{"type":25,"value":914},"    LD A,$40            ; Internal reset command \n",{"type":20,"tag":869,"props":916,"children":918},{"class":871,"line":917},6,[919],{"type":20,"tag":869,"props":920,"children":921},{},[922],{"type":25,"value":923},"    OUT ($FF),A         ; Reset the 8251\n",{"type":20,"tag":869,"props":925,"children":927},{"class":871,"line":926},7,[928],{"type":20,"tag":869,"props":929,"children":930},{},[931],{"type":25,"value":932},"    ; ... timing NOPs ...\n",{"type":20,"tag":869,"props":934,"children":936},{"class":871,"line":935},8,[937],{"type":20,"tag":869,"props":938,"children":939},{},[940],{"type":25,"value":941},"    XOR A\n",{"type":20,"tag":869,"props":943,"children":945},{"class":871,"line":944},9,[946],{"type":20,"tag":869,"props":947,"children":948},{},[949],{"type":25,"value":950},"    OUT ($FE),A         ; Set border to black\n",{"type":20,"tag":869,"props":952,"children":954},{"class":871,"line":953},10,[955],{"type":20,"tag":869,"props":956,"children":957},{},[958],{"type":25,"value":959},"    LD A,(IX+$07)       ; Load configured mode register value\n",{"type":20,"tag":869,"props":961,"children":963},{"class":871,"line":962},11,[964],{"type":20,"tag":869,"props":965,"children":966},{},[967],{"type":25,"value":968},"    OUT ($FF),A         ; Write mode to 8251\n",{"type":20,"tag":869,"props":970,"children":972},{"class":871,"line":971},12,[973],{"type":20,"tag":869,"props":974,"children":975},{},[976],{"type":25,"value":977},"    LD (IX+$1B),$64     ; Set idle timeout to 100 (decimal)\n",{"type":20,"tag":21,"props":979,"children":980},{},[981],{"type":25,"value":982},"At first glance this looks like it sets the 8251 into \"hunt mode\" via $82 which would use the shift register to find SYN bytes... BUT we're actually going to be using async so why do this? To flip the 8251 out of any pending state so that the $40 reset command that follows will work.",{"type":20,"tag":21,"props":984,"children":985},{},[986],{"type":25,"value":987},"Once it sees that reset it knows the next byte will be the actual configuration from IX+$07 which is $7B for our async 7-bit data, even parity, 1 stop bit, 64× clock mode.",{"type":20,"tag":21,"props":989,"children":990},{},[991],{"type":25,"value":992},"The IX register points to a table full of state and configuration the ROM uses extensively to save swapping registers a bunch.",{"type":20,"tag":54,"props":994,"children":996},{"id":995},"the-ix-table",[997],{"type":25,"value":998},"The IX Table",{"type":20,"tag":73,"props":1000,"children":1001},{},[1002,1024],{"type":20,"tag":77,"props":1003,"children":1004},{},[1005],{"type":20,"tag":81,"props":1006,"children":1007},{},[1008,1014,1019],{"type":20,"tag":85,"props":1009,"children":1011},{"align":1010},"center",[1012],{"type":25,"value":1013},"Offset",{"type":20,"tag":85,"props":1015,"children":1016},{"align":1010},[1017],{"type":25,"value":1018},"Default",{"type":20,"tag":85,"props":1020,"children":1021},{},[1022],{"type":25,"value":1023},"Purpose",{"type":20,"tag":107,"props":1025,"children":1026},{},[1027,1052,1077,1111,1136,1162,1188,1214,1240,1266,1291,1316,1341,1366,1391,1416,1441,1466,1491,1517,1542,1567,1592,1616,1641,1666,1691,1716,1755,1780,1805,1830,1856,1882,1907,1932,1957,1982,2007,2038,2063,2093,2118,2149,2175],{"type":20,"tag":81,"props":1028,"children":1029},{},[1030,1039,1047],{"type":20,"tag":114,"props":1031,"children":1032},{"align":1010},[1033],{"type":20,"tag":123,"props":1034,"children":1036},{"className":1035},[],[1037],{"type":25,"value":1038},"+$00",{"type":20,"tag":114,"props":1040,"children":1041},{"align":1010},[1042],{"type":20,"tag":123,"props":1043,"children":1045},{"className":1044},[],[1046],{"type":25,"value":406},{"type":20,"tag":114,"props":1048,"children":1049},{},[1050],{"type":25,"value":1051},"Splash-screen tail byte (not used as IX data)",{"type":20,"tag":81,"props":1053,"children":1054},{},[1055,1064,1072],{"type":20,"tag":114,"props":1056,"children":1057},{"align":1010},[1058],{"type":20,"tag":123,"props":1059,"children":1061},{"className":1060},[],[1062],{"type":25,"value":1063},"+$01",{"type":20,"tag":114,"props":1065,"children":1066},{"align":1010},[1067],{"type":20,"tag":123,"props":1068,"children":1070},{"className":1069},[],[1071],{"type":25,"value":583},{"type":20,"tag":114,"props":1073,"children":1074},{},[1075],{"type":25,"value":1076},"Splash-screen tail byte",{"type":20,"tag":81,"props":1078,"children":1079},{},[1080,1089,1098],{"type":20,"tag":114,"props":1081,"children":1082},{"align":1010},[1083],{"type":20,"tag":123,"props":1084,"children":1086},{"className":1085},[],[1087],{"type":25,"value":1088},"+$02",{"type":20,"tag":114,"props":1090,"children":1091},{"align":1010},[1092],{"type":20,"tag":123,"props":1093,"children":1095},{"className":1094},[],[1096],{"type":25,"value":1097},"$58",{"type":20,"tag":114,"props":1099,"children":1100},{},[1101,1103,1109],{"type":25,"value":1102},"Splash-screen tail byte (",{"type":20,"tag":123,"props":1104,"children":1106},{"className":1105},[],[1107],{"type":25,"value":1108},"'X'",{"type":25,"value":1110},")",{"type":20,"tag":81,"props":1112,"children":1113},{},[1114,1123,1131],{"type":20,"tag":114,"props":1115,"children":1116},{"align":1010},[1117],{"type":20,"tag":123,"props":1118,"children":1120},{"className":1119},[],[1121],{"type":25,"value":1122},"+$03",{"type":20,"tag":114,"props":1124,"children":1125},{"align":1010},[1126],{"type":20,"tag":123,"props":1127,"children":1129},{"className":1128},[],[1130],{"type":25,"value":311},{"type":20,"tag":114,"props":1132,"children":1133},{},[1134],{"type":25,"value":1135},"Ring buffer countdown (high byte)",{"type":20,"tag":81,"props":1137,"children":1138},{},[1139,1148,1157],{"type":20,"tag":114,"props":1140,"children":1141},{"align":1010},[1142],{"type":20,"tag":123,"props":1143,"children":1145},{"className":1144},[],[1146],{"type":25,"value":1147},"+$04",{"type":20,"tag":114,"props":1149,"children":1150},{"align":1010},[1151],{"type":20,"tag":123,"props":1152,"children":1154},{"className":1153},[],[1155],{"type":25,"value":1156},"$FF",{"type":20,"tag":114,"props":1158,"children":1159},{},[1160],{"type":25,"value":1161},"Ring buffer size (255)",{"type":20,"tag":81,"props":1163,"children":1164},{},[1165,1174,1183],{"type":20,"tag":114,"props":1166,"children":1167},{"align":1010},[1168],{"type":20,"tag":123,"props":1169,"children":1171},{"className":1170},[],[1172],{"type":25,"value":1173},"+$05",{"type":20,"tag":114,"props":1175,"children":1176},{"align":1010},[1177],{"type":20,"tag":123,"props":1178,"children":1180},{"className":1179},[],[1181],{"type":25,"value":1182},"$00",{"type":20,"tag":114,"props":1184,"children":1185},{},[1186],{"type":25,"value":1187},"Unused / reserved",{"type":20,"tag":81,"props":1189,"children":1190},{},[1191,1200,1209],{"type":20,"tag":114,"props":1192,"children":1193},{"align":1010},[1194],{"type":20,"tag":123,"props":1195,"children":1197},{"className":1196},[],[1198],{"type":25,"value":1199},"+$06",{"type":20,"tag":114,"props":1201,"children":1202},{"align":1010},[1203],{"type":20,"tag":123,"props":1204,"children":1206},{"className":1205},[],[1207],{"type":25,"value":1208},"$60",{"type":20,"tag":114,"props":1210,"children":1211},{},[1212],{"type":25,"value":1213},"Device flags (bits 5+6 set at boot: TX busy + b6)",{"type":20,"tag":81,"props":1215,"children":1216},{},[1217,1226,1235],{"type":20,"tag":114,"props":1218,"children":1219},{"align":1010},[1220],{"type":20,"tag":123,"props":1221,"children":1223},{"className":1222},[],[1224],{"type":25,"value":1225},"+$07",{"type":20,"tag":114,"props":1227,"children":1228},{"align":1010},[1229],{"type":20,"tag":123,"props":1230,"children":1232},{"className":1231},[],[1233],{"type":25,"value":1234},"$7B",{"type":20,"tag":114,"props":1236,"children":1237},{},[1238],{"type":25,"value":1239},"8251 mode register: 7-bit data, even parity, 1 stop bit, 64× clock",{"type":20,"tag":81,"props":1241,"children":1242},{},[1243,1252,1261],{"type":20,"tag":114,"props":1244,"children":1245},{"align":1010},[1246],{"type":20,"tag":123,"props":1247,"children":1249},{"className":1248},[],[1250],{"type":25,"value":1251},"+$08",{"type":20,"tag":114,"props":1253,"children":1254},{"align":1010},[1255],{"type":20,"tag":123,"props":1256,"children":1258},{"className":1257},[],[1259],{"type":25,"value":1260},"$15",{"type":20,"tag":114,"props":1262,"children":1263},{},[1264],{"type":25,"value":1265},"8251 command register: RxEn/TxEn/DTR, RTS=0 (VTX ROM paged in)",{"type":20,"tag":81,"props":1267,"children":1268},{},[1269,1278,1286],{"type":20,"tag":114,"props":1270,"children":1271},{"align":1010},[1272],{"type":20,"tag":123,"props":1273,"children":1275},{"className":1274},[],[1276],{"type":25,"value":1277},"+$09",{"type":20,"tag":114,"props":1279,"children":1280},{"align":1010},[1281],{"type":20,"tag":123,"props":1282,"children":1284},{"className":1283},[],[1285],{"type":25,"value":1182},{"type":20,"tag":114,"props":1287,"children":1288},{},[1289],{"type":25,"value":1290},"Keyboard / input state flags",{"type":20,"tag":81,"props":1292,"children":1293},{},[1294,1303,1311],{"type":20,"tag":114,"props":1295,"children":1296},{"align":1010},[1297],{"type":20,"tag":123,"props":1298,"children":1300},{"className":1299},[],[1301],{"type":25,"value":1302},"+$0A",{"type":20,"tag":114,"props":1304,"children":1305},{"align":1010},[1306],{"type":20,"tag":123,"props":1307,"children":1309},{"className":1308},[],[1310],{"type":25,"value":1182},{"type":20,"tag":114,"props":1312,"children":1313},{},[1314],{"type":25,"value":1315},"Prestel frame parser state",{"type":20,"tag":81,"props":1317,"children":1318},{},[1319,1328,1336],{"type":20,"tag":114,"props":1320,"children":1321},{"align":1010},[1322],{"type":20,"tag":123,"props":1323,"children":1325},{"className":1324},[],[1326],{"type":25,"value":1327},"+$0B",{"type":20,"tag":114,"props":1329,"children":1330},{"align":1010},[1331],{"type":20,"tag":123,"props":1332,"children":1334},{"className":1333},[],[1335],{"type":25,"value":1182},{"type":20,"tag":114,"props":1337,"children":1338},{},[1339],{"type":25,"value":1340},"Return code (0 = continue, 1 = BREAK, 2 = timeout, 3 = carrier lost, 4 = error, 5 = frame complete, 6 = retry, 7 = specific)",{"type":20,"tag":81,"props":1342,"children":1343},{},[1344,1353,1361],{"type":20,"tag":114,"props":1345,"children":1346},{"align":1010},[1347],{"type":20,"tag":123,"props":1348,"children":1350},{"className":1349},[],[1351],{"type":25,"value":1352},"+$0C",{"type":20,"tag":114,"props":1354,"children":1355},{"align":1010},[1356],{"type":20,"tag":123,"props":1357,"children":1359},{"className":1358},[],[1360],{"type":25,"value":1182},{"type":20,"tag":114,"props":1362,"children":1363},{},[1364],{"type":25,"value":1365},"Cursor row",{"type":20,"tag":81,"props":1367,"children":1368},{},[1369,1378,1386],{"type":20,"tag":114,"props":1370,"children":1371},{"align":1010},[1372],{"type":20,"tag":123,"props":1373,"children":1375},{"className":1374},[],[1376],{"type":25,"value":1377},"+$0D",{"type":20,"tag":114,"props":1379,"children":1380},{"align":1010},[1381],{"type":20,"tag":123,"props":1382,"children":1384},{"className":1383},[],[1385],{"type":25,"value":1182},{"type":20,"tag":114,"props":1387,"children":1388},{},[1389],{"type":25,"value":1390},"Cursor column",{"type":20,"tag":81,"props":1392,"children":1393},{},[1394,1403,1411],{"type":20,"tag":114,"props":1395,"children":1396},{"align":1010},[1397],{"type":20,"tag":123,"props":1398,"children":1400},{"className":1399},[],[1401],{"type":25,"value":1402},"+$0E",{"type":20,"tag":114,"props":1404,"children":1405},{"align":1010},[1406],{"type":20,"tag":123,"props":1407,"children":1409},{"className":1408},[],[1410],{"type":25,"value":1182},{"type":20,"tag":114,"props":1412,"children":1413},{},[1414],{"type":25,"value":1415},"Last row rendered",{"type":20,"tag":81,"props":1417,"children":1418},{},[1419,1428,1436],{"type":20,"tag":114,"props":1420,"children":1421},{"align":1010},[1422],{"type":20,"tag":123,"props":1423,"children":1425},{"className":1424},[],[1426],{"type":25,"value":1427},"+$0F",{"type":20,"tag":114,"props":1429,"children":1430},{"align":1010},[1431],{"type":20,"tag":123,"props":1432,"children":1434},{"className":1433},[],[1435],{"type":25,"value":1182},{"type":20,"tag":114,"props":1437,"children":1438},{},[1439],{"type":25,"value":1440},"Last column rendered",{"type":20,"tag":81,"props":1442,"children":1443},{},[1444,1453,1461],{"type":20,"tag":114,"props":1445,"children":1446},{"align":1010},[1447],{"type":20,"tag":123,"props":1448,"children":1450},{"className":1449},[],[1451],{"type":25,"value":1452},"+$10",{"type":20,"tag":114,"props":1454,"children":1455},{"align":1010},[1456],{"type":20,"tag":123,"props":1457,"children":1459},{"className":1458},[],[1460],{"type":25,"value":1182},{"type":20,"tag":114,"props":1462,"children":1463},{},[1464],{"type":25,"value":1465},"Previous line number (dirty-line tracking)",{"type":20,"tag":81,"props":1467,"children":1468},{},[1469,1478,1486],{"type":20,"tag":114,"props":1470,"children":1471},{"align":1010},[1472],{"type":20,"tag":123,"props":1473,"children":1475},{"className":1474},[],[1476],{"type":25,"value":1477},"+$11",{"type":20,"tag":114,"props":1479,"children":1480},{"align":1010},[1481],{"type":20,"tag":123,"props":1482,"children":1484},{"className":1483},[],[1485],{"type":25,"value":1182},{"type":20,"tag":114,"props":1487,"children":1488},{},[1489],{"type":25,"value":1490},"Display attribute state (low byte - EXX pair)",{"type":20,"tag":81,"props":1492,"children":1493},{},[1494,1503,1512],{"type":20,"tag":114,"props":1495,"children":1496},{"align":1010},[1497],{"type":20,"tag":123,"props":1498,"children":1500},{"className":1499},[],[1501],{"type":25,"value":1502},"+$12",{"type":20,"tag":114,"props":1504,"children":1505},{"align":1010},[1506],{"type":20,"tag":123,"props":1507,"children":1509},{"className":1508},[],[1510],{"type":25,"value":1511},"$47",{"type":20,"tag":114,"props":1513,"children":1514},{},[1515],{"type":25,"value":1516},"Display attribute state (high): bright white ink on black paper",{"type":20,"tag":81,"props":1518,"children":1519},{},[1520,1529,1537],{"type":20,"tag":114,"props":1521,"children":1522},{"align":1010},[1523],{"type":20,"tag":123,"props":1524,"children":1526},{"className":1525},[],[1527],{"type":25,"value":1528},"+$13",{"type":20,"tag":114,"props":1530,"children":1531},{"align":1010},[1532],{"type":20,"tag":123,"props":1533,"children":1535},{"className":1534},[],[1536],{"type":25,"value":1182},{"type":20,"tag":114,"props":1538,"children":1539},{},[1540],{"type":25,"value":1541},"Saved attribute state (low)",{"type":20,"tag":81,"props":1543,"children":1544},{},[1545,1554,1562],{"type":20,"tag":114,"props":1546,"children":1547},{"align":1010},[1548],{"type":20,"tag":123,"props":1549,"children":1551},{"className":1550},[],[1552],{"type":25,"value":1553},"+$14",{"type":20,"tag":114,"props":1555,"children":1556},{"align":1010},[1557],{"type":20,"tag":123,"props":1558,"children":1560},{"className":1559},[],[1561],{"type":25,"value":1182},{"type":20,"tag":114,"props":1563,"children":1564},{},[1565],{"type":25,"value":1566},"Saved attribute state (high)",{"type":20,"tag":81,"props":1568,"children":1569},{},[1570,1579,1587],{"type":20,"tag":114,"props":1571,"children":1572},{"align":1010},[1573],{"type":20,"tag":123,"props":1574,"children":1576},{"className":1575},[],[1577],{"type":25,"value":1578},"+$15",{"type":20,"tag":114,"props":1580,"children":1581},{"align":1010},[1582],{"type":20,"tag":123,"props":1583,"children":1585},{"className":1584},[],[1586],{"type":25,"value":1182},{"type":20,"tag":114,"props":1588,"children":1589},{},[1590],{"type":25,"value":1591},"Current display attribute",{"type":20,"tag":81,"props":1593,"children":1594},{},[1595,1604,1612],{"type":20,"tag":114,"props":1596,"children":1597},{"align":1010},[1598],{"type":20,"tag":123,"props":1599,"children":1601},{"className":1600},[],[1602],{"type":25,"value":1603},"+$16",{"type":20,"tag":114,"props":1605,"children":1606},{"align":1010},[1607],{"type":20,"tag":123,"props":1608,"children":1610},{"className":1609},[],[1611],{"type":25,"value":1182},{"type":20,"tag":114,"props":1613,"children":1614},{},[1615],{"type":25,"value":1187},{"type":20,"tag":81,"props":1617,"children":1618},{},[1619,1628,1636],{"type":20,"tag":114,"props":1620,"children":1621},{"align":1010},[1622],{"type":20,"tag":123,"props":1623,"children":1625},{"className":1624},[],[1626],{"type":25,"value":1627},"+$17",{"type":20,"tag":114,"props":1629,"children":1630},{"align":1010},[1631],{"type":20,"tag":123,"props":1632,"children":1634},{"className":1633},[],[1635],{"type":25,"value":1182},{"type":20,"tag":114,"props":1637,"children":1638},{},[1639],{"type":25,"value":1640},"Saved attribute for restore",{"type":20,"tag":81,"props":1642,"children":1643},{},[1644,1653,1661],{"type":20,"tag":114,"props":1645,"children":1646},{"align":1010},[1647],{"type":20,"tag":123,"props":1648,"children":1650},{"className":1649},[],[1651],{"type":25,"value":1652},"+$18",{"type":20,"tag":114,"props":1654,"children":1655},{"align":1010},[1656],{"type":20,"tag":123,"props":1657,"children":1659},{"className":1658},[],[1660],{"type":25,"value":1182},{"type":20,"tag":114,"props":1662,"children":1663},{},[1664],{"type":25,"value":1665},"Previous keyboard scan result",{"type":20,"tag":81,"props":1667,"children":1668},{},[1669,1678,1686],{"type":20,"tag":114,"props":1670,"children":1671},{"align":1010},[1672],{"type":20,"tag":123,"props":1673,"children":1675},{"className":1674},[],[1676],{"type":25,"value":1677},"+$19",{"type":20,"tag":114,"props":1679,"children":1680},{"align":1010},[1681],{"type":20,"tag":123,"props":1682,"children":1684},{"className":1683},[],[1685],{"type":25,"value":1182},{"type":20,"tag":114,"props":1687,"children":1688},{},[1689],{"type":25,"value":1690},"Carrier-detect timeout (low)",{"type":20,"tag":81,"props":1692,"children":1693},{},[1694,1703,1711],{"type":20,"tag":114,"props":1695,"children":1696},{"align":1010},[1697],{"type":20,"tag":123,"props":1698,"children":1700},{"className":1699},[],[1701],{"type":25,"value":1702},"+$1A",{"type":20,"tag":114,"props":1704,"children":1705},{"align":1010},[1706],{"type":20,"tag":123,"props":1707,"children":1709},{"className":1708},[],[1710],{"type":25,"value":1182},{"type":20,"tag":114,"props":1712,"children":1713},{},[1714],{"type":25,"value":1715},"Carrier-detect timeout (high)",{"type":20,"tag":81,"props":1717,"children":1718},{},[1719,1728,1736],{"type":20,"tag":114,"props":1720,"children":1721},{"align":1010},[1722],{"type":20,"tag":123,"props":1723,"children":1725},{"className":1724},[],[1726],{"type":25,"value":1727},"+$1B",{"type":20,"tag":114,"props":1729,"children":1730},{"align":1010},[1731],{"type":20,"tag":123,"props":1732,"children":1734},{"className":1733},[],[1735],{"type":25,"value":1182},{"type":20,"tag":114,"props":1737,"children":1738},{},[1739,1741,1747,1749,1754],{"type":25,"value":1740},"Idle timeout counter (set to ",{"type":20,"tag":123,"props":1742,"children":1744},{"className":1743},[],[1745],{"type":25,"value":1746},"$64",{"type":25,"value":1748}," by ",{"type":20,"tag":123,"props":1750,"children":1752},{"className":1751},[],[1753],{"type":25,"value":846},{"type":25,"value":1110},{"type":20,"tag":81,"props":1756,"children":1757},{},[1758,1767,1775],{"type":20,"tag":114,"props":1759,"children":1760},{"align":1010},[1761],{"type":20,"tag":123,"props":1762,"children":1764},{"className":1763},[],[1765],{"type":25,"value":1766},"+$1C",{"type":20,"tag":114,"props":1768,"children":1769},{"align":1010},[1770],{"type":20,"tag":123,"props":1771,"children":1773},{"className":1772},[],[1774],{"type":25,"value":1156},{"type":20,"tag":114,"props":1776,"children":1777},{},[1778],{"type":25,"value":1779},"Prestel session scratchpad start",{"type":20,"tag":81,"props":1781,"children":1782},{},[1783,1792,1800],{"type":20,"tag":114,"props":1784,"children":1785},{"align":1010},[1786],{"type":20,"tag":123,"props":1787,"children":1789},{"className":1788},[],[1790],{"type":25,"value":1791},"+$2B",{"type":20,"tag":114,"props":1793,"children":1794},{"align":1010},[1795],{"type":20,"tag":123,"props":1796,"children":1798},{"className":1797},[],[1799],{"type":25,"value":1156},{"type":20,"tag":114,"props":1801,"children":1802},{},[1803],{"type":25,"value":1804},"Prestel session scratchpad end",{"type":20,"tag":81,"props":1806,"children":1807},{},[1808,1817,1825],{"type":20,"tag":114,"props":1809,"children":1810},{"align":1010},[1811],{"type":20,"tag":123,"props":1812,"children":1814},{"className":1813},[],[1815],{"type":25,"value":1816},"+$2C",{"type":20,"tag":114,"props":1818,"children":1819},{"align":1010},[1820],{"type":20,"tag":123,"props":1821,"children":1823},{"className":1822},[],[1824],{"type":25,"value":1182},{"type":20,"tag":114,"props":1826,"children":1827},{},[1828],{"type":25,"value":1829},"Prestel frame repeat count",{"type":20,"tag":81,"props":1831,"children":1832},{},[1833,1842,1851],{"type":20,"tag":114,"props":1834,"children":1835},{"align":1010},[1836],{"type":20,"tag":123,"props":1837,"children":1839},{"className":1838},[],[1840],{"type":25,"value":1841},"+$2D",{"type":20,"tag":114,"props":1843,"children":1844},{"align":1010},[1845],{"type":20,"tag":123,"props":1846,"children":1848},{"className":1847},[],[1849],{"type":25,"value":1850},"$17",{"type":20,"tag":114,"props":1852,"children":1853},{},[1854],{"type":25,"value":1855},"Prestel line retry count (23)",{"type":20,"tag":81,"props":1857,"children":1858},{},[1859,1868,1877],{"type":20,"tag":114,"props":1860,"children":1861},{"align":1010},[1862],{"type":20,"tag":123,"props":1863,"children":1865},{"className":1864},[],[1866],{"type":25,"value":1867},"+$2E",{"type":20,"tag":114,"props":1869,"children":1870},{"align":1010},[1871],{"type":20,"tag":123,"props":1872,"children":1874},{"className":1873},[],[1875],{"type":25,"value":1876},"$05",{"type":20,"tag":114,"props":1878,"children":1879},{},[1880],{"type":25,"value":1881},"Prestel attempt counter",{"type":20,"tag":81,"props":1883,"children":1884},{},[1885,1894,1902],{"type":20,"tag":114,"props":1886,"children":1887},{"align":1010},[1888],{"type":20,"tag":123,"props":1889,"children":1891},{"className":1890},[],[1892],{"type":25,"value":1893},"+$2F",{"type":20,"tag":114,"props":1895,"children":1896},{"align":1010},[1897],{"type":20,"tag":123,"props":1898,"children":1900},{"className":1899},[],[1901],{"type":25,"value":1182},{"type":20,"tag":114,"props":1903,"children":1904},{},[1905],{"type":25,"value":1906},"Prestel data pointer (low)",{"type":20,"tag":81,"props":1908,"children":1909},{},[1910,1919,1927],{"type":20,"tag":114,"props":1911,"children":1912},{"align":1010},[1913],{"type":20,"tag":123,"props":1914,"children":1916},{"className":1915},[],[1917],{"type":25,"value":1918},"+$30",{"type":20,"tag":114,"props":1920,"children":1921},{"align":1010},[1922],{"type":20,"tag":123,"props":1923,"children":1925},{"className":1924},[],[1926],{"type":25,"value":1182},{"type":20,"tag":114,"props":1928,"children":1929},{},[1930],{"type":25,"value":1931},"Prestel data pointer (high)",{"type":20,"tag":81,"props":1933,"children":1934},{},[1935,1944,1952],{"type":20,"tag":114,"props":1936,"children":1937},{"align":1010},[1938],{"type":20,"tag":123,"props":1939,"children":1941},{"className":1940},[],[1942],{"type":25,"value":1943},"+$31",{"type":20,"tag":114,"props":1945,"children":1946},{"align":1010},[1947],{"type":20,"tag":123,"props":1948,"children":1950},{"className":1949},[],[1951],{"type":25,"value":1182},{"type":20,"tag":114,"props":1953,"children":1954},{},[1955],{"type":25,"value":1956},"Prestel shift state",{"type":20,"tag":81,"props":1958,"children":1959},{},[1960,1969,1977],{"type":20,"tag":114,"props":1961,"children":1962},{"align":1010},[1963],{"type":20,"tag":123,"props":1964,"children":1966},{"className":1965},[],[1967],{"type":25,"value":1968},"+$32",{"type":20,"tag":114,"props":1970,"children":1971},{"align":1010},[1972],{"type":20,"tag":123,"props":1973,"children":1975},{"className":1974},[],[1976],{"type":25,"value":1182},{"type":20,"tag":114,"props":1978,"children":1979},{},[1980],{"type":25,"value":1981},"Prestel parser flags",{"type":20,"tag":81,"props":1983,"children":1984},{},[1985,1994,2002],{"type":20,"tag":114,"props":1986,"children":1987},{"align":1010},[1988],{"type":20,"tag":123,"props":1989,"children":1991},{"className":1990},[],[1992],{"type":25,"value":1993},"+$41",{"type":20,"tag":114,"props":1995,"children":1996},{"align":1010},[1997],{"type":20,"tag":123,"props":1998,"children":2000},{"className":1999},[],[2001],{"type":25,"value":1876},{"type":20,"tag":114,"props":2003,"children":2004},{},[2005],{"type":25,"value":2006},"Prestel max attempts (5)",{"type":20,"tag":81,"props":2008,"children":2009},{},[2010,2019,2027],{"type":20,"tag":114,"props":2011,"children":2012},{"align":1010},[2013],{"type":20,"tag":123,"props":2014,"children":2016},{"className":2015},[],[2017],{"type":25,"value":2018},"+$42",{"type":20,"tag":114,"props":2020,"children":2021},{"align":1010},[2022],{"type":20,"tag":123,"props":2023,"children":2025},{"className":2024},[],[2026],{"type":25,"value":1746},{"type":20,"tag":114,"props":2028,"children":2029},{},[2030,2032],{"type":25,"value":2031},"Online timeout (low) - ",{"type":20,"tag":123,"props":2033,"children":2035},{"className":2034},[],[2036],{"type":25,"value":2037},"$0064 = 100",{"type":20,"tag":81,"props":2039,"children":2040},{},[2041,2050,2058],{"type":20,"tag":114,"props":2042,"children":2043},{"align":1010},[2044],{"type":20,"tag":123,"props":2045,"children":2047},{"className":2046},[],[2048],{"type":25,"value":2049},"+$43",{"type":20,"tag":114,"props":2051,"children":2052},{"align":1010},[2053],{"type":20,"tag":123,"props":2054,"children":2056},{"className":2055},[],[2057],{"type":25,"value":1182},{"type":20,"tag":114,"props":2059,"children":2060},{},[2061],{"type":25,"value":2062},"Online timeout (high)",{"type":20,"tag":81,"props":2064,"children":2065},{},[2066,2075,2083],{"type":20,"tag":114,"props":2067,"children":2068},{"align":1010},[2069],{"type":20,"tag":123,"props":2070,"children":2072},{"className":2071},[],[2073],{"type":25,"value":2074},"+$44",{"type":20,"tag":114,"props":2076,"children":2077},{"align":1010},[2078],{"type":20,"tag":123,"props":2079,"children":2081},{"className":2080},[],[2082],{"type":25,"value":1746},{"type":20,"tag":114,"props":2084,"children":2085},{},[2086,2088],{"type":25,"value":2087},"Offline timeout (low) - ",{"type":20,"tag":123,"props":2089,"children":2091},{"className":2090},[],[2092],{"type":25,"value":2037},{"type":20,"tag":81,"props":2094,"children":2095},{},[2096,2105,2113],{"type":20,"tag":114,"props":2097,"children":2098},{"align":1010},[2099],{"type":20,"tag":123,"props":2100,"children":2102},{"className":2101},[],[2103],{"type":25,"value":2104},"+$45",{"type":20,"tag":114,"props":2106,"children":2107},{"align":1010},[2108],{"type":20,"tag":123,"props":2109,"children":2111},{"className":2110},[],[2112],{"type":25,"value":1182},{"type":20,"tag":114,"props":2114,"children":2115},{},[2116],{"type":25,"value":2117},"Offline timeout (high)",{"type":20,"tag":81,"props":2119,"children":2120},{},[2121,2130,2138],{"type":20,"tag":114,"props":2122,"children":2123},{"align":1010},[2124],{"type":20,"tag":123,"props":2125,"children":2127},{"className":2126},[],[2128],{"type":25,"value":2129},"+$46",{"type":20,"tag":114,"props":2131,"children":2132},{"align":1010},[2133],{"type":20,"tag":123,"props":2134,"children":2136},{"className":2135},[],[2137],{"type":25,"value":190},{"type":20,"tag":114,"props":2139,"children":2140},{},[2141,2143],{"type":25,"value":2142},"Character font base (low) - together = ",{"type":20,"tag":123,"props":2144,"children":2146},{"className":2145},[],[2147],{"type":25,"value":2148},"$1B20",{"type":20,"tag":81,"props":2150,"children":2151},{},[2152,2161,2170],{"type":20,"tag":114,"props":2153,"children":2154},{"align":1010},[2155],{"type":20,"tag":123,"props":2156,"children":2158},{"className":2157},[],[2159],{"type":25,"value":2160},"+$47",{"type":20,"tag":114,"props":2162,"children":2163},{"align":1010},[2164],{"type":20,"tag":123,"props":2165,"children":2167},{"className":2166},[],[2168],{"type":25,"value":2169},"$1B",{"type":20,"tag":114,"props":2171,"children":2172},{},[2173],{"type":25,"value":2174},"Character font base (high) - points at ROM font",{"type":20,"tag":81,"props":2176,"children":2177},{},[2178,2187,2195],{"type":20,"tag":114,"props":2179,"children":2180},{"align":1010},[2181],{"type":20,"tag":123,"props":2182,"children":2184},{"className":2183},[],[2185],{"type":25,"value":2186},"+$48",{"type":20,"tag":114,"props":2188,"children":2189},{"align":1010},[2190],{"type":20,"tag":123,"props":2191,"children":2193},{"className":2192},[],[2194],{"type":25,"value":1156},{"type":20,"tag":114,"props":2196,"children":2197},{},[2198],{"type":25,"value":2199},"(Trampoline region begins here - not IX-table data)",{"type":20,"tag":54,"props":2201,"children":2203},{"id":2202},"the-modem-polling-loop",[2204],{"type":25,"value":2205},"The Modem Polling Loop",{"type":20,"tag":21,"props":2207,"children":2208},{},[2209,2211,2217],{"type":25,"value":2210},"The main modem loop at ",{"type":20,"tag":123,"props":2212,"children":2214},{"className":2213},[],[2215],{"type":25,"value":2216},"$13FA",{"type":25,"value":2218}," is where the VTX5000 spends most of its time. It's a straightforward poll-and-dispatch cycle:",{"type":20,"tag":858,"props":2220,"children":2222},{"className":860,"code":2221,"language":862,"meta":863,"style":863},"MODEM_MAIN_LOOP:\n    LD (IX+$0B),$00      ; Clear return code\n    CALL CHECK_TX_READY  ; Send a byte if transmitter is free\n    CALL CHECK_RX_DATA   ; Read a byte if receiver has data\n    LD B,$04\n    CALL RINGBUF_READ    ; Pull from RX ring buffer\n    JR Z,.no_rx_data     ; Nothing? Skip processing\n    CALL PRESTEL_DETECT  ; Check for Prestel frame markers\n    CALL PROCESS_RX_CHAR ; Handle the received character\n.no_rx_data:\n    CALL SCAN_KEYBOARD   ; Check keyboard\n    LD C,(IX+$0B)        ; Read return code\n    LD A,C\n    OR A\n    JR Z,MODEM_MAIN_LOOP ; Code 0: keep looping\n",[2223],{"type":20,"tag":123,"props":2224,"children":2225},{"__ignoreMap":863},[2226,2234,2242,2250,2258,2266,2274,2282,2290,2298,2306,2314,2322,2331,2340],{"type":20,"tag":869,"props":2227,"children":2228},{"class":871,"line":872},[2229],{"type":20,"tag":869,"props":2230,"children":2231},{},[2232],{"type":25,"value":2233},"MODEM_MAIN_LOOP:\n",{"type":20,"tag":869,"props":2235,"children":2236},{"class":871,"line":881},[2237],{"type":20,"tag":869,"props":2238,"children":2239},{},[2240],{"type":25,"value":2241},"    LD (IX+$0B),$00      ; Clear return code\n",{"type":20,"tag":869,"props":2243,"children":2244},{"class":871,"line":890},[2245],{"type":20,"tag":869,"props":2246,"children":2247},{},[2248],{"type":25,"value":2249},"    CALL CHECK_TX_READY  ; Send a byte if transmitter is free\n",{"type":20,"tag":869,"props":2251,"children":2252},{"class":871,"line":899},[2253],{"type":20,"tag":869,"props":2254,"children":2255},{},[2256],{"type":25,"value":2257},"    CALL CHECK_RX_DATA   ; Read a byte if receiver has data\n",{"type":20,"tag":869,"props":2259,"children":2260},{"class":871,"line":908},[2261],{"type":20,"tag":869,"props":2262,"children":2263},{},[2264],{"type":25,"value":2265},"    LD B,$04\n",{"type":20,"tag":869,"props":2267,"children":2268},{"class":871,"line":917},[2269],{"type":20,"tag":869,"props":2270,"children":2271},{},[2272],{"type":25,"value":2273},"    CALL RINGBUF_READ    ; Pull from RX ring buffer\n",{"type":20,"tag":869,"props":2275,"children":2276},{"class":871,"line":926},[2277],{"type":20,"tag":869,"props":2278,"children":2279},{},[2280],{"type":25,"value":2281},"    JR Z,.no_rx_data     ; Nothing? Skip processing\n",{"type":20,"tag":869,"props":2283,"children":2284},{"class":871,"line":935},[2285],{"type":20,"tag":869,"props":2286,"children":2287},{},[2288],{"type":25,"value":2289},"    CALL PRESTEL_DETECT  ; Check for Prestel frame markers\n",{"type":20,"tag":869,"props":2291,"children":2292},{"class":871,"line":944},[2293],{"type":20,"tag":869,"props":2294,"children":2295},{},[2296],{"type":25,"value":2297},"    CALL PROCESS_RX_CHAR ; Handle the received character\n",{"type":20,"tag":869,"props":2299,"children":2300},{"class":871,"line":953},[2301],{"type":20,"tag":869,"props":2302,"children":2303},{},[2304],{"type":25,"value":2305},".no_rx_data:\n",{"type":20,"tag":869,"props":2307,"children":2308},{"class":871,"line":962},[2309],{"type":20,"tag":869,"props":2310,"children":2311},{},[2312],{"type":25,"value":2313},"    CALL SCAN_KEYBOARD   ; Check keyboard\n",{"type":20,"tag":869,"props":2315,"children":2316},{"class":871,"line":971},[2317],{"type":20,"tag":869,"props":2318,"children":2319},{},[2320],{"type":25,"value":2321},"    LD C,(IX+$0B)        ; Read return code\n",{"type":20,"tag":869,"props":2323,"children":2325},{"class":871,"line":2324},13,[2326],{"type":20,"tag":869,"props":2327,"children":2328},{},[2329],{"type":25,"value":2330},"    LD A,C\n",{"type":20,"tag":869,"props":2332,"children":2334},{"class":871,"line":2333},14,[2335],{"type":20,"tag":869,"props":2336,"children":2337},{},[2338],{"type":25,"value":2339},"    OR A\n",{"type":20,"tag":869,"props":2341,"children":2343},{"class":871,"line":2342},15,[2344],{"type":20,"tag":869,"props":2345,"children":2346},{},[2347],{"type":25,"value":2348},"    JR Z,MODEM_MAIN_LOOP ; Code 0: keep looping\n",{"type":20,"tag":21,"props":2350,"children":2351},{},[2352,2354,2360,2362,2368],{"type":25,"value":2353},"Every iteration, it checks for outgoing data, incoming data, and keyboard input. If a return code gets set anywhere (BREAK pressed, timeout, carrier lost, frame complete), the loop exits and returns to the BASIC program via ",{"type":20,"tag":123,"props":2355,"children":2357},{"className":2356},[],[2358],{"type":25,"value":2359},"USR",{"type":25,"value":2361},". The return code in ",{"type":20,"tag":123,"props":2363,"children":2365},{"className":2364},[],[2366],{"type":25,"value":2367},"IX+$0B",{"type":25,"value":2369}," tells BASIC what happened - 0 means keep going, 1 is BREAK, 2 is idle timeout, 3 is carrier lost, and so on.",{"type":20,"tag":21,"props":2371,"children":2372},{},[2373],{"type":25,"value":2374},"This cooperative polling design means nothing ever blocks. There's no interrupt-driven receive, no DMA - just a tight loop checking everything in turn, fast enough at 3.5MHz that nothing gets missed at 1200 baud.",{"type":20,"tag":54,"props":2376,"children":2378},{"id":2377},"transmit",[2379],{"type":25,"value":2380},"Transmit",{"type":20,"tag":21,"props":2382,"children":2383},{},[2384],{"type":25,"value":2385},"The transmit path is simple - check if the 8251's TxRDY flag is set, and if there's data in the TX buffer, send it:",{"type":20,"tag":858,"props":2387,"children":2389},{"className":860,"code":2388,"language":862,"meta":863,"style":863},"CHECK_TX_READY:\n    LD A,(IX+$06)\n    AND $42              ; TX enabled?\n    RET NZ               ; No: return\n    IN A,($FF)           ; Read 8251 status\n    BIT 0,A              ; TxRDY?\n    RET Z                ; Not ready: return\n    LD B,$02             ; Ring buffer type 2 (TX)\n    CALL RINGBUF_READ    ; Read from TX buffer\n    RET Z                ; Empty: return\n    CP $23               ; '#' hash?\n    JR NZ,.not_hash\n    LD A,$5F             ; Replace with underscore\n.not_hash:\n    OUT ($7F),A          ; Transmit byte\n    RET\n",[2390],{"type":20,"tag":123,"props":2391,"children":2392},{"__ignoreMap":863},[2393,2401,2409,2417,2425,2433,2441,2449,2457,2465,2473,2481,2489,2497,2505,2513],{"type":20,"tag":869,"props":2394,"children":2395},{"class":871,"line":872},[2396],{"type":20,"tag":869,"props":2397,"children":2398},{},[2399],{"type":25,"value":2400},"CHECK_TX_READY:\n",{"type":20,"tag":869,"props":2402,"children":2403},{"class":871,"line":881},[2404],{"type":20,"tag":869,"props":2405,"children":2406},{},[2407],{"type":25,"value":2408},"    LD A,(IX+$06)\n",{"type":20,"tag":869,"props":2410,"children":2411},{"class":871,"line":890},[2412],{"type":20,"tag":869,"props":2413,"children":2414},{},[2415],{"type":25,"value":2416},"    AND $42              ; TX enabled?\n",{"type":20,"tag":869,"props":2418,"children":2419},{"class":871,"line":899},[2420],{"type":20,"tag":869,"props":2421,"children":2422},{},[2423],{"type":25,"value":2424},"    RET NZ               ; No: return\n",{"type":20,"tag":869,"props":2426,"children":2427},{"class":871,"line":908},[2428],{"type":20,"tag":869,"props":2429,"children":2430},{},[2431],{"type":25,"value":2432},"    IN A,($FF)           ; Read 8251 status\n",{"type":20,"tag":869,"props":2434,"children":2435},{"class":871,"line":917},[2436],{"type":20,"tag":869,"props":2437,"children":2438},{},[2439],{"type":25,"value":2440},"    BIT 0,A              ; TxRDY?\n",{"type":20,"tag":869,"props":2442,"children":2443},{"class":871,"line":926},[2444],{"type":20,"tag":869,"props":2445,"children":2446},{},[2447],{"type":25,"value":2448},"    RET Z                ; Not ready: return\n",{"type":20,"tag":869,"props":2450,"children":2451},{"class":871,"line":935},[2452],{"type":20,"tag":869,"props":2453,"children":2454},{},[2455],{"type":25,"value":2456},"    LD B,$02             ; Ring buffer type 2 (TX)\n",{"type":20,"tag":869,"props":2458,"children":2459},{"class":871,"line":944},[2460],{"type":20,"tag":869,"props":2461,"children":2462},{},[2463],{"type":25,"value":2464},"    CALL RINGBUF_READ    ; Read from TX buffer\n",{"type":20,"tag":869,"props":2466,"children":2467},{"class":871,"line":953},[2468],{"type":20,"tag":869,"props":2469,"children":2470},{},[2471],{"type":25,"value":2472},"    RET Z                ; Empty: return\n",{"type":20,"tag":869,"props":2474,"children":2475},{"class":871,"line":962},[2476],{"type":20,"tag":869,"props":2477,"children":2478},{},[2479],{"type":25,"value":2480},"    CP $23               ; '#' hash?\n",{"type":20,"tag":869,"props":2482,"children":2483},{"class":871,"line":971},[2484],{"type":20,"tag":869,"props":2485,"children":2486},{},[2487],{"type":25,"value":2488},"    JR NZ,.not_hash\n",{"type":20,"tag":869,"props":2490,"children":2491},{"class":871,"line":2324},[2492],{"type":20,"tag":869,"props":2493,"children":2494},{},[2495],{"type":25,"value":2496},"    LD A,$5F             ; Replace with underscore\n",{"type":20,"tag":869,"props":2498,"children":2499},{"class":871,"line":2333},[2500],{"type":20,"tag":869,"props":2501,"children":2502},{},[2503],{"type":25,"value":2504},".not_hash:\n",{"type":20,"tag":869,"props":2506,"children":2507},{"class":871,"line":2342},[2508],{"type":20,"tag":869,"props":2509,"children":2510},{},[2511],{"type":25,"value":2512},"    OUT ($7F),A          ; Transmit byte\n",{"type":20,"tag":869,"props":2514,"children":2516},{"class":871,"line":2515},16,[2517],{"type":20,"tag":869,"props":2518,"children":2519},{},[2520],{"type":25,"value":2521},"    RET\n",{"type":20,"tag":21,"props":2523,"children":2524},{},[2525,2527,2533,2535,2541,2543,2548,2550,2556,2558,2563],{"type":25,"value":2526},"There's a character substitution here: the ",{"type":20,"tag":123,"props":2528,"children":2530},{"className":2529},[],[2531],{"type":25,"value":2532},"#",{"type":25,"value":2534}," key gets replaced with ",{"type":20,"tag":123,"props":2536,"children":2538},{"className":2537},[],[2539],{"type":25,"value":2540},"$5F",{"type":25,"value":2542}," (underscore) on transmit. This is a UK keyboard mapping artifact - on the Spectrum keyboard, what you'd think of as ",{"type":20,"tag":123,"props":2544,"children":2546},{"className":2545},[],[2547],{"type":25,"value":2532},{"type":25,"value":2549}," needed to be sent as ",{"type":20,"tag":123,"props":2551,"children":2553},{"className":2552},[],[2554],{"type":25,"value":2555},"_",{"type":25,"value":2557}," for Prestel's character set, where ",{"type":20,"tag":123,"props":2559,"children":2561},{"className":2560},[],[2562],{"type":25,"value":2532},{"type":25,"value":2564}," has a different meaning (it's the \"send\" key in Prestel navigation, like pressing Enter on a form).",{"type":20,"tag":54,"props":2566,"children":2568},{"id":2567},"receive",[2569],{"type":25,"value":2570},"Receive",{"type":20,"tag":21,"props":2572,"children":2573},{},[2574],{"type":25,"value":2575},"The receive side reads from the 8251 data register and writes into the RX buffer:",{"type":20,"tag":858,"props":2577,"children":2579},{"className":860,"code":2578,"language":862,"meta":863,"style":863},"CHECK_RX_DATA:\n    BIT 5,(IX+$06)       ; TX busy?\n    RET NZ               ; Yes: skip RX\n    IN A,($FF)           ; Read 8251 status\n    BIT 7,A              ; DSR (Data Set Ready)?\n    RET Z                ; No DSR: modem not connected\n    LD (IX+$1B),$64      ; Reset idle timeout (modem is alive)\n    BIT 1,A              ; RxRDY?\n    RET Z                ; No data: return\n    BIT 3,A              ; Parity error?\n    IN A,($7F)           ; Read received byte\n    JR Z,.no_parity_err  ; No error: use as-is\n    LD A,(IX+$08)        ; Parity error: rewrite command register\n    OUT ($FF),A          ;   (clears error flags)\n    LD A,$FF             ;   Replace byte with $FF (error marker)\n.no_parity_err:\n    LD B,$04             ; Ring buffer type 4 (RX)\n    CALL RINGBUF_WRITE   ; Write to buffer\n    CALL SET_CARRIER_TIMEOUT  ; Reset carrier timeout\n    RET\n",[2580],{"type":20,"tag":123,"props":2581,"children":2582},{"__ignoreMap":863},[2583,2591,2599,2607,2614,2622,2630,2638,2646,2654,2662,2670,2678,2686,2694,2702,2710,2719,2728,2737],{"type":20,"tag":869,"props":2584,"children":2585},{"class":871,"line":872},[2586],{"type":20,"tag":869,"props":2587,"children":2588},{},[2589],{"type":25,"value":2590},"CHECK_RX_DATA:\n",{"type":20,"tag":869,"props":2592,"children":2593},{"class":871,"line":881},[2594],{"type":20,"tag":869,"props":2595,"children":2596},{},[2597],{"type":25,"value":2598},"    BIT 5,(IX+$06)       ; TX busy?\n",{"type":20,"tag":869,"props":2600,"children":2601},{"class":871,"line":890},[2602],{"type":20,"tag":869,"props":2603,"children":2604},{},[2605],{"type":25,"value":2606},"    RET NZ               ; Yes: skip RX\n",{"type":20,"tag":869,"props":2608,"children":2609},{"class":871,"line":899},[2610],{"type":20,"tag":869,"props":2611,"children":2612},{},[2613],{"type":25,"value":2432},{"type":20,"tag":869,"props":2615,"children":2616},{"class":871,"line":908},[2617],{"type":20,"tag":869,"props":2618,"children":2619},{},[2620],{"type":25,"value":2621},"    BIT 7,A              ; DSR (Data Set Ready)?\n",{"type":20,"tag":869,"props":2623,"children":2624},{"class":871,"line":917},[2625],{"type":20,"tag":869,"props":2626,"children":2627},{},[2628],{"type":25,"value":2629},"    RET Z                ; No DSR: modem not connected\n",{"type":20,"tag":869,"props":2631,"children":2632},{"class":871,"line":926},[2633],{"type":20,"tag":869,"props":2634,"children":2635},{},[2636],{"type":25,"value":2637},"    LD (IX+$1B),$64      ; Reset idle timeout (modem is alive)\n",{"type":20,"tag":869,"props":2639,"children":2640},{"class":871,"line":935},[2641],{"type":20,"tag":869,"props":2642,"children":2643},{},[2644],{"type":25,"value":2645},"    BIT 1,A              ; RxRDY?\n",{"type":20,"tag":869,"props":2647,"children":2648},{"class":871,"line":944},[2649],{"type":20,"tag":869,"props":2650,"children":2651},{},[2652],{"type":25,"value":2653},"    RET Z                ; No data: return\n",{"type":20,"tag":869,"props":2655,"children":2656},{"class":871,"line":953},[2657],{"type":20,"tag":869,"props":2658,"children":2659},{},[2660],{"type":25,"value":2661},"    BIT 3,A              ; Parity error?\n",{"type":20,"tag":869,"props":2663,"children":2664},{"class":871,"line":962},[2665],{"type":20,"tag":869,"props":2666,"children":2667},{},[2668],{"type":25,"value":2669},"    IN A,($7F)           ; Read received byte\n",{"type":20,"tag":869,"props":2671,"children":2672},{"class":871,"line":971},[2673],{"type":20,"tag":869,"props":2674,"children":2675},{},[2676],{"type":25,"value":2677},"    JR Z,.no_parity_err  ; No error: use as-is\n",{"type":20,"tag":869,"props":2679,"children":2680},{"class":871,"line":2324},[2681],{"type":20,"tag":869,"props":2682,"children":2683},{},[2684],{"type":25,"value":2685},"    LD A,(IX+$08)        ; Parity error: rewrite command register\n",{"type":20,"tag":869,"props":2687,"children":2688},{"class":871,"line":2333},[2689],{"type":20,"tag":869,"props":2690,"children":2691},{},[2692],{"type":25,"value":2693},"    OUT ($FF),A          ;   (clears error flags)\n",{"type":20,"tag":869,"props":2695,"children":2696},{"class":871,"line":2342},[2697],{"type":20,"tag":869,"props":2698,"children":2699},{},[2700],{"type":25,"value":2701},"    LD A,$FF             ;   Replace byte with $FF (error marker)\n",{"type":20,"tag":869,"props":2703,"children":2704},{"class":871,"line":2515},[2705],{"type":20,"tag":869,"props":2706,"children":2707},{},[2708],{"type":25,"value":2709},".no_parity_err:\n",{"type":20,"tag":869,"props":2711,"children":2713},{"class":871,"line":2712},17,[2714],{"type":20,"tag":869,"props":2715,"children":2716},{},[2717],{"type":25,"value":2718},"    LD B,$04             ; Ring buffer type 4 (RX)\n",{"type":20,"tag":869,"props":2720,"children":2722},{"class":871,"line":2721},18,[2723],{"type":20,"tag":869,"props":2724,"children":2725},{},[2726],{"type":25,"value":2727},"    CALL RINGBUF_WRITE   ; Write to buffer\n",{"type":20,"tag":869,"props":2729,"children":2731},{"class":871,"line":2730},19,[2732],{"type":20,"tag":869,"props":2733,"children":2734},{},[2735],{"type":25,"value":2736},"    CALL SET_CARRIER_TIMEOUT  ; Reset carrier timeout\n",{"type":20,"tag":869,"props":2738,"children":2740},{"class":871,"line":2739},20,[2741],{"type":20,"tag":869,"props":2742,"children":2743},{},[2744],{"type":25,"value":2521},{"type":20,"tag":21,"props":2746,"children":2747},{},[2748],{"type":25,"value":2749},"A few things are worth noting.",{"type":20,"tag":2751,"props":2752,"children":2753},"ol",{},[2754,2760],{"type":20,"tag":2755,"props":2756,"children":2757},"li",{},[2758],{"type":25,"value":2759},"The DSR check - if the modem isn't reporting Data Set Ready, we don't even try to read. This is the VTX5000's carrier detect mechanism.",{"type":20,"tag":2755,"props":2761,"children":2762},{},[2763,2765,2770],{"type":25,"value":2764},"Parity errors don't cause a crash or a disconnect - the errored byte is simply replaced with ",{"type":20,"tag":123,"props":2766,"children":2768},{"className":2767},[],[2769],{"type":25,"value":1156},{"type":25,"value":2771}," and passed on. The rendering engine will display something garbled, but the connection stays up. At 1200 baud over a phone line, occasional parity errors are a fact of life.",{"type":20,"tag":21,"props":2773,"children":2774},{},[2775,2777,2783],{"type":25,"value":2776},"The idle timeout at ",{"type":20,"tag":123,"props":2778,"children":2780},{"className":2779},[],[2781],{"type":25,"value":2782},"IX+$1B",{"type":25,"value":2784}," is reset to 100 ($64) every time valid data arrives. It's decremented by the keyboard scan routine, and if it ever reaches zero, the return code is set to 2 (timeout). This is how the VTX5000 detects that the remote end has stopped sending.",{"type":20,"tag":54,"props":2786,"children":2788},{"id":2787},"the-buffers",[2789],{"type":25,"value":2790},"The Buffers",{"type":20,"tag":21,"props":2792,"children":2793},{},[2794],{"type":25,"value":2795},"There are two small ring buffers - type 2 for transmit, type 4 for receive - both embedded within the IX state block. Each buffer has a 2-byte count at its head, followed by the data bytes.",{"type":20,"tag":21,"props":2797,"children":2798},{},[2799,2805,2807,2813],{"type":20,"tag":2800,"props":2801,"children":2802},"strong",{},[2803],{"type":25,"value":2804},"Write",{"type":25,"value":2806}," (",{"type":20,"tag":123,"props":2808,"children":2810},{"className":2809},[],[2811],{"type":25,"value":2812},"$15D6",{"type":25,"value":2814},") is trivial - increment the count, calculate the write position by adding count to the base pointer, and store the byte:",{"type":20,"tag":858,"props":2816,"children":2818},{"className":860,"code":2817,"language":862,"meta":863,"style":863},"RINGBUF_WRITE:\n    CALL RINGBUF_GETPTR  ; Get buffer base and current count\n    INC BC               ; Increment count\n    LD (HL),C            ; Store count low\n    INC HL\n    LD (HL),B            ; Store count high\n    ADD HL,BC            ; Point to write position\n    LD (HL),A            ; Write byte\n    RET\n",[2819],{"type":20,"tag":123,"props":2820,"children":2821},{"__ignoreMap":863},[2822,2830,2838,2846,2854,2862,2870,2878,2886],{"type":20,"tag":869,"props":2823,"children":2824},{"class":871,"line":872},[2825],{"type":20,"tag":869,"props":2826,"children":2827},{},[2828],{"type":25,"value":2829},"RINGBUF_WRITE:\n",{"type":20,"tag":869,"props":2831,"children":2832},{"class":871,"line":881},[2833],{"type":20,"tag":869,"props":2834,"children":2835},{},[2836],{"type":25,"value":2837},"    CALL RINGBUF_GETPTR  ; Get buffer base and current count\n",{"type":20,"tag":869,"props":2839,"children":2840},{"class":871,"line":890},[2841],{"type":20,"tag":869,"props":2842,"children":2843},{},[2844],{"type":25,"value":2845},"    INC BC               ; Increment count\n",{"type":20,"tag":869,"props":2847,"children":2848},{"class":871,"line":899},[2849],{"type":20,"tag":869,"props":2850,"children":2851},{},[2852],{"type":25,"value":2853},"    LD (HL),C            ; Store count low\n",{"type":20,"tag":869,"props":2855,"children":2856},{"class":871,"line":908},[2857],{"type":20,"tag":869,"props":2858,"children":2859},{},[2860],{"type":25,"value":2861},"    INC HL\n",{"type":20,"tag":869,"props":2863,"children":2864},{"class":871,"line":917},[2865],{"type":20,"tag":869,"props":2866,"children":2867},{},[2868],{"type":25,"value":2869},"    LD (HL),B            ; Store count high\n",{"type":20,"tag":869,"props":2871,"children":2872},{"class":871,"line":926},[2873],{"type":20,"tag":869,"props":2874,"children":2875},{},[2876],{"type":25,"value":2877},"    ADD HL,BC            ; Point to write position\n",{"type":20,"tag":869,"props":2879,"children":2880},{"class":871,"line":935},[2881],{"type":20,"tag":869,"props":2882,"children":2883},{},[2884],{"type":25,"value":2885},"    LD (HL),A            ; Write byte\n",{"type":20,"tag":869,"props":2887,"children":2888},{"class":871,"line":944},[2889],{"type":20,"tag":869,"props":2890,"children":2891},{},[2892],{"type":25,"value":2521},{"type":20,"tag":21,"props":2894,"children":2895},{},[2896,2901,2902,2908],{"type":20,"tag":2800,"props":2897,"children":2898},{},[2899],{"type":25,"value":2900},"Read",{"type":25,"value":2806},{"type":20,"tag":123,"props":2903,"children":2905},{"className":2904},[],[2906],{"type":25,"value":2907},"$15E0",{"type":25,"value":2909},") is more interesting - after reading the first byte, it shifts the entire remaining buffer down by one position using LDIR:",{"type":20,"tag":858,"props":2911,"children":2913},{"className":860,"code":2912,"language":862,"meta":863,"style":863},"RINGBUF_READ:\n    CALL RINGBUF_GETPTR  ; Get buffer base and count\n    LD A,B\n    OR C                 ; Empty?\n    RET Z                ; Yes: return Z flag\n    DEC BC               ; Decrement count\n    LD (HL),C            ; Store new count\n    INC HL\n    LD (HL),B\n    INC HL\n    LD A,(HL)            ; Read first byte\n    INC BC               ; Restore count for shift\n    LD E,L               ; Set up LDIR (shift buffer down by 1)\n    LD D,H\n    INC HL\n    LDIR                 ; Shift remaining bytes\n    RET\n",[2914],{"type":20,"tag":123,"props":2915,"children":2916},{"__ignoreMap":863},[2917,2925,2933,2941,2949,2957,2965,2973,2980,2988,2995,3003,3011,3019,3027,3034,3042],{"type":20,"tag":869,"props":2918,"children":2919},{"class":871,"line":872},[2920],{"type":20,"tag":869,"props":2921,"children":2922},{},[2923],{"type":25,"value":2924},"RINGBUF_READ:\n",{"type":20,"tag":869,"props":2926,"children":2927},{"class":871,"line":881},[2928],{"type":20,"tag":869,"props":2929,"children":2930},{},[2931],{"type":25,"value":2932},"    CALL RINGBUF_GETPTR  ; Get buffer base and count\n",{"type":20,"tag":869,"props":2934,"children":2935},{"class":871,"line":890},[2936],{"type":20,"tag":869,"props":2937,"children":2938},{},[2939],{"type":25,"value":2940},"    LD A,B\n",{"type":20,"tag":869,"props":2942,"children":2943},{"class":871,"line":899},[2944],{"type":20,"tag":869,"props":2945,"children":2946},{},[2947],{"type":25,"value":2948},"    OR C                 ; Empty?\n",{"type":20,"tag":869,"props":2950,"children":2951},{"class":871,"line":908},[2952],{"type":20,"tag":869,"props":2953,"children":2954},{},[2955],{"type":25,"value":2956},"    RET Z                ; Yes: return Z flag\n",{"type":20,"tag":869,"props":2958,"children":2959},{"class":871,"line":917},[2960],{"type":20,"tag":869,"props":2961,"children":2962},{},[2963],{"type":25,"value":2964},"    DEC BC               ; Decrement count\n",{"type":20,"tag":869,"props":2966,"children":2967},{"class":871,"line":926},[2968],{"type":20,"tag":869,"props":2969,"children":2970},{},[2971],{"type":25,"value":2972},"    LD (HL),C            ; Store new count\n",{"type":20,"tag":869,"props":2974,"children":2975},{"class":871,"line":935},[2976],{"type":20,"tag":869,"props":2977,"children":2978},{},[2979],{"type":25,"value":2861},{"type":20,"tag":869,"props":2981,"children":2982},{"class":871,"line":944},[2983],{"type":20,"tag":869,"props":2984,"children":2985},{},[2986],{"type":25,"value":2987},"    LD (HL),B\n",{"type":20,"tag":869,"props":2989,"children":2990},{"class":871,"line":953},[2991],{"type":20,"tag":869,"props":2992,"children":2993},{},[2994],{"type":25,"value":2861},{"type":20,"tag":869,"props":2996,"children":2997},{"class":871,"line":962},[2998],{"type":20,"tag":869,"props":2999,"children":3000},{},[3001],{"type":25,"value":3002},"    LD A,(HL)            ; Read first byte\n",{"type":20,"tag":869,"props":3004,"children":3005},{"class":871,"line":971},[3006],{"type":20,"tag":869,"props":3007,"children":3008},{},[3009],{"type":25,"value":3010},"    INC BC               ; Restore count for shift\n",{"type":20,"tag":869,"props":3012,"children":3013},{"class":871,"line":2324},[3014],{"type":20,"tag":869,"props":3015,"children":3016},{},[3017],{"type":25,"value":3018},"    LD E,L               ; Set up LDIR (shift buffer down by 1)\n",{"type":20,"tag":869,"props":3020,"children":3021},{"class":871,"line":2333},[3022],{"type":20,"tag":869,"props":3023,"children":3024},{},[3025],{"type":25,"value":3026},"    LD D,H\n",{"type":20,"tag":869,"props":3028,"children":3029},{"class":871,"line":2342},[3030],{"type":20,"tag":869,"props":3031,"children":3032},{},[3033],{"type":25,"value":2861},{"type":20,"tag":869,"props":3035,"children":3036},{"class":871,"line":2515},[3037],{"type":20,"tag":869,"props":3038,"children":3039},{},[3040],{"type":25,"value":3041},"    LDIR                 ; Shift remaining bytes\n",{"type":20,"tag":869,"props":3043,"children":3044},{"class":871,"line":2712},[3045],{"type":20,"tag":869,"props":3046,"children":3047},{},[3048],{"type":25,"value":2521},{"type":20,"tag":21,"props":3050,"children":3051},{},[3052],{"type":25,"value":3053},"This is technically a FIFO queue, not a ring buffer - there's no wrap-around, just a linear shift on every read. At 1200 baud with a buffer size of 16 bytes (when online) or 255 bytes (when offline), the LDIR is never shifting more than a few bytes, so the performance cost is negligible. It's a simpler implementation than a proper circular buffer with head/tail pointers, and on a system where RAM is scarce, every byte counts.",{"type":20,"tag":21,"props":3055,"children":3056},{},[3057,3059,3065,3066,3072],{"type":25,"value":3058},"The ",{"type":20,"tag":123,"props":3060,"children":3062},{"className":3061},[],[3063],{"type":25,"value":3064},"RINGBUF_GETPTR",{"type":25,"value":848},{"type":20,"tag":123,"props":3067,"children":3069},{"className":3068},[],[3070],{"type":25,"value":3071},"$15F3",{"type":25,"value":3073}," finds the right buffer by walking through the chain. Buffer type is passed in the B register, and the routine skips forward through the count/data pairs until it reaches the right one. It's a linked-list walk through what's essentially a stack of variably-sized buffers inside the IX state block.",{"type":20,"tag":54,"props":3075,"children":3077},{"id":3076},"carrier-and-idle-timeouts",[3078],{"type":25,"value":3079},"Carrier and Idle Timeouts",{"type":20,"tag":21,"props":3081,"children":3082},{},[3083],{"type":25,"value":3084},"Two separate timeout mechanisms protect against connection problems:",{"type":20,"tag":21,"props":3086,"children":3087},{},[3088,3089,3094,3095,3100],{"type":25,"value":3058},{"type":20,"tag":2800,"props":3090,"children":3091},{},[3092],{"type":25,"value":3093},"idle timeout",{"type":25,"value":2806},{"type":20,"tag":123,"props":3096,"children":3098},{"className":3097},[],[3099],{"type":25,"value":2782},{"type":25,"value":3101},", initialised to 100) counts down on each keyboard scan. Any received data resets it. If it hits zero, the return code is set to 2 (\"Line Break\" in BASIC). This catches the case where the remote end goes silent - no data, no carrier drop, just silence.",{"type":20,"tag":21,"props":3103,"children":3104},{},[3105,3106,3111,3112,3118,3120,3126,3128,3134],{"type":25,"value":3058},{"type":20,"tag":2800,"props":3107,"children":3108},{},[3109],{"type":25,"value":3110},"carrier timeout",{"type":25,"value":2806},{"type":20,"tag":123,"props":3113,"children":3115},{"className":3114},[],[3116],{"type":25,"value":3117},"IX+$19",{"type":25,"value":3119},"/",{"type":20,"tag":123,"props":3121,"children":3123},{"className":3122},[],[3124],{"type":25,"value":3125},"$1A",{"type":25,"value":3127},", a 16-bit counter) uses different values depending on mode: 25000 cycles when offline and waiting for a connection, or a configured value when online. It's decremented on each keyboard scan, and if both bytes reach zero, the return code is set to 3 (\"Carrier lost\"). The ",{"type":20,"tag":123,"props":3129,"children":3131},{"className":3130},[],[3132],{"type":25,"value":3133},"SET_CARRIER_TIMEOUT",{"type":25,"value":3135}," routine picks the right values:",{"type":20,"tag":858,"props":3137,"children":3139},{"className":860,"code":3138,"language":862,"meta":863,"style":863},"SET_CARRIER_TIMEOUT:\n    LD L,(IX+$42)        ; Online timeout low\n    LD H,(IX+$43)        ; Online timeout high\n    BIT 0,(IX+$06)       ; Online?\n    JR NZ,.set_timeout   ; Yes\n    LD L,(IX+$44)        ; Offline timeout low\n    LD H,(IX+$45)        ; Offline timeout high\n    BIT 4,(IX+$06)       ; Auto-answer?\n    JR NZ,.set_timeout   ; Yes\n    LD HL,$61A8          ; Default: 25000\n.set_timeout:\n    LD (IX+$19),L\n    INC H                ; Add 256 to high byte\n    LD (IX+$1A),H\n    RET\n",[3140],{"type":20,"tag":123,"props":3141,"children":3142},{"__ignoreMap":863},[3143,3151,3159,3167,3175,3183,3191,3199,3207,3214,3222,3230,3238,3246,3254],{"type":20,"tag":869,"props":3144,"children":3145},{"class":871,"line":872},[3146],{"type":20,"tag":869,"props":3147,"children":3148},{},[3149],{"type":25,"value":3150},"SET_CARRIER_TIMEOUT:\n",{"type":20,"tag":869,"props":3152,"children":3153},{"class":871,"line":881},[3154],{"type":20,"tag":869,"props":3155,"children":3156},{},[3157],{"type":25,"value":3158},"    LD L,(IX+$42)        ; Online timeout low\n",{"type":20,"tag":869,"props":3160,"children":3161},{"class":871,"line":890},[3162],{"type":20,"tag":869,"props":3163,"children":3164},{},[3165],{"type":25,"value":3166},"    LD H,(IX+$43)        ; Online timeout high\n",{"type":20,"tag":869,"props":3168,"children":3169},{"class":871,"line":899},[3170],{"type":20,"tag":869,"props":3171,"children":3172},{},[3173],{"type":25,"value":3174},"    BIT 0,(IX+$06)       ; Online?\n",{"type":20,"tag":869,"props":3176,"children":3177},{"class":871,"line":908},[3178],{"type":20,"tag":869,"props":3179,"children":3180},{},[3181],{"type":25,"value":3182},"    JR NZ,.set_timeout   ; Yes\n",{"type":20,"tag":869,"props":3184,"children":3185},{"class":871,"line":917},[3186],{"type":20,"tag":869,"props":3187,"children":3188},{},[3189],{"type":25,"value":3190},"    LD L,(IX+$44)        ; Offline timeout low\n",{"type":20,"tag":869,"props":3192,"children":3193},{"class":871,"line":926},[3194],{"type":20,"tag":869,"props":3195,"children":3196},{},[3197],{"type":25,"value":3198},"    LD H,(IX+$45)        ; Offline timeout high\n",{"type":20,"tag":869,"props":3200,"children":3201},{"class":871,"line":935},[3202],{"type":20,"tag":869,"props":3203,"children":3204},{},[3205],{"type":25,"value":3206},"    BIT 4,(IX+$06)       ; Auto-answer?\n",{"type":20,"tag":869,"props":3208,"children":3209},{"class":871,"line":944},[3210],{"type":20,"tag":869,"props":3211,"children":3212},{},[3213],{"type":25,"value":3182},{"type":20,"tag":869,"props":3215,"children":3216},{"class":871,"line":953},[3217],{"type":20,"tag":869,"props":3218,"children":3219},{},[3220],{"type":25,"value":3221},"    LD HL,$61A8          ; Default: 25000\n",{"type":20,"tag":869,"props":3223,"children":3224},{"class":871,"line":962},[3225],{"type":20,"tag":869,"props":3226,"children":3227},{},[3228],{"type":25,"value":3229},".set_timeout:\n",{"type":20,"tag":869,"props":3231,"children":3232},{"class":871,"line":971},[3233],{"type":20,"tag":869,"props":3234,"children":3235},{},[3236],{"type":25,"value":3237},"    LD (IX+$19),L\n",{"type":20,"tag":869,"props":3239,"children":3240},{"class":871,"line":2324},[3241],{"type":20,"tag":869,"props":3242,"children":3243},{},[3244],{"type":25,"value":3245},"    INC H                ; Add 256 to high byte\n",{"type":20,"tag":869,"props":3247,"children":3248},{"class":871,"line":2333},[3249],{"type":20,"tag":869,"props":3250,"children":3251},{},[3252],{"type":25,"value":3253},"    LD (IX+$1A),H\n",{"type":20,"tag":869,"props":3255,"children":3256},{"class":871,"line":2342},[3257],{"type":20,"tag":869,"props":3258,"children":3259},{},[3260],{"type":25,"value":2521},{"type":20,"tag":54,"props":3262,"children":3264},{"id":3263},"keyboard-scanning",[3265],{"type":25,"value":3266},"Keyboard Scanning",{"type":20,"tag":21,"props":3268,"children":3269},{},[3270,3272,3278],{"type":25,"value":3271},"The keyboard scanner at ",{"type":20,"tag":123,"props":3273,"children":3275},{"className":3274},[],[3276],{"type":25,"value":3277},"$1550",{"type":25,"value":3279}," does more than just read keys - it handles the translation from Spectrum's keyboard layout to Prestel's expectations.",{"type":20,"tag":21,"props":3281,"children":3282},{},[3283,3285,3291],{"type":25,"value":3284},"The Spectrum keyboard uses a matrix read via port ",{"type":20,"tag":123,"props":3286,"children":3288},{"className":3287},[],[3289],{"type":25,"value":3290},"$FE",{"type":25,"value":3292},". The scanner first checks for BREAK (CAPS SHIFT + SPACE), which sets return code 1 for an immediate exit. Then it reads the key value from the Spectrum's system variables (the ROM's interrupt handler has already decoded the matrix) and applies several transformations:",{"type":20,"tag":3294,"props":3295,"children":3296},"ul",{},[3297,3329,3346,3363,3387],{"type":20,"tag":2755,"props":3298,"children":3299},{},[3300,3305,3306,3312,3314,3320,3322,3327],{"type":20,"tag":2800,"props":3301,"children":3302},{},[3303],{"type":25,"value":3304},"Symbol Shift",{"type":25,"value":2806},{"type":20,"tag":123,"props":3307,"children":3309},{"className":3308},[],[3310],{"type":25,"value":3311},"$0E",{"type":25,"value":3313},") sets internal shift state flags - Prestel uses ",{"type":20,"tag":123,"props":3315,"children":3317},{"className":3316},[],[3318],{"type":25,"value":3319},"*",{"type":25,"value":3321}," (star) as a modifier key, so Symbol Shift is remapped to ",{"type":20,"tag":123,"props":3323,"children":3325},{"className":3324},[],[3326],{"type":25,"value":3319},{"type":25,"value":3328}," for Prestel navigation",{"type":20,"tag":2755,"props":3330,"children":3331},{},[3332,3337,3338,3344],{"type":20,"tag":2800,"props":3333,"children":3334},{},[3335],{"type":25,"value":3336},"CAPS LOCK",{"type":25,"value":2806},{"type":20,"tag":123,"props":3339,"children":3341},{"className":3340},[],[3342],{"type":25,"value":3343},"$06",{"type":25,"value":3345},") toggles bit 3 of the border colour attribute - this gives visual feedback (bright/dim border) to show caps lock state, since Viewdata doesn't have a separate caps indicator",{"type":20,"tag":2755,"props":3347,"children":3348},{},[3349,3354,3355,3361],{"type":20,"tag":2800,"props":3350,"children":3351},{},[3352],{"type":25,"value":3353},"EDIT",{"type":25,"value":2806},{"type":20,"tag":123,"props":3356,"children":3358},{"className":3357},[],[3359],{"type":25,"value":3360},"$07",{"type":25,"value":3362},") toggles a display mode flag and triggers a full screen refresh",{"type":20,"tag":2755,"props":3364,"children":3365},{},[3366,3371,3372,3378,3380,3385],{"type":20,"tag":2800,"props":3367,"children":3368},{},[3369],{"type":25,"value":3370},"ENTER",{"type":25,"value":2806},{"type":20,"tag":123,"props":3373,"children":3375},{"className":3374},[],[3376],{"type":25,"value":3377},"$0D",{"type":25,"value":3379},") becomes ",{"type":20,"tag":123,"props":3381,"children":3383},{"className":3382},[],[3384],{"type":25,"value":2540},{"type":25,"value":3386}," (underscore) - in Prestel, underscore is the \"send\" character",{"type":20,"tag":2755,"props":3388,"children":3389},{},[3390,3395,3396,3401,3402,3407],{"type":20,"tag":2800,"props":3391,"children":3392},{},[3393],{"type":25,"value":3394},"DELETE",{"type":25,"value":2806},{"type":20,"tag":123,"props":3397,"children":3399},{"className":3398},[],[3400],{"type":25,"value":530},{"type":25,"value":3379},{"type":20,"tag":123,"props":3403,"children":3405},{"className":3404},[],[3406],{"type":25,"value":249},{"type":25,"value":3408}," (backspace)",{"type":20,"tag":21,"props":3410,"children":3411},{},[3412,3414,3420],{"type":25,"value":3413},"The keyboard lock feature (bit 2 of ",{"type":20,"tag":123,"props":3415,"children":3417},{"className":3416},[],[3418],{"type":25,"value":3419},"IX+$06",{"type":25,"value":3421},") suppresses all key output when set. This is used during data reception - Prestel doesn't support type-ahead, so keys pressed while a frame is loading should be discarded.",{"type":20,"tag":54,"props":3423,"children":3425},{"id":3424},"whats-next",[3426],{"type":25,"value":3427},"What's Next",{"type":20,"tag":21,"props":3429,"children":3430},{},[3431],{"type":25,"value":3432},"In part 5 we'll tackle the most technically fascinating part of the ROM: the Viewdata rendering engine and how it renders that 40x24 display with a 5-pixel font, mosaic block graphics and Prestel frames onto the Speccy's display.",{"type":20,"tag":3434,"props":3435,"children":3436},"style",{},[3437],{"type":25,"value":3438},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":863,"searchDepth":881,"depth":881,"links":3440},[3441,3442,3443,3444,3445,3446,3447,3448,3449,3450],{"id":56,"depth":890,"text":59},{"id":832,"depth":890,"text":835},{"id":995,"depth":890,"text":998},{"id":2202,"depth":890,"text":2205},{"id":2377,"depth":890,"text":2380},{"id":2567,"depth":890,"text":2570},{"id":2787,"depth":890,"text":2790},{"id":3076,"depth":890,"text":3079},{"id":3263,"depth":890,"text":3266},{"id":3424,"depth":890,"text":3427},"markdown","content:blog:2026:2026-05-06-vtx5000-part-4-comms-routines.md","content","blog/2026/2026-05-06-vtx5000-part-4-comms-routines.md","blog/2026/2026-05-06-vtx5000-part-4-comms-routines","md","/blog/2026/05/06/vtx5000-part-4-comms-routines/",2441,0,[3461,3464,3468],{"title":3462,"date":3463,"url":45},"VTX5000: Part 3 - Software ROM","2026-04-15T23:00:00.000Z",{"title":3465,"date":3466,"url":3467},"VTX5000: Part 2 - Hardware","2026-03-30T23:00:00.000Z","/blog/2026/03/30/prism-vtx5000-part-2/",{"title":3469,"date":3470,"url":3471},"VTX 5000: Part 1 - Prism, Prestel and Teletext","2026-03-13","/blog/2026/03/23/prism-vtx5000-part-1/",[],1778082214058]