TITLE WA1LMV 8085 Repeater Control Software PAGE 90 include vers.z80 ; version and date vers equ 15 vmonth equ 10 vday equ 29 vcent equ 19 vyear equ 94 .comment ~ ============================================================================ WA1LMV Repeater Control Software Copyright 1990,1995 by Rick Swenton 106 Melinda Lane Bristol, CT 06010-7176 All Rights Reserved This is a full-featured repeater control system for an 8085 CPU. This program is a proprietary work and has not been released. ============================================================================ This program supports the following features: (at this time) - Two Main Receiver Inputs for COS and PL - Two Auxiliary Receiver Inputs for COS - Audio Gate Control signals for Audio Mixer - Two Main Transmitter Outputs - Two Auxlilary Transmitter Outputs - MCW Messages and ID with programmable pitch and speed - ID Timer with Polite ID and Broadcast ID - Separate Main Receiver Time-Out Timers with PL inhibit - Separate Main and Auxiliary Receiver Timers: Input Access Delay Input Release Delay - Auxiliary Transmitters inactivity dump timer - Autopatch with inactivity dump timer - DTMF regeneration and speed-dialing with speech readout of 10 Programmable Dialer slots and last number recall - DTMF Mute of Audio Gates - Reverse Autopatch with announce - Dial-in Landline Control System - Courtesy tones with programmable MCW character and programmable pitch for each main receiver - Auxiliary RX/TX Indicator Tones on Main RX usage - CRT Console Terminal with Command Menu and Status Display - Ability to enable/disable any input/output signal - Interrupt driven background timing system updates timers every ten milliseconds and I/O every millisecond - Two Interrupt driven DTMF Decoders with buffered type-ahead One decoder for radio input, the other for phone line control - Interrupt driven Console input with buffered type-ahead and X-ON/X-OFF protocol - Simultaneous input from CRT keyboard and both DTMF decoders - Emulation of existing WA1LMV/R Repeater Control Codes - Enahncement of Control System functionality and security (User Operator/Control Operator) - Watchdog timer in hardware and other software error traps to recover from noise, power surges or software bugs. - Speech Synthesis using SSI263 chip -- controls speech inflection, rate and articulation. - Time of Day Clock/Calendar/Alarm (MM58167) with speech readout, hourly chime announce and ten scheduled events - Software detects presence of speech and clock chips and disables speech if chip not there. Program emulates clock chip in software if chip not there. - 10 Programmable Macro keys for control speed-commands - Capability to read/write to/from memory in HEX through Console or DTMF (0-9, A-F) with MCW or Speech readout of memory locations - Two Meter Synthesizer control with 10 preset user programmable frequencies, mode and power control At this time, the program is about 17K large with up to 32K of EPROM available for program storage. The target CPU is an INTEL 8085. The program is written in Z80 Assembly Language. The SLR Systems SLR180+ Assembler was used to create the EPROM file using the /Z switch so as to reject Z80-specific instructions. ~ include codes.z80 .comment ~ Currently Implemented Control and User Functions: ============================================================================== User Functions Series *2500 Codes: ============================================================================== ------------------------------------------------------------------------------ General User Functions ------------------------------------------------------------------------------ *2501 - Autopatch ON *2500 - Autopatch OFF *2502 - Autopatch Speed Dialer where ten phone numbers are stored in Slots 0 -> 9 Usage: *25020 through *25029 *2503 - Speak the last dialed number (Last manually dialed number is saved in Speed Dialer slot 0) *2505 - Curly (see *2539 which adds time and ID to Curly) *2506 - Voice Time *2507 - Super Beep (no special purpose, just for test) *2508 - MCW ID Start *2509 - Voice ID Start ------------------------------------------------------------------------------ Link Transceiver #1 Functions (Two Meters) ------------------------------------------------------------------------------ *2511 - 2M RX ON *2510 - 2M RX/TX OFF *2512 - 2M TX ON *2514c - Set 2M Active channel *2515c - Speak Preset Channel Frequency where 'c' is the channel number *2516ffffmp - Set 2m Chan 0 Freq where 'ffff' is the freq (6880 = 146.880) This function also selects 'm' is the mode Channel 0 as the Active Channel 0 = Simplex 1 = Auto-Repeat 2 = Auto-Inverse 'p' is the power 0 = Low 1 = High ------------------------------------------------------------------------------ Link Transceiver #2 Functions ------------------------------------------------------------------------------ *2521 - Aux RX2 ON *2520 - Aux RX2/TX2 OFF *2522 - Aux TX2 ON ------------------------------------------------------------------------------ Time, Date and Hourly Chime Functions ------------------------------------------------------------------------------ *2505 - Speak Time *2536 - Speak Date *2535 - Enable Hourly Chime *2534 - Disable Hourly Chime *2539 - Curly Routine (scheduled during chime disabled) ------------------------------------------------------------------------------ MCW and Speech Functions ------------------------------------------------------------------------------ *2581 - Speech/CW Mode Usage: *2581n where n = the desired mode: 0 = Speech/CW Disabled 1 = CW Only Mode 2 = Speech/CW Mode The MCW ID is always enabled. Speech/MCW Disable only disables feedback functions such as ON/OFF announcements and other non-essential readouts. ------------------------------------------------------------------------------ Courtesy Tone Functions ------------------------------------------------------------------------------ *2583 - 6M Courtesy Tone Mode *2584 - 450 Courtesy Tone Mode Usage: *2583n where n = the desired mode 0 = Disabled 1 = First Key-Up Mode 2 = Each Key-Up Mode ------------------------------------------------------------------------------ 450 Transmit Time Limiter ------------------------------------------------------------------------------ *2531 - Enable 450 TX Time Limit *2530 - Disable 450 TX Time Limit ------------------------------------------------------------------------------ Antenna Relay ------------------------------------------------------------------------------ *2541 - Antenna #1 *2542 - Antenna #2 ------------------------------------------------------------------------------ Landline Control ------------------------------------------------------------------------------ Unlock: Call 582-8024. Press 0 when the phone answers. *2591 - Full Patch ON *2590 - Full Patch OFF *2597 - Monitor Mode ON *2596 - Monitor Mode OFF *2598 - Reset Landline Control ------------------------------------------------------------------------------ *2599 - Master Reset User Functions (all *2500 codes) to ROM defaults ============================================================================== Control Functions Series *6900 Codes: ============================================================================== ------------------------------------------------------------------------------ Autopatch Control Functions ------------------------------------------------------------------------------ *6901 - Autopatch Enable *6900 - Autopatch Disable *6902 - Program Speed Dialer Usage: *6902snnnnnnnnnn where S = slot # (0 to 9) to program and nnnnnnnnnn = up to 10 digits to save in that slot *6903 - Speak Speed Dialer Numbers Usage: *6903S where S = slot # (0 to 9) to read *6963 - Ring Detector Enable *6962 - Ring Detector Disable ------------------------------------------------------------------------------ DTMF Decoder Control Functions ------------------------------------------------------------------------------ *6921 - 450 DTMF PL Enable *6920 - 450 DTMF PL Disable *6923 - 6M DTMF PL Enable *6922 - 6M DTMF PL Disable *6925 - DTMF Mute Enable *6924 - DTMF Mute Disable ------------------------------------------------------------------------------ Clock/Calendar Control Functions ------------------------------------------------------------------------------ *6911 - Set Time Usage: *6911hhmmss where hh = hours in 24 hour format mm = minutes ss = seconds (optional) If the seconds are omitted, then the seconds are set to sero *6912 - Set Date Usage: *6912mmddyyyy where mm is the month (1 to 12) dd is the day of the month (1 to 31) yyyy is the full year (1991) other valid date sequences are: *6912mmdd *6912mmddyy (where yy is the last two digits of the year) *6913 - Events Usage: *6913ephhmmccccc where e is the event (0 to 9) p is the priority (0=low, 1=hi) hh is the hours (24 hour format) mm is the minutes cccccc is the control code (i.e. *2511 or silent command **2511) *6913e with no parameters toggles active/inactive status *6914 - Subtract one hour from current time to return to Standard Time *6915 - Add one hour to current time to return to Daylight Savings Time ------------------------------------------------------------------------------ Main Receivers Control Functions ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ Six Meter Receiver Functions ------------------------------------------------------------------------------ *6971 - 6M RX Enable (PL Enabled) *6970 - 6M RX Disable *6972 - 6M RX Enable (PL Disabled) *6974 - 6M PL Time-Out Inhibit ON *6973 - 6M Time-out Inhibit OFF *6976 - 6M Temp PL Override Enabled *6975 - 6M Temp PL Override Disabled ------------------------------------------------------------------------------ UHF Receiver Functions ------------------------------------------------------------------------------ *6981 - 450 RX Enable (PL Enabled) *6980 - 450 RX Disable *6982 - 450 RX Enable (PL Disabled) *6984 - 450 PL Time-Out Inhibit ON *6983 - 450 Time-out Inhibit OFF *6986 - 450 Temp PL Override Enabled *6985 - 450 Temp PL Override Disabled ------------------------------------------------------------------------------ Two Meter Link System Functions ------------------------------------------------------------------------------ *6904cffffmp - Program 2M Preset Frequencies where: 'c' is the channel 'ffff' is the freq (6880 = 146.880) This function also selects 'm' is the mode Channel 'c' as the Active Channel 0 = Simplex 1 = Auto-Repeat 2 = Auto-Inverse ------------------------------------------------------------------------------ Main Transmitters Control Functions ------------------------------------------------------------------------------ *6991 - 450 TX Enable *6990 - 450 TX Disable *6993 - 6M TX Enable *6992 - 6M TX Disable *6961 - Preset Transmit Time to 5 Minutes for testing (The next receiver input will preset back to 5 seconds) *6933 - Test Tone Deviation ON *6932 - Test Tone Deviation OFF *6935 - Test Speech Deviation ON *6934 - Test Speech Deviation ON ------------------------------------------------------------------------------ Macro Control Speed Commands ------------------------------------------------------------------------------ #0 to #9 - Programmed Macro Functions *6952 - Program Macro Functions Usage: *6952n*xxxx where n = macro key 0 to 9 *xxxx = the Control Code to save (i.e. *2501) *6951 - Macro Functions Enable *6950 - Macro Functions Disable ------------------------------------------------------------------------------ Miscellaneous Control Functions ------------------------------------------------------------------------------ *6954 - User Codes Enable *6953 - User Codes Disable *6930aaaa - Memory Read *6931aaaa#0dd - Memory Write where: aaaa = address in hex dd = data in hex to enter hex alpha characters, use the two-digit DTMF sequence - #1=A, #2=B, #3=C, #4=D, #5=E, #6=F and #0 is the space char separating aaaa and dd. *2599 - User Functions Reset *6999 - Controller Master Reset and default system parameters from ROM Placing a "*" in front of any 4-digit command sequence (i.e. **2501 instead of *2501) will disable speech or MCW transpond of the results of the command. ------------------------------------------------------------------------------- ~ .comment ~ ============================================================================== Modifications: (sub-versions are diferentiated only by sign-on date) Version 1.0 Program started on 09/22/1990 Version 1.3 11/02/1991 Version 1.5 03/12/1992 Version 1.5 09/23/1994 Fixed bug in TISR which caused time-out timers to start running if a main receiver was disabled by control. Version 1.5 10/29/1994 Fixed bug in the Daylight/Standard +1/-1 hour function which did not properly add one hour at 9 am or 7 pm and did not properly subtract one hour at 10 am or 8 pm. ============================================================================== This is a surplus single-board 8085 based computer which was removed from Kodak Ektachem Blood Analyzers during a modification. The board can accept an 8K, 16K or 32K EPROM and has 4K of Static Ram, a Programmable Interval Timer (PIT), a Programmable Peripheral Interface (PPI), a Programmable Interrupt Controller (PIC), a Universal Synchronous/Asynchronous Receiver-Transmitter (USART), four 8-bit output ports and three 8-bit input ports (not including the I/O ports on the PPI). This SBC uses memory-mapped I/O conforming to the following chart: Program ROM 00000H to 01FFFH - 8K EPROM 2764 A15 or 00000H to 03FFFH - 16K EPROM 27128 A15 or 00000H to 07FFFH - 32K EPROM 27256 A15 requires one wire and one cut land for each increase in ROM size Static RAM 08000H to 087FFH - 2K RAM 6116 CS0 Static RAM 08800H to 08FFFH - 2K RAM 6116 CS1 I/O Device 09000H to 09003H - PPI 8255 CS2 I/O Device 09800H to 09801H - PIC 8259 CS3 I/O Device 0A000H to 0A001H - USART 8251 CS4 I/O Device 0A800H to 0A803H - PIT 8253 CS5 I/O Device 0B000H to 0B007H - Ports 0 to 7 CS6 The following I/O assignments are decoded on the auxiliary board and not part of the computer main board: Output Port 0C000H to 0CFFFH - SSI-263 Speech IC (uses 0C000H to 0C007H) Output Port 0D000H to 0D005H - MM58177 Clock IC (uses 0D000H to 0D01FH) Output Port 0E000H to 0EFFFH - SSI-75T2089 DTMF Encoder/Decoder (uses 0E000H bits 0-1-2-3 for Encoder) Input Port 0D000H to 0DFFFH - MM58167 Clock IC (uses 0D000H to 0D01FH) Input Port 0E000H to 0EFFFH - SSI-202 DTMF Decoder IC (uses 0E000H bits 0-1-2-3) SSI-75T2089 DTMF Encoder/Decoder IC (uses 0E000H bits 4-5-6-7 for Decoder) A modification to the circuit is required at U4. The wire on U4 pin 4 is removed and pin 4 is connected to address line A14. This will make U4 unambiguously decode device selects which will not contend with device selects made by the 74LS138 on the Auxiliary Board. ---------------------- End of Comment Text ------------------------------------ ~ ;============================================================================= true equ 0ffh yes equ 0ffh false equ 0 no equ 0 ;============================================================================= .printx WA1LMV Repeater Controller Software .printx ;.printx Enter the Processor Clock Crystal Frequency in KHz. ;.printx ;.accept 'Valid choices are 5185 or 8000 --> ', clock ;.printx .printx Please wait while assembly continues ... .printx clock equ 5185 ; CPU Clock ;clock equ 8000 ; (wishful thinking) ;============================================================================= ; SSI-263 Speech Synthesizer Port Equates sbase equ 0c000h ; Base Port durphon equ sbase ; Duration/Phoneme Register 0 inflect equ sbase+1 ; Inflection Pitch Register 1 rateinf equ sbase+2 ; Rate/Inflection Register 2 cttramp equ sbase+3 ; Control/Articulation/Amplitude Register 3 filfreq equ sbase+4 ; Filter Frequency Register 4 ;============================================================================= ; SSI-202P Radio DTMF Decoder Port Equates dbase equ 0e000h ; Base Port (lower nibble) rdmsk equ 00001111b rdvmsk equ 10000000b ; Radio DTMF Data Valid Mask (Port 0) ;============================================================================= ; SSI-75T2089 Telephone DTMF Decoder/Encoder Port Equates ; dbase equ 0e000h ; Base Port (upper nibble) tdmsk equ 11110000b ; Port 8 is the data port for the 2089 DTMF Encoder ;============================================================================= ; MM58167 Clock/Calendar IC Port Equates ; Not all ports are used cbase equ 0d000h ; Base Port sec equ cbase+2 ; Seconds min equ cbase+3 ; Minutes hrs equ cbase+4 ; Hours ;day equ cbase+5 ; Day of the Week date equ cbase+6 ; Day of the Month month equ cbase+7 ; Month year equ cbase+9 ; Year (in hundreths/tenths of seconds latch) ;lsec equ cbase+10 ; Seconds Latch ;lmin equ cbase+11 ; Minutes Latch lhrs equ cbase+12 ; Hours Latch ;lday equ cbase+13 ; Day of the Week Latch ;ldate equ cbase+14 ; Day of the Month Latch ;lmonth equ cbase+15 ; Month Latch ;cints equ cbase+16 ; Interrupt Status Latch (read only) ;cintc equ cbase+17 ; Interrupt Control Latch (write only) ;ccrst equ cbase+18 ; Counter Reset ;clrst equ cbase+19 ; Latch Reset cstat equ cbase+20 ; Status Bit ; Interrupt Mask for Status (read) and Control (write) registers ; D7 D6 D5 D4 D3 D2 D1 D0 ; Month Week Day Hour Minute Second 1/10 Comparator ; ** Note ** Version 1.3 changes clock operation from interrupt ; driven to polled operation in order to implement the event ; scheduler. ;============================================================================= ; 8255 Programmable Peripheral Interface Equates ppictl equ 09003H ; 8255 PPI control port ppimod equ 10100110b ; 8255 Mode ; |||||||| ; |||||||+-- Group B Port C (Lower) 1=Input 0=Output ; ||||||+--- Group B Port B 1=Input 0=Output ; |||||+---- Group B Mode Selection 1=Mode 1 0=Mode 0 ; ||||+----- Group A Port C (Upper) 1=Input 0=Output ; |||+------ Group A Port A 1=Input 0=Output ; ||+-----+- Group A Mode Selection 01=Mode 1 00=Mode 0 ; |+------+ 1X=Mode 2 ; +--------- Mode Set Flag 1=Active ; We need to set the PC5 bit because it controls ALE to ; enable the dedicated output ports on the board ppipc5 equ 00001010b ; |||||||| ; |||||||+-- Bit Set/Reset 1=Set 0=Reset ; ||||||+--- B0 ; |||||+---- B1 Bit Select ; ||||+----- B2 ; |||+------ x ; ||+------- x x = don't care ; |+-------- x ; +--------- Bit Set/Reset Flag 0=Active ;============================================================================= ; 8253 Programmable Interval Timer equates pitc0 equ 0A800H ; 8253 PIT Counter 0 pitc1 equ 0A801H ; 8253 PIT Counter 1 pitc2 equ 0A802H ; 8253 PIT Counter 2 pitctl equ 0A803H ; 8253 PIT contorl port pitcw equ 10110110b ; counter 2, mode 3 ; |||||||| ; |||||||+--- 0 = Binary 16 bits, 1 = BCD 4 decades ; ||||||+---- M0 -+ 000 = Mode 0, 001 = Mode 1 ; |||||+----- M1 -+ X10 = Mode 2, X11 = Mode 3 ; ||||+------ M2 -+ 100 = Mode 4, 101 = Mode 5 ; |||+------- RL0 -+ 00 = Counter Latching Operation ; ||+-------- RL1 -+ 01 = Read/Load MS byte only ; || 10 = Read/Load LS byte only ; || 11 = Read/Load LS byte first, then MS byte ; |+--------- SC0 -+ 00 = Select Counter 0, 01 = Select Counter 1 ; +---------- SC1 -+ 10 = Select Counter 2, 11 = Illegal ; Timing Constants to generate varouus audio frequencies if clock eq 5185 b2000 equ 1296 ; 2000 Hz. tone clock*(500/2000) b1200 equ 2160 ; 1200 Hz. tone clock*(500/1200) b1000 equ 2592 ; 1000 Hz. tone clock*(500/1000) b900 equ 2877 ; 900 Hz. tone clock*(500/900) b800 equ 3240 ; 800 Hz. tone clock*(500/800) b660 equ 3928 ; 660 Hz. tone clock*(500/660) b550 equ 4713 ; 550 Hz. tone clock*(500/550) b500 equ 5185 ; 500 Hz. tone clock*(500/500) b480 equ 5401 ; 480 Hz. tone clock*(500/480) b440 equ 5892 ; 440 Hz. tone clock*(500/440) endif ; clock eq 5185 if clock eq 8000 b2000 equ 2000 ; 2000 Hz. tone clock*(500/2000) b1200 equ 3333 ; 1200 Hz. tone clock*(500/1200) b1000 equ 4000 ; 1000 Hz. tone clock*(500/1000) b900 equ 4439 ; 900 Hz. tone clock*(500/900) b800 equ 5000 ; 800 Hz. tone clock*(500/800) b660 equ 6060 ; 660 Hz. tone clock*(500/660) b550 equ 7272 ; 550 Hz. tone clock*(500/550) b500 equ 8000 ; 500 Hz. tone clock*(500/500) b480 equ 8333 ; 480 Hz. tone clock*(500/480) b440 equ 9090 ; 440 Hz. tone clock*(500/440) endif ; clock eq 8000 ; Timing Constants to generate musical notes (not currently used) if clock eq 5185 mds5 equ 4165 ; 622.3 Hz. me5 equ 3928 ; 659.3 Hz. mf5 equ 3711 ; 698.5 Hz. mfs5 equ 3503 ; 740.0 Hz. mg5 equ 3306 ; 784.0 Hz. mgs5 equ 3121 ; 830.6 Hz. ma5 equ 2946 ; 880.0 Hz. mas5 equ 2780 ; 932.3 Hz. mb5 equ 2624 ; 987.8 Hz. mc6 equ 2477 ; 1046.5 Hz. mcs6 equ 2338 ; 1108.7 Hz. md6 equ 2206 ; 1174.7 Hz. mds6 equ 2083 ; 1244.5 Hz. me6 equ 1966 ; 1318.5 Hz. mf6 equ 1855 ; 1396.9 Hz. mfs6 equ 1751 ; 1480.0 Hz. mg6 equ 1653 ; 1568.0 Hz. mgs6 equ 1560 ; 1661.2 Hz. ma6 equ 1473 ; 1760.0 Hz. mas6 equ 1390 ; 1864.7 Hz. mb6 equ 1312 ; 1975.5 Hz. mc7 equ 1238 ; 2093.5 Hz. mcs7 equ 1169 ; 2217.5 Hz. bd7 equ 1103 ; 2349.3 Hz. mds7 equ 1041 ; 2489.0 Hz. endif ; clock eq 5185 if clock eq 8000 mds5 equ 6428 ; 622.3 Hz. me5 equ 6067 ; 659.3 Hz. mf5 equ 5727 ; 698.5 Hz. mfs5 equ 5405 ; 740.0 Hz. mg5 equ 5102 ; 784.0 Hz. mgs5 equ 4816 ; 830.6 Hz. ma5 equ 4545 ; 880.0 Hz. mas5 equ 4290 ; 932.3 Hz. mb5 equ 4049 ; 987.8 Hz. mc6 equ 3822 ; 1046.5 Hz. mcs6 equ 3608 ; 1108.7 Hz. md6 equ 3405 ; 1174.7 Hz. mds6 equ 3214 ; 1244.5 Hz. me6 equ 3033 ; 1318.5 Hz. mf6 equ 2863 ; 1396.9 Hz. mfs6 equ 2703 ; 1480.0 Hz. mg6 equ 2551 ; 1568.0 Hz. mgs6 equ 2408 ; 1661.2 Hz. ma6 equ 2272 ; 1760.0 Hz. mas6 equ 2145 ; 1864.7 Hz. mb6 equ 2025 ; 1975.5 Hz. mc7 equ 1911 ; 2093.5 Hz. mcs7 equ 1804 ; 2217.5 Hz. bd7 equ 1703 ; 2349.3 Hz. mds7 equ 1697 ; 2489.0 Hz. endif ; clock eq 8000 ;============================================================================= ; 8259 Programmable Interrupt Controller Equates pic0 equ 09800H ; 8259 port with A0=0 pic1 equ 09801H ; 8259 port with A0=1 ; Initialization Command Words icw1 equ 00010010b ; 8259 ICW1 with A0=0 and D4=1 ; |||||||| ; |||||||+-- always zero ; ||||||+--- 1=Single, 0=Not Single ; |||||+---- Address Interval 1=4, 0=8 ; ||||+----- always zero ; |||+------ always one ; ||+------- A5 -+ ; |+-------- A6 -+---- A7 to A5 of Lower Routine Address ; +--------- A7 -+ icw2 equ 00000000b ; 8259 ICW2 ; |||||||| ; |||||||+-- A8 --+ ; ||||||+--- A9 --+ ; |||||+---- A10 -+ ; ||||+----- A11 -+---- Upper Routine Address ; |||+------ A12 -+ ; ||+------- A13 -+ ; |+-------- A14 -+ ; +--------- A15 -+ ; Operation Command Words ocw1 equ 11010001b ; 8259 OCW1 witn A0=1 ; |||||||| ; |||||||+-- IR0 (enable IR1,IR2,IR3 and IR5) ; ||||||+--- IR1 ; |||||+---- IR2 ; ||||+----- IR3 0 = Mask Reset (Interrupt Enabled) ; |||+------ IR4 1 = Mask Set (Interrupt Disabled) ; ||+------- IR5 ; |+-------- IR6 ; +--------- IR7 ocw2 equ 00000000b ; 8259 OCW2 with A0=0 ; |||||||| ; |||||||+-- A -+ ; ||||||+--- B -+--- BCD Value of the INT Level to be reset ; |||||+---- C -+ or put into lowest priority ; ||||+----- always zero ; |||+------ always zero ; ||+------- Non-Specific EOI 1=Reset Highest Priority bit of IS ; || 0=No Action ; |+-------- Specfic EOI 1=L2,L1,L0 Bits used, 0=No Action ; +--------- Rotate Priority 1=Rotate, 0=Not Rotate ;============================================================================= ; 8251 Universal Synchronous Receiver-Transmitter Equates ttyd equ 0A000H ; 8251 data port ttyc equ 0A001H ; 8251 control port ; 8251 Mode Instruction mode equ 01001110B ; 8251 mode instruction (Asynchronous) ; |||||||| ; |||||||+-- B1 Baud Rate Factor 00=Sync Mode ; ||||||+--- B2 01=1X 10=16X 11=64X ; |||||+---- L1 Character Length 00=5 Bits ; ||||+----- L2 01=6 Bits 10=7 Bits 11=8 Bits ; |||+------ Parity 1=Enable 0=Disable ; ||+------- Parity Generation/Check 1=Even 0=Odd ; |+-------- S1 Stop Bits 00=invalid 01=1 Bit ; +--------- 10=1.5 Bits 11=2 Bits ; 8251 Command Instruction cmd equ 00110111B ; 8251 command word ; |||||||| ; |||||||+-- TxEN 1=enable 0=disable ; ||||||+--- DTR 1=Force DTR output low ; |||||+---- RxE 1=enable 0=disable ; ||||+----- SBRK 1=force TxD low 0=normal operation ; |||+------ ER Error Reset 1=reset error flags PE OE FE ; ||+------- RTS 1=Force RTS output low ; |+-------- IR Internal Reset 1=force 8251 into Mode Format ; +--------- EH Enter Hunt Mode 1=enable search for sync ; 8251 Status Read Byte Format ; bbbbbbbb ; 76543210 ; |||||||| ; |||||||+-- TxREADY ; ||||||+--- RxREADY ; |||||+---- TxEMPTY ; ||||+----- PE ; |||+------ OE ; ||+------- FE ; |+-------- SYNDET ; +--------- DSR dsrmsk equ 10000000b ; DSR Mask rxrdy equ 00000010b ; RxREADY Mask ; 8251 Command Instruction to return to Mode Instruction Format cmdrst equ 01000000b ; 8251 reset command word ; 8251 RxRDY and TxEMPTY Bit Masks inmask equ 00000010B ; Rx Ready Mask outmask equ 00000100B ; Tx Ready Mask ;============================================================================= ; Various Signal Definitions ; Input Port 0 port0 equ 0B000H spreq equ 00000001b ; SSI-263 Request Data lmic equ 00000010b ; Local Mic PTT pdint equ 00100000b ; SSI-75T2089 Phone DTMF Interrupt IR1 ;ckint equ 01000000b ; MM58167 Clock Interrupt IR2 rdint equ 10000000b ; SSI-263 Radio DTMF Interrupt IR3 ; Input Port 1 port1 equ 0B001H ; Receivers vrcos equ 00000001b ; 6M COS Mask vrtos equ 00000010b ; 6M TOS Mask urcos equ 00000100b ; 450 COS Mask urtos equ 00001000b ; 450 TOS Mask a1cos equ 00010000b ; Aux RX #1 COS Mask a2cos equ 00100000b ; Aux RX #2 COS Mask ring equ 01000000b ; phone ring detector ; Input Port 2 port2 equ 0B002H ; Spare ; Output Port 4 port4 equ 0B004H mcwt equ 00000001b ; MCW Tone Mask iclr equ 00000010b ; landline relay ptmon equ 00000100b ; Patch Monitor wdog equ 10000000b ; Watchdog Timer Mask ; Output Port 5 port5 equ 0B005H ; Spare ; Output Port 6 port6 equ 0B006H ; Audio Gates vag equ 00000001b ; 6M A Gate Mask vbg equ 00000010b ; 6M B Gate Mask vdg equ 00000100b ; 6M D gate Mask uag equ 00001000b ; 450 A Gate Mask ubg equ 00010000b ; 450 B Gate Mask udg equ 00100000b ; 450 D Gate Mask a1ag equ 01000000b ; Aux RX #1 A Gate Mask a2ag equ 10000000b ; Aux RX #2 A Gate Mask ; Output Port 7 port7 equ 0B007H ; Transmitters, Autopatch vtx equ 00000001b ; 6M TX Mask utx equ 00000010b ; 450 TX Mask ptchr equ 00000100b ; Patch Relay a1tx equ 00001000b ; Aux TX #1 Mask a2tx equ 00010000b ; Aux TX #2 Mask idptt equ 00100000b ; ID/Speech PTT Mask ptchg equ 01000000b ; Patch Gate antt equ 10000000b ; Antenna Relay ; Output Port 8 port8 equ 0E000H ; DTMF Decoder/Dialer on Aux Board dgend equ 00001111b ; DTMF Generator Data Mask dgenc equ 00010000b ; DTMF Generator Clock Mask ; Input Port 8 ;dbase equ 0E000H ; DTMF Decoders on Aux Board ;rdmsk equ 00001111b ; these are already defined and ;tdmsk equ 11110000b ; are here for info only ;============================================================================= ; Memory equates rombase equ 00000H ; 32K ROM between 0000-7FFFH romtop equ 07FFFH rambase equ 08000H ; 4K RAM between 8000-8FFFH ramtop equ 08FFFH ;============================================================================= ; ASCII Equates bell equ 7 ; CRTL G (bell) ctrh equ 8 ; CTRL H (BACKSPACE) ctrc equ 3 ; CTRL C ctrs equ 19 ; CTRL S ctrq equ 17 ; CTRL Q backup equ ctrh ; BACKUP CHAR del equ 127 ; RUBOUT esc equ 27 ; ESCAPE apos equ (39-'0') and 0ffh cr equ 13 ; CARRIAGE RETURN lf equ 10 ; LINE FEED ;============================================================================= ; MACRO to resolve 8085 SIM instruction sim macro defb 30h endm ;============================================================================= org rombase di jp start org 00008h ; RST 1 jp tdisr ; Telephone DTMF Interrupt org 00010h ; RST 2 ret org 00018h ; RST 3 jp rdisr ; Radio DTMF Interrupt org 00020H ; RST 4 ret org 00024h ; TRAP interrupt ret org 0028h ; RST 5 jp kisr ; Console Interrupt Service Routine org 0002ch ; RST 5.5 ret org 00030h ; RST 6 ret org 00034h ; RST 6.5 ret org 0038h ; RST 7 jp erst ; error trap, run-away system attempting ; to execute non-existent memory locations, ; the floating bus appears as an RST 7 org 003ch ; RST 7.5 jp tisr ; Timer Interrupt Service Routine ; Install copyright notice in the EPROM defb 'Copyright 1990,1993 by Rick Swenton, WA1LMV' subttl System Data Table ; place the system data table here page include sysdef.z80 ;============================================================================= ; File SYSDEF.Z80 -- System Default Configuration Parameters ;============================================================================= ; The WA1LMV Repeater Controller Software has established ; system start-up default parameters saved in EPROM and ; copied to RAM during the first cold start. ; The master reset command (*6998) also completely refreshes ; the contents of RAM with the default startup values in EPROM. ;============================================================================= ; System Data Table -- copied to RAM during cold start ;============================================================================= ; Select CRT Terminal Type ADDS equ no ; ADDS A2 A2020 equ yes ; ADDS 2020 HEATH equ no ; Heath H19/H29 ; WARNING! This table must be in the same order and contain ; the same number of bytes that are defined in the RAM Data Table ; which is the final destination of this table systbl: ; Default System Start-Up Conditions ; Initialize I/O Port Control Bytes ; (some bits read/written direct and can not be disabled) ; Input Ports: defb 11111111b ; port0c Input Port 0 ; |||||||| ; |||||||+-- SSI-263 Request Data (read direct) ; ||||||+--- lmic Local Mic PTT ; |||||+---- not used ; ||||+----- not used ; |||+------ IR0 ; ||+------- IR1 SSI-75T2089 Data Valid (read direct) ; |+-------- IR2 MM58167 INT (read direct) ; +--------- IR3 SSI-202P Data Valid (read direct) defb 11001010b ; port1c Receivers P1 ; |||||||| ; |||||||+-- vrcos 6M COS ; ||||||+--- vrtos 6M TOS ; |||||+---- urcos 450 COS ; ||||+----- urtos 450 TOS ; |||+------ a1cos AUX RX #1 COS ; ||+------- a2cos AUX RX #2 COS ; |+-------- ring Landline Ring Detector ; +--------- not used defb 11111111b ; port2c Input Port 2 ; |||||||| ; |||||||+-- not used ; ||||||+--- not used ; |||||+---- not used ; ||||+----- not used ; |||+------ not used ; ||+------- not used ; |+-------- not used ; +--------- not used ; Output Ports: defb 11111111b ; port4c Output Port 4 ; |||||||| ; |||||||+-- mcwt Audio Tone Gate (write direct) ; ||||||+--- iclr Landline Relay ; |||||+---- ptmon Monitor Mode ; ||||+----- not used ; |||+------ not used ; ||+------- not used ; |+-------- not used ; +--------- wdog Watchdog Timer (write direct) defb 11111111b ; port5c Output Port 5 ; |||||||| ; |||||||+-- not used ; ||||||+--- not used ; |||||+---- not used ; ||||+----- not used ; |||+------ not used ; ||+------- not used ; |+-------- not used ; +--------- not used defb 11111111b ; port6c Audio Gates P5 ; |||||||| ; |||||||+-- vag 6M A Gate ; ||||||+--- vbg 6M B Gate ; |||||+---- vdg 6M D Gate ; ||||+----- uag 450 A Gate ; |||+------ ubg 450 B Gate ; ||+------- udg 450 D Gate ; |+-------- a1ag AUX RX #1 A Gate ; +--------- a2ag AUX RX #2 A Gate defb 11100111b ; port7c Transmitters P6 ; |||||||| ; |||||||+-- vtx 6M Transmitter ; ||||||+--- utx 450 Transmitter ; |||||+---- ptchr Patch Relay ; ||||+----- a1tx Aux TX #1 ; |||+------ a2tx Aux TX #2 ; ||+------- idptt ID PTT ; |+-------- ptcgh Patch Gate ; +--------- not used defb no ; CRT update enable uflag defb 0 ; CRT update mode umode defb yes ; Macro Functions enable mflag defb yes ; UAD Functions enable uadflg defb 2 ; MCW Mode control cwena ; 0 = Disabled, 1=MCW only, 2=Speech defb 1 ; default 6M courtesy tone mode vctmod defb 1 ; default 450 courtesy tone mode uctmod ; 0 = Disabled, 1 = First Key-Up ; 2 = Each Key-Up defb yes ; DTMF Mute enable dmutc defb yes ; Autopatch enable ptchc defb no ; 6M DTMF PL enable dtplv defb no ; 450 DTMF PL enable dtplu defb no ; 6M PL Time-out Inhibit vpltf defb no ; 450 PL Time-out Inhibit upltf defb yes ; 6M Temp PL override enable vplom defb yes ; 450 Temp PL override enable uplom defb no ; hourly chime enable chena defb yes ; 450 TX activity limit limuhf systbc equ $ ; Control System Unlock Codes ; User Functions (*2500 Series) ; First two digits to unlock the user functions defb '2' ; first unlock digit defb '5' ; second unlock digit ; Control Functions (*6900 Series) ; First two digits to unlock the control functions defb '6' ; first unlock digit defb '9' ; second unlock digit ; Time constants -- ** are in 10 ms. increments ; * are in 1 ms. increments defw 5*100+2 ; default main tx hang time (5 sec) ** defb 850/10 ; default aux tx hang time (850 ms) ** defb 2*10 ; default IDPTT delay time (2 sec) ** defw b2000 ; default MCW tone pitch defw 7*60*100+2 ; default ID timer time (7 mins.) ** defw 3*60*100+2 ; default Time Out timer (3 Mins.) ** defb 250/10 ; default 6M access delay (250 ms) ** defb 750/10 ; default 6M release delay (750 ms) ** defb 40/10 ; default 6M audio access delay (40 ms) ** defb 250/10 ; default 450 access delay (250 ms) ** defb 750/10 ; default 450 release delay (750 ms) ** defb 40/10 ; default 450 audio access delay (40 ms) ** defb 250/10 ; default Aux R1 access delay (250 ms) ** defb 750/10 ; default Aux R1 release delay (750 ms) ** defb 250/10 ; default Aux R2 access delay (250 ms) ** defb 750/10 ; default Aux R2 release delay (750 ms) ** defw 10*60*100+2 ; default Aux TX On Time (10 Mins) ** defw 1*60*100 ; default Temp PL Override Time (1 Min) ** defw 10*60*100+8 ; default 450 TX activity limit (10 Mins) ** defw 5*60*100+8 ; default 450 TX activity reset (5 Mins) ** defb 45 ; default MCW dot length (MCW Speed) * defw 2*60*100+2 ; default patch timer (2 Mins) ** defb 2*100 ; default control time-out (2 sec) ** defb 2*100 ; default radio DTMF Mute delay (2 sec) ** defb 2*100 ; default telephone DTMF Mute delay (2 sec) ** defb 100/10 ; default Radio DTMF Data Valid Delay (100 ms)* defw 20*100 ; default DTMF pass-through time (20 sec) ** defb 4 ; default max rings to answer (4) defw 8*100 ; default ring-to-ring delay (8 sec) ** defw 5*100 ; default answer control time (5 sec) ** defw 45*100 ; default answer hold time (45 sec) ** defw 10*60*100+2 ; default maximum landline time (10 mins) ** defw 40*100 ; default landline courtesy time (40 sec) ** defb 250/10 ; CRT refresh time (250 ms) ** defb 'R' ; Aux RX #1 Indicator Char defb 'R' ; Aux RX #2 Indicator Char defb 'T' ; Aux TX #1 Indicator Char defb 'T' ; Aux TX #2 Indicator Char defb 090h ; Speech Rate defb 1 ; Inflection Rate (0 to 7) defb 7 ; Articulation rate (0 to 7) defb 500/10 ; default ring detect delay (500 ms) ** defb 19h ; default century ; Speed Dialer Table of 10 Default Numbers. ; 12 bytes per entry including trailing 0ffh end of entry marker. ; The first entry #0 is empty because that slot is used to store ; the last manually dialed number for redialing. If the first byte ; of the table is 0FFH, the entry is considered empty and no ; action will be taken, i.e. dialing or speaking. An MCW "no" ; message will be generated. defb 0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh ;#0 defb 5,8,9,7,2,9,7,0ffh,0ffh,0ffh,0ffh,0ffh ; LMV ;#1 defb 5,8,3,7,9,6,6,0ffh,0ffh,0ffh,0ffh,0ffh ; SZU ;#2 defb 4,8,5,1,4,0,6,0ffh,0ffh,0ffh,0ffh,0ffh ; ZSG ;#3 defb 5,8,2,9,8,8,2,0ffh,0ffh,0ffh,0ffh,0ffh ; ZDF ;#4 defb 5,8,2,5,9,4,4,0ffh,0ffh,0ffh,0ffh,0ffh ; YHM ;#5 defb 5,8,5,9,4,4,7,0ffh,0ffh,0ffh,0ffh,0ffh ; LMV ;#6 defb 5,8,9,0,9,6,0,0ffh,0ffh,0ffh,0ffh,0ffh ; Telco Test ;#7 defb 5,8,4,2,8,1,1,0ffh,0ffh,0ffh,0ffh,0ffh ; SHC ;#8 defb 5,8,2,8,1,4,3,0ffh,0ffh,0ffh,0ffh,0ffh ; State Police ;#9 ; Programmed Macro Functions ; This is a table of ten ASCII entries of five characters defb 'A2500' ; #0 Autopatch Off defb 'A2501' ; #1 Autopatch On defb 'A2502' ; #2 Speed Dial defb 'A2503' ; #3 Speak Last Number defb 'A2541' ; #4 Antenna #1 defb 'A2505' ; #5 Curly defb 'A2506' ; #6 Time defb 'A2542' ; #7 Antenna #2 defb 'A2508' ; #8 MCW ID defb 'A2509' ; #9 Voice ID ; Programmed Scheduled Events ; This is a table of ten ASCII entries 9 bytes each ; in the format: ; (Control FLag) (Priority Flag) HH MM C1 C2 C3 C4 C5 C6 ; Control Flag: 00H = Not Active ; 80H = Active, Not Pending ; FFH = Active, Pending ; Priority Byte: 00H = Low Priority ; FFH = High Priority ; ; Low Priority will cause event to be ; skipped if repeater is in use ; ; High Priority will cause event to ; be executed even if repeater is in use ; Time: HH MM Hours and Minutes in Packed BCD ; Six chars per command (C1 C2 C3 C4 C5 C6) allows the ; silent command prefix if desired, i.e. A06972 ; 1 2 3 4 5 6 7 8 9 A defb 0,0,0,0,0,0,0,0,0,0 ; Event #0 defb 0,0,0,0,0,0,0,0,0,0 ; Event #1 defb 0,0,0,0,0,0,0,0,0,0 ; Event #2 defb 0,0,0,0,0,0,0,0,0,0 ; Event #3 defb 0,0,0,0,0,0,0,0,0,0 ; Event #4 defb 0,0,0,0,0,0,0,0,0,0 ; Event #5 defb 0,0,0,0,0,0,0,0,0,0 ; Event #6 defb 0,0,0,0,0,0,0,0,0,0 ; Event #7 defb 0ffh,00h,00h,00h,'A2539 ' ; Event #8 defb 0ffh,00h,12h,00h,'A2539 ' ; Event #9 ; Programmed Two Meter Remote Base Frequencies ; Enter the whole frequency in ASCII including the decimal point ; Define values for modes and power levels sx equ '0' ; simplex mode rpt equ '1' ; auto-repeat mode inv equ '2' ; auto-inverse mode lp equ '0' ; low power hp equ '1' ; high power ; 1234567 defb '146.520',rpt,hp ; CH 0 - 146.520 Repeat High Power defb '146.880',rpt,lp ; CH 1 - 146.880 Repeat Low Power defb '147.150',rpt,lp ; CH 2 - 147.150 Repeat Low Power defb '146.685',rpt,lp ; CH 3 - 146.685 Repeat Low Power defb '146.445',sx,hp ; CH 4 - 146.445 Simplex High Power defb '147.510',sx,hp ; CH 5 - 147.510 Simplex High Power defb '146.520',sx,hp ; CH 6 - 146.520 Simplex High Power defb '146.520',sx,hp ; CH 7 - 146.520 Simplex High Power defb '146.520',sx,hp ; CH 8 - 146.520 Simplex High Power defb '146.520',sx,hp ; CH 9 - 146.520 Simplex High Power defb 9 ; Two Meter Active Channel ; CRT Definitions - always one trailing zero if ADDS defb esc,'0','A',esc,'6',0 ; initialization string - 6 bytes defb 0 defb 14,0,0,0 ; dim string - 4 bytes defb 0 defb 15,0,0,0 ; bright string - 4 bytes defb 0 defb 0ch,0,0,0 ; clear screen - 4 bytes defb 0 defb 24,esc,'6',0 ; cursor on string - 4 bytes defb 0 defb 23,0,0,0 ; cursor off string - 4 bytes defb 0 endif ; ADDS if A2020 defb esc,'0','P',esc,'6',0 ; initialization string - 6 bytes defb 0 defb 14,0,0,0 ; dim string - 4 bytes defb 0 defb 15,0,0,0 ; bright string - 4 bytes defb 0 defb 0ch,0,0,0 ; clear screen - 4 bytes defb 0 defb 24,esc,'6',0 ; cursor on string - 4 bytes defb 0 defb 23,0,0,0 ; cursor off string - 4 bytes defb 0 endif ; A2020 if HEATH defb 0,0,0,0,0,0 ; initialization string - 6 bytes defb 0 defb esc,'p',0,0 ; reverse video string - 4 bytes defb 0 defb esc,'q',0,0 ; normal video string - 4 bytes defb 0 defb esc,'E',0,0 ; clear screen - 4 bytes defb 0 defb esc,'y','5',0 ; cursor on string - 4 bytes defb 0 defb esc,'x','5',0 ; cursor off string - 4 bytes defb 0 endif ; HEATH sysend equ $ ; end of table marker ; Calculate the size of this table to later compare with the size of ; its destination table in RAM syslen equ sysend-systbl ;--------------------- End of System Data Table ---------------------------- ;--------------------- end of file SYSDEF.Z80 ------------------------------ subttl page ; Power-up start start: ld a,3 ld (merr),a ; preset controller error byte startr: di ; Disable interrupts ld a,00011011b ; Interrupt Mask for INT 7.5 sim ld sp,stack ; Set the stack pointer ; Initialize the Hardware ; Set-up the 8259 PIC ld a,icw1 ; Set 8259 ICW1 ld (pic0),a ld a,icw2 ; Set 8259 ICW2 ld (pic1),a ld a,ocw1 ; Set 8259 OCW1 ld (pic1),a ld a,ocw2 ; Set 8259 OCW2 ld (pic0),a ; Set-up the 8255 PPI ld a,ppimod ; Set PPI mode ld (ppictl),a ld a,ppipc5 ; Set PC5 bit ld (ppictl),a ;============================================================================= ; Set-up the 8253 PIT to generate 1ms. ticks ; (RST 7.5 is used because it is edge triggered) ;============================================================================= ld a,pitcw ; PIT Control Word (counter 2, mode 3) ld (pitctl),a ld a,low((clock/2)*1) ; Initial counter value LSB ld (pitc2),a ld a,high((clock/2)*1) ; Initial counter value MSB ld (pitc2),a ; ---------------------------------------------------------------------------- ; Set-up the 8251 USART for Console I/O ld a,mode ld (ttyc),a ; Set USART mode ld a,cmd ld (ttyc),a ; Set command ; ---------------------------------------------------------------------------- cold: ld hl,rambase ; Initialize all RAM ld bc,(ramtop-1)-rambase ; (merr) is saved at RAMTOP zloop: ld (hl),0 ; To zero inc hl dec bc ; no flags affected here! ld a,b ; test for zero in A or a,c jp nz,zloop ; Copy the System Data Table from its current location ; in ROM to an area in RAM ld hl,systbl ; source = system data table ld de,ramdat ; dest = location in RAM ld bc,sysend-systbl; # table entries call moveit ; block move ROM to RAM ; Hardware initialization complete cold1: di ld sp,stack xor a ld (iptr),a ; set-up input buffer pointer ld (optr),a ; set-up output buffer pointer ld (sbase),a ; mute speech chip just in case ld (port8),a ; reset port 8 separately ld a,0ffh ; block DTMF interrupts from ld (bdtmft),a ; telephone line decoder ei ; start letting those interrupts in ; Initialize SSI-263 Speech Synthesizer ld a,80h ; set to transitioned inflection ld (cttramp),a ; first set control bit ld a,11000000b ; set DR1 and DR0 ld (durphon),a ld a,70h ; now reset the control bit ld (cttramp),a ; The following stablizes the SSI-263 so that its first ; sounds after initial power up sound acceptable ld a,78h ; default amplitude ld (cttramp),a ld a,17 ; default inflection ld (inflect),a ld a,0e6h ; default filter freq ld (filfreq),a xor a ld (durphon),a ; turn off just in case ; Test for existance of the SSI-263 Speech Synthesizer chip ; after we tried to initialize it. call chksp ;----------------------------------------------------------------------------- ; Check for the existance of the MM58167 Clock/Calendar ;----------------------------------------------------------------------------- chkck: ld a,(lhrs) ; get the current value of hours latch ld b,a ; save ld a,55h ; load a value ld (lhrs),a ; into the latch ld a,(lhrs) ; get it back cp 55h ; same value? jp z,clkc1 ld a,0ffh ; flag clock inhibit ld (clkp),a jp clkc2 clkc1: ld a,b ; get the saved hours latch value ld (lhrs),a ; restore it clkc2: call cmenu jp warm ;============================================================================= ; Include the Interrupt Service Routines ;============================================================================= subttl Console Keyboard Interrupt Service Routine page include kisr.z80 subttl Console Keyboard Interrupt Service Routine ;============================================================================= ; Console Keyboard Interrupt Service Routine ;============================================================================= ; Careful! So far, this routine only uses register A. ; The subroutine PUTBUF saves its own registers. kisr: push af ; Pending character - Interrupt (IR5) ld a,(ttyd) ; get the character and 01111111b ; strip parity cp ctrs ; Control-S? jp nz,kisr1 ld a,0ffh ; set the XON flag to WAIT status ld (xon),a jp kisrd ; don't save in buffer kisr1: cp ctrq ; Control-Q? jp nz,kisr2 xor a ; set the XON flag to RUN status ld (xon),a jp kisrd ; don't save in buffer kisr2: call putbuf ; put character into buffer kisrd: ld a,01100101b ; SET 8259 OCW2 (reset IR5 IS bit) ld (pic0),a ; to indicate specific EOI pop af ei ret ;----------------------- end of file KISR.Z80 -------------------------------- subttl DTMF Interrupt Service Routine page include disr.z80 subttl DTMF Interrupt Service Routine ;============================================================================= ; DTMF Interrupt Service Routine ;============================================================================= ; Radio DTMF Interrupt Dispatcher rdisr: ei push hl push de push bc push af ld a,(bdtmfr) ; see if Radio DTMF interrupts are blocked or a jp nz,risre ; NZ = Blocked, do nothing xor a ; flag Decoder 0 - the SSI-202 ld (dtmfn),a ld hl,(mdfto) ; get the default RX time out value ld (vrtim),hl ; preset time-out timers ld (urtim),hl call disr ; Process end of specific interrupt for Decoder 0 (radio) risre: ld a,01100011b ; SET 8259 OCW2 (reset IR3 IS bit) ld (pic0),a ; to indicate specific EOI pop af pop bc pop de pop hl ret ;----------------------------------------------------------------------------- ; Phone DTMF Interrupt Dispatcher tdisr: ei push hl push de push bc push af ld a,(bdtmft) ; see if phone DTMF interrupts are blocked or a jp nz,tdsre ; NZ = Blocked, do nothing ld a,1 ; flag Decoder 1 - the SSI-75T2089 ld (dtmfn),a call disr ; Process end of specific interrupt for Decoder 1 (phone) tdsre: ld a,01100001b ; SET 8259 OCW2 (reset IR1 IS bit) ld (pic0),a ; to indicate specific EOI pop af pop bc pop de pop hl ret ;----------------------------------------------------------------------------- ; Main DTMF Service Routine disr: xor a ld (xon),a ; release X-ON just in case it is locked-up ; Max Landline Control Time and 450 RX inactivity limit ; are preset during each Data Valid interrupt ; from the either DTMF decoder. ld a,(llful) ; see if landline control unlocked or a ; 0ffh = Unlocked jp z,disr1 ; skip if not unlocked ld hl,(mdfmxl) ; get the default max landline time ld (maxll),hl ; preset counter to default time disr1: ld hl,(mdfulm) ; get the default 450 RX inactivity time ld (utxlim),hl ; preset counter to default time ld a,(dtmfn) ; which decoder? (0 = Radio, 1 = Phone) or a jp z,disr2 ; Process Decoder 1 (Telephone) ld a,(dbase) and tdmsk ; look only at upper 4-bits from DTMF rra ; rotate into lower position rra rra rra ld b,a ; save the char jp disr4 ; Process Decoder 0 (Radio) disr2: ld a,(dbase) ; read the input port and rdmsk ; look only at lower 4-bits from DTMF ld b,a ; save the char ld a,(crflag) ; get the CR flag or a jp nz,disr5 ; skip delay if it's not the first character ld a,(mdfrdv) ; get the default radio DTMF delay ld (rdvdly),a ; preset the delay disr3: ld a,(port0) ; read port 0 direct and rdvmsk ; look at radio DTMF Data Valid ret z ; bail out if it is not still there ld a,(rdvdly) ; get the remaining delay time or a jp nz,disr3 ; loop until delay done, only for first char disr4: ld a,0ffh ld (crflag),a ; set the CR Flag disr5: ld a,(mdfctl) ld (atime),a ; preset control time-out ld a,b ; get the char back cp 00001011b ; is it a *? jp nz,disr6 ld a,0ffh ; set the sflag ld (sflag),a ld a,'A' jp disr11 disr6: cp 00001100b ; is it a #? jp nz,disr7 ld a,(sflag) ; see if control sequence pending or a jp nz,disrx ld a,0ffh ; set the pflag ld (pflag),a ld a,'B' jp disr11 disr7: cp 00001010b ; is it a DTMF 0? jp nz,disr8 ld a,'0' jp disr9 disr8: cp 00001101b ; is it a DTMF A? jp z,disry cp 00001110b ; is it a DTMF B? jp z,disry cp 00001111b ; is it a DTMF C? jp z,disry cp 00000000b ; is it a DTMF D? jp z,disry ; Must be a valid digit from 0 to 9 add a,30h ; make into ASCII disr9: ld b,a ; save the char ld a,(alpha) ; alpha flag set? or a jp nz,disr15 ld a,(sflag) ; control sequence pending? or a jp nz,disr10 ld a,(pflag) ; macro sequence pending? or a jp nz,disr10 ; Only A (*) or B (#) are processed if Patch is ON or ; Landline Control is UNLOCKED. Everything else is discarded. ld a,(ptchm) ; see if the autopatch is on or a ; 0ffh = on jp nz,disrd ; don't save anything if patch is on ld a,(llful) ; see if landline control is unlocked or a ; 0ffh = unlocked jp nz,disrd ; don't save anything if landline control unlocked disr10: ld a,b ; get the char back disr11: call putbuf ; save the character in the buffer ld b,a ; save the char xor a ld (alpha),a ; reset the alpha flag disrd: ld a,(dtmfn) ; which decoder? (0 = Radio, 1 = Phone) or a jp z,disr13 ; Process DTMF Mute for Decoder 1 (Telephone) ld a,(sflag) ; control sequence pending? or a jp nz,disr12 ; force phone DTMF mute ld a,(pflag) ; macro sequence pending? or a jp nz,disr12 ; force phone DTMF mute ld a,(dmutc) ; get mute control flag or a jp z,disrd1 ; skip phone DTMF mute disr12: ld a,(mdftut) ; preset Telephone DTMF mute ld (tmute),a jp disrd1 ; Process DTMF Mute for Decoder 0 (Radio) disr13: ld a,(sflag) ; control sequence pending? or a jp nz,disr14 ; force radio DTMF mute ld a,(pflag) ; macro sequence pending? or a jp nz,disr14 ; force radio DTMF mute ld a,(dmutc) ; get mute control flag or a jp z,disrd0 ; skip phone DTMF mute disr14: ld a,(mdfrut) ; preset Radio DTMF mute ld (rmute),a ; jp disrd0 ;----------------------------------------------------------------------------- ; Done with Decoder Zero (radio) disrd0: ld a,b ; get the char back ld (digitr),a ; save ret ;----------------------------------------------------------------------------- ; Done with Decoder One (phone) disrd1: ld a,b ; get the char back ld (digitp),a ; save ret ;----------------------------------------------------------------------------- disry: ld a,'%' ; invalid char symbol jp disr10 ;----------------------------------------------------------------------------- ; A "#" came in during a control or macro sequence disrx: ld a,0ffh ; set alpha flag ld (alpha),a ld b,' ' ; default char jp disrd ;----------------------------------------------------------------------------- ; Alpha Flag is set. Next Character is translated. ; 1=A 2=B 3=C 4=D 5=E 6=F all others are a space " " disr15: ld a,b ; get the character back cp '0' ; zero? jp z,disr16 cp '7' ; greater than 6? jp nc,disr16 add 10h ; make '1' through '6' into alpha A through F jp disr11 disr16: ld a,' ' ; make everything else into a space jp disr11 ;--------------- end of DTMF Interrupt Service Routine ----------------------- ; DNUL - DTMF Pass-Through Routine dnul: ld a,0ffh ; block further DTMF interrupts ld (bdtmfr),a ; from radio decoder call stat defb 'DTMF Pass-Thru',0 call sndok ld hl,(mdfnul) ; get the default pass through delay ld (dnulm),hl ; preset the time ret ; interrupts re-enabled in the background ;--------------------- end of file DISR.Z80 ---------------------------------- subttl Timer Interrupt Service Routine page include tisr.z80 subttl Timer Interrupt Service Routine ;============================================================================= ; Timer Interrupt Service Routine ; (Highest Priority Interrupt) ;============================================================================= tisr: push hl push de push bc push af ; Error Trap - See if the stack is messed-up ld hl,0 add hl,sp ; get the stack pointer ld a,h ; get high nibble cp high(stack) ; is it in range? jp nz,irst ; reset if not ; The Refresh I/O Ports and Audio Gate routines are processed ; during each 1ms tick ;---------------------------------------------------------------------------- ; Refresh the I/O Ports ;---------------------------------------------------------------------------- ; Remember that the ports are memory-mapped and the ; cpu thinks they are memory. ; First do input ports 1 -> 2 ; The control byte is AND-ed with the inverted input port and ; saved in the status byte tisr1: ld a,(port0c) ; port 0 ld b,a ld a,(port0) cpl and a,b ld (port0s),a ld a,(port1c) ; port 1 ld b,a ld a,(port1) cpl and a,b ld (port1s),a ld a,(port2c) ; port 2 ld b,a ld a,(port2) cpl ld (port2s),a ; Now do output ports 4 -> 7 ; The control byte is ANDed with the status byte, then ; inverted, and sent to the respective output port. ld a,(port4c) ; port 4 ld b,a ld a,(port4s) and a,b ; cpl ld (port4),a ld a,(port5c) ; port 5 ld b,a ld a,(port5s) and a,b cpl ld (port5),a ld a,(port6c) ; port 6 ld b,a ld a,(port6s) and a,b cpl ld (port6),a ld a,(port7c) ; port 7 ld b,a ld a,(port7s) and a,b ; cpl ; don't invert port 7 ld (port7),a ;============================================================================= ; Process Audio Gates for 6M Receiver ;============================================================================= tiva1: ; The MICOR Squelch closes faster than the TOS without reverse ; burst. Always force the audio gate closed when COS goes away. ld a,(port1) ; read receivers direct cpl and vrcos ; look at 6M COS jp z,tiva2 ; Z = COS inactive ; Receiver coming on ld a,(vgdly) ; get the 6M audio gate access delay or a jp nz,tivd1 ; NZ = access delay not finished ; Receiver is on ld a,(port1s) ; read receivers and vrcos+vrtos ; lool at 6M COS and TOS ld b,a ; save ld a,(pltv) ; get 6M temp PL override flag and vrtos ; simulate TOS? or a,b jp z,tiva2 ; Z = COS, TOS and PL override inactive ld a,(rmute) ; get radio DTMF mute time or a jp z,tiva3 ld a,(port6s) and not vag ; mute 6M A gate or vbg ; keep the 6M B gate on ld (port6s),a jp tivd1 tiva2: ld a,(port6s) ; COS or TOS inactive and not(vag+vbg) ; turn off 6M A B gates ld (port6s),a ld a,(mdfvgd) ; preset the 6M audio gate access delay ld (vgdly),a jp tivd1 tiva3: ld a,(port6s) or vag+vbg ; turn on 6M A and B gates ld (port6s),a ; update audio gates tivd1: ld a,(port1) ; read receivers DIRECT cpl ; invert ld b,a ; save and vrcos ; COS on jp z,tivd3 ; Z = no, turn off D gate ld a,b ; restore and vrtos ; look at 6M TOS jp nz,tivd2 ; NZ = TOS on ; The COS is on all alone, see if ok to enable D gate ld a,(dtplv) ; 6M DTMF gate on PL? or a jp nz,tivd3 ; NZ = D Gate on PL, turn off D Gate tivd2: ld a,(port1) ; read receivers DIRECT cpl ; invert and urtos ; 450 PL signal has priority jp nz,tivd3 ; mute 6M D gate if 450 PL signal present ld a,(port6s) or vdg ; turn on 6M D gate ld (port6s),a jp tiua1 tivd3: ld a,(port6s) and not vdg ; turn off 6M D gate ld (port6s),a ;============================================================================= ; Process Audio Gates for 450 Receiver ;============================================================================= tiua1: ; The MICOR Squelch closes faster than the TOS without reverse ; burst. Always force the audio gate closed when COS goes away. ld a,(port1) ; read receivers direct cpl and urcos ; look at 450 COS jp z,tiua2 ; Z = COS inactive ; Receiver coming on ld a,(ugdly) ; get the 450 audio gate access delay or a jp nz,tiud1 ; NZ = access delay not finished ; Receiver is on ld a,(port1s) ; read receivers and urcos+urtos ; look at 450 COS and TOS ld b,a ; save ld a,(pltu) ; get 450 temp PL override flag and urtos ; simulate 450 TOS? or a,b jp z,tiua2 ; Z = COS, TOS and PL override inactive ld a,(rmute) ; get radio DTMF mute time or a jp z,tiua3 ld a,(port6s) and not uag ; mute 450 A gate or ubg ; keep the 450 B gate on ld (port6s),a jp tiud1 tiua2: ld a,(port6s) ; COS or TOS inactive and not(uag+ubg) ; turn off 450 A B gates ld (port6s),a ld a,(mdfugd) ; preset the 450 audio gate access delay ld (ugdly),a jp tiud1 tiua3: ld a,(port6s) or uag+ubg ; turn on 450 A and B gates ld (port6s),a ; update audio gates tiud1: ld a,(port1) ; read receivers DIRECT cpl ; invert ld b,a ; save and urcos ; look at 450 COS jp z,tiud3 ; Z = COS off, turn off D gate ld a,b ; restore and urtos ; look at 450 TOS jp nz,tiud2 ; NZ = TOS on ; The COS is on all alone, see if ok to enable D gate ld a,(dtplu) ; 450 DTMF gate on PL? or a jp nz,tiud3 ; NZ = D Gate on PL, turn off D Gate tiud2: ld a,(port6s) or udg ; turn on 450 D gate ld (port6s),a jp tiaa1 tiud3: ld a,(port6s) and not udg ; turn off 450 D gate ld (port6s),a ;----------------------------------------------------------------------------- ; Process Audio Gates for Auxiliary Receivers ;----------------------------------------------------------------------------- tiaa1: ld a,(ptchm) ; see if autopatch is on or a ; 0ffh = on jp nz,tiaa2 ; close gate if on ld a,(idptim) ; see if ID PTT is on or a ; NZ = on jp nz,tiaa2 ; close gate if on call grsd ; get main RX delayed COS status jp nz,tiaa2 ; close gate if active ld a,(port1s) ; read receivers and a1cos ; look at aux receiver #1 jp z,tiaa2 ld a,(port6s) or a1ag ld (port6s),a ; set aux R1 A gate jp tiaa3 tiaa2: ld a,(port6s) and not a1ag ; reset aux R1 A gate ld (port6s),a tiaa3: ld a,(ptchm) ; see if autopatch is on or a ; 0ffh = on jp nz,tiaa4 ; close gate if on ld a,(idptim) ; see if ID PTT is on or a ; NZ = on jp nz,tiaa4 ; close gate if on call grsd ; get main RX delayed COS status jp nz,tiaa4 ; close gate if active ld a,(port1s) ; read receivers and a2cos ; look at aux receiver #2 jp z,tiaa4 ld a,(port6s) or a2ag ; set aux R2 A gate ld (port6s),a jp tisrp tiaa4: ld a,(port6s) and not a2ag ; reset aux R2 A gate ld (port6s),a ;---------------------------------------------------------------------------- ; Interrupt Cycle Process Dispatcher ;---------------------------------------------------------------------------- tisrp: ld hl,idspd ; ID speed timer call bump ; service every 1ms interrupt ld a,(intcnt) ; get the current interrupt cycle count or a jp z,tiapt ; service autopatch cp 1 jp z,tistx ; service transmitters cp 2 jp z,tisst ; service timers cp 3 jp z,tissu ; service timers cp 4 jp z,tirxv ; service 6M receiver cp 5 jp z,tirxu ; service 450 receiver cp 6 jp z,tirxa ; service aux receiver #1 cp 7 jp z,tirxb ; service aux receiver #2 cp 8 jp z,tiidt ; service identifier cp 9 jp z,tirng ; service ring detector ;----------------------------------------------------------------------------- ; The "untick" bit reset is called here in the background. "Ticks" bit ; set are called from the foreground so that a crash of either foreground ; or background routines will cause a loss of watchdog heartbeat ; and eventual hardware-generated master reset. ;----------------------------------------------------------------------------- tisrd: ld a,(intcnt) ; get the current interrupt cycle count or a jp z,tisrd1 ; is it zero? dec a ; nope, bump down ld (intcnt),a ; save back jp tisrd2 tisrd1: ld a,9 ; it's zero, preset the cycle count ld (intcnt),a tisrd2: call untick ; process watchdog timer pop af pop bc pop de pop hl ei ret ;============================================================================ ; Service the Transmitters ;============================================================================ tistx: ld hl,(hang) ; transmitter hang timer ld a,h or a,l jp z,tist1 ; if zero, dump the transmitters dec hl ld (hang),hl ; bump down counter if not zero tistm: ld a,(port7s) ; get the port 7 status or utx+vtx ; turn on 6 and 450 TX bits ld b,a ; save ld a,(idptim) ; get the ID PTT time or a jp nz,tistb tista: ld a,(limuhf) ; get the 450 TX inactivity control flag or a jp z,tistb ld hl,(utxlim) ; get the 450 TX inactivity timer ld a,h or a,l jp nz,tistb ; keep 450 TX on if timer not zero ld a,b ; restore and not utx ; dump 450 TX jp tistc tistb: ld a,b ; restore tistc: ld (port7s),a ; output the contents ld hl,(mdfina) ; preset the repeater inactivity timer ld (unact),hl jp tist2 ; Hang Timer count is zero. Test for local Mic PTT tist1: ld a,(port0s) ; get port 0 status byte and lmic ; only look at Local Mic bit jp nz,tistm ; Mic is pressed, key transmitters ld a,(port7s) ; get port 7 status and not (utx+vtx) ; hang timed-out ld (port7s),a xor a ; reset courtesy tone control flags ld (cttflg),a ld (cttflv),a ld (cttflu),a tist2: ld a,(lhang) ; get the link TX hang timer or a jp z,tist3 dec a ld (lhang),a ld a,(rmute) ; get radio DTMF mute status or a ; dump link transmitters if jp nz,tist3 ; radio DTMF mute in progress ld a,(port7s) ; get the port 7 status or a1tx+a2tx ; turn on both link transmitters ld (port7s),a jp tisrd tist3: ld a,(port7s) ; get port7 status and not (a1tx+a2tx) ; turn off both link transmitters ld (port7s),a jp tisrd ; -------------------- end routine TISTX --------------------------------- ;============================================================================ ; Service Timers (Routine #1) ;============================================================================ ; Service the varoius Timers by counting them down ; until they reach zero, then stop counting! tisst: ld hl,idtim ; ID timer call bump2 jp nc,tiss1 ld (fidtm),a ; ID timer timed out tiss1: ld hl,vrtim ; 6M RX time out call bump2 jp nc,tiss2 ld (fberm),a ; request Beer message ld (fvtom),a ; 6M RX timed out tiss2: ld hl,urtim ; 450 RX time out call bump2 jp nc,tiss3 ld (fberm),a ; request Beer message ld (futom),a ; 450 RX timed out tiss3: ld hl,tmppl ; temp PL override time out call bump2 jp nc,tiss4 ld (ftplm),a ; temp PL timed out tiss4: ld hl,gpt ; general purpose timer call bump ld hl,crt ; CRT refresh refresh timer call bump jp nz,tiss5 ld a,0ffh ; set the foreground task flag ld (fucrm),a ; ready for CRT refresh tiss5: ld hl,vadly ; 6M access delay call bump ld hl,vrdly ; 6M release delay call bump ld hl,uadly ; 450 access delay call bump ld hl,urdly ; 450 release delay call bump ld hl,aadly ; R1 access delay call bump ld hl,ardly ; R1 release delay call bump ld hl,badly ; R2 access delay call bump ld hl,brdly ; R2 delay call bump ld hl,rmute ; radio DTMF mute timer call bump ld hl,tmute ; telephone DTMF mute timer call bump ld hl,atime ; control time-out call bump ld hl,tickt ; watchdog tick time-out call bump ld hl,idptim ; ID PTT timer call bump ld hl,rdvdly ; Radio DTMF Data Valid Delay call bump ld hl,vgdly ; 6M audio gate access delay call bump ld hl,ugdly ; 450 audio gate access delay call bump jp tisrd ; --------------------- end routine TISST ------------------------------ ;============================================================================ ; Service Timers (Routine #2) ;============================================================================ ; Service the varoius Timers by counting them down ; until they reach zero, then stop counting! tissu: ld hl,rgdlya ; phone ring detector access delay call bump ld hl,rgdlyr ; phone ring detector release delay call bump ld hl,rgird ; inter-ring delay call bump2 jp nc,tisu1 ld (llfrt),a ; update ring time out flag tisu1: ld hl,ansacc ; get answer control access time call bump2 jp nc,tisu2 ld (llfan),a ; update ANS time out tisu2: ld hl,anshld ; get the answer hold time call bump2 jp nc,tisu3 ld (llfhl),a ; update hold time-out tisu3: ld hl,maxll ; get the max landline time call bump2 jp nc,tisu4 ld (fltom),a ; update landline time-out tisu4: ld hl,(mdfpct) ; get the default courtesy tone time ex de,hl ld hl,(maxll) ; get current max landline time call subhd ; see if time, result in HL ld a,h ; HL = 0 if time to send courtesy tone or a,l ; to alert landline user that jp nz,tisu5 ; it's about to time-out ld a,0ffh ld (fpctm),a ; update landline courtesy tone flag tisu5: ; Don't operate patch timer if patch is off ; or Landline Control is unlocked ld a,(ptchm) ; see if patch is on or a ; 0ffh = on jp z,tisu6 ld a,(llful) ; or if landline control is unlocked or a ; 0ffh = unlocked jp nz,tisu6 ld hl,teltim ; update patch time out call bump2 jp nc,tisu6 ld (fpatm),a ; Patch Timer timed out ; See if any Aux TX enabled tisu6: ld a,(port7c) ; read control byte and a1tx+a2tx ; only look at Aux TX's jp z,tisu7 ; Z = both are disabled ld hl,attim ; get Aux TX time limit call bump2 ; count it down jp nc,tisu7 ld (fltxm),a ; reset both Aux Transmitters tisu7: ld hl,dnulm ; check DTMF Pass-Through timer call bump2 jp nc,tisu8 ld (fdnlm),a ; restore normal DTMF Processing tisu8: ld a,(limuhf) ; see if 450 TX activity limit active or a jp z,tisu9 ; Z = disabled ld hl,utxlim ; check 450 TX activity limit call bump2 tisu9: ld hl,unact ; check repeater inactivity timer call bump2 jp nz,tisu10 ld hl,(mdfulm) ; preset the 450 TX activity limit timer ld (utxlim),hl tisu10: ld a,(clkp) ; get the hardware clock flag or a ; Z = clock present call nz,softc ; do the software clock update jp tisrd ; ------------------- end routine TISSU ---------------------------------- ;============================================================================= ; Process 6M Receiver ;============================================================================= tirxv: ld a,(port1c) ; get 6M control status and vrcos+vrtos jp z,tirvo ; Z = 6M RX Disabled ld a,(port1) ; get receiver status direct cpl and vrcos ; look at 6M COS only jp z,tirvb ; Z = COS inactive ld a,(pltv) ; get 6M temp PL override flag or a jp nz,tirv1 ; NZ = fake PL tirva: ld a,(port1s) ; get receiver status and vrcos+vrtos ; look at 6M only jp nz,tirv1 ; NZ = receiver coming on ; Receiver going off tirvb: ld a,(vrdly) ; get 6M release delay or a jp nz,tirv3 ; Receiver is off tirvo: ld hl,(mdfto) ; preset 6M RX time out ld (vrtim),hl ld a,(mdfvad) ; preset 6M Access Delay ld (vadly),a xor a ; reset 6M delayed COS ld (vdcos),a jp tisrd ; Receiver coming on tirv1: ld a,(vadly) ; get 6M access delay or a jp nz,tisrd ; NZ = access delay not finished ; Receiver is on tirv2: ld a,(mdfvrd) ; preset the release delay ld (vrdly),a ld hl,(mdftel) ; preset patch timer ld (teltim),hl ld hl,(mdfatt) ; preset Aux TX time limit ld (attim),hl ld a,(vpltf) ; see if 6M PL time-out inhibit enabled or a jp z,tirv3 ; zero is disabled ld a,(port1s) ; get receiver status and vrtos ; look only at 6M tos jp z,tirv3 ld hl,(mdfto) ; preset 6M RX time out ld (vrtim),hl tirv3: ld hl,(vrtim) ; get 6M RX timer ld a,h or a,l call nz,lhtim ; key main and aux transmitters call preid ; set early ID if required ld a,0ffh ld (vdcos),a ; set the 6M delayed COS ld (bidflg),a ; and the Broadcast ID flag ld (fvctm),a ; and the 6M courtesy tone foreground flag jp tisrd ; -------------------------- end routine TIRXV --------------------------- ;============================================================================ ; 450 Receiver Processing ;============================================================================ tirxu: ld a,(port1c) ; get 450 control status and urcos+urtos jp z,tiruo ; Z = 450 RX Disabled ld a,(port1) ; get receiver status direct cpl and urcos ; look at 450 COS only jp z,tirub ; Z = COS inactive ld a,(pltu) ; get 450 temp PL override flag or a jp nz,tiru1 ; NZ = fake PL tirua: ld a,(port1s) ; get receiver status and urcos+urtos ; look at 450 only jp nz,tiru1 ; NZ = receiver coming on ; Receiver going off tirub: ld a,(urdly) ; get 450 release delay or a jp nz,tiru3 ; Receiver is off tiruo: ld hl,(mdfto) ; preset 450 RX time out ld (urtim),hl ld a,(mdfuad) ; preset 450 Access Delay ld (uadly),a xor a ; reset 450 delayed COS ld (udcos),a jp tisrd ; Receiver coming on tiru1: ld a,(uadly) ; get 450 access delay or a jp nz,tisrd ; NZ = access delay not finished ; Receiver is on tiru2: ld a,(mdfurd) ; preset the release delay ld (urdly),a ld hl,(mdftel) ; preset patch timer ld (teltim),hl ld hl,(mdfatt) ; preset Aux TX time limit ld (attim),hl ld hl,(mdfulm) ; preset 450 TX inactivity timer ld (utxlim),hl ld a,(upltf) ; see if 450 PL time-out inhibit enabled or a jp z,tiru3 ; zero is disabled ld a,(port1s) ; get receiver status and urtos ; look only at 450 tos jp z,tiru3 ld hl,(mdfto) ; preset 450 RX time out ld (urtim),hl tiru3: ld hl,(urtim) ; get 450 RX timer ld a,h or a,l call nz,lhtim ; key main and aux transmitters call preid ; set early ID if required ld a,0ffh ld (udcos),a ; set the 450 delayed COS ld (bidflg),a ; and the Broadcast ID flag ld (fuctm),a ; and the 450 courtesy tone foreground flag jp tisrd ; --------------------- end routine TIRXU -------------------------------- ;============================================================================= ; Process Auxiliary Receiver #1 ;============================================================================= tirxa: ld a,(port1s) ; get receiver status and a1cos ; look at Aux #1 only jp nz,tira1 ; NZ = receiver coming on ; Receiver going off ld a,(ardly) ; get R1 release delay or a jp nz,tira2 ; Receiver is off ld a,(mdfaad) ; preset R1 Access Delay ld (aadly),a xor a ld (adcos),a ; reset R1 delayed COS jp tisrd ; Receiver coming on tira1: ld a,(aadly) ; get R1 access delay or a jp nz,tisrd ; NZ = access delay not finished ; Receiver is on ld a,(mdfard) ; preset the release delay ld (ardly),a tira2: ld a,0ffh ld (acf),a ; set the R1 cos flag ld (adcos),a ; and the R1 delayed COS ld (bidflg),a ; and the Broadcast ID flag call htime ; transmit jp tisrd ; --------------------- end routine TIRXA --------------------------------- ;============================================================================ ; Process Auxiliary Receiver #2 ;============================================================================ tirxb: ld a,(port1s) ; get receiver status and a2cos ; look at R2 only jp nz,tirb1 ; NZ = receiver coming on ; Receiver going off ld a,(brdly) ; get R2 release delay or a jp nz,tirb2 ; Receiver is off ld a,(mdfbad) ; preset R2 Access Delay ld (badly),a xor a ld (bdcos),a ; reset R2 delayed COS jp tisrd ; Receiver coming on tirb1: ld a,(badly) ; get R2 access delay or a jp nz,tisrd ; NZ = access delay not finished ; Receiver is on ld a,(mdfbrd) ; preset the release delay ld (brdly),a tirb2: ld a,0ffh ld (bcf),a ; set the R1 cos flag ld (bdcos),a ; and the R1 delayed COS ld (bidflg),a ; and the Broadcast ID flag call htime ; transmit jp tisrd ; --------------------- end routine TIRXB --------------------------------- ;============================================================================= ; Process ID PTT ;============================================================================= tiidt: ld a,(cwptt) ; get CW PTT flag or a jp z,tiid2 ; Z = no ID PTT push af call ihtim ; set CW PTT Hang Time and TX Hang Time pop af tiid2: ld a,(idptim) ; check ID PTT Time or a jp z,tiid3 ld a,(port7s) ; set the ID PTT bit or idptt ld (port7s),a jp tisrd tiid3: ld a,(port7s) ; reset the ID PTT bit and not idptt ld (port7s),a jp tisrd ; --------------------- end routine TIIDT ------------------------------- ;============================================================================= ; Process Autopatch ;============================================================================= tiapt: ld a,(ptchm) ; see if patch is on or a ; 0ffh = on jp z,tiap3 ld a,(rmute) ; process possible patch gate DTMF mute ld b,a ; from either radio or telephone ld a,(tmute) ; DTMF decoders or a,b jp nz,tiap1 ld a,(port7s) or ptchg ; turn on the patch gate ld (port7s),a jp tiap2 tiap1: ld a,(port7s) and not ptchg ; mute the patch gate ld (port7s),a tiap2: call htime ; keep transmitters on jp tisrd tiap3: ld hl,(mdftel) ; preset patch timer ld (teltim),hl jp tisrd ; -------------------- end routine TIAPT ---------------------------------- ;============================================================================= ; Process Ring Detector ;============================================================================= tirng: ld a,(port1s) and a,b and ring ; see if the phone is ringing jp nz,tirg1 ; NZ = ring starting or ringing ; Ring Stopping ld a,(rgdlyr) ; get release delay or a jp nz,titot ; Ring Stopped ld a,(mdfrd) ; get the default ring delay ld (rgdlya),a ; preset the access delay jp titot ; Ring Starting tirg1: ld a,(rgdlya) ; get the ring access delay cp 1 ; last count before zero? jp nz,titot ; NZ = ring not long enough ; Ringing ld a,(mdfrd) ; get the default ring delay ld (rgdlyr),a ; preset the release delay ld a,0ffh ; set the ring flag ld (llfrg),a ld hl,(mdfird) ; get the default inter-ring time ld (rgird),hl ; preset it ; jp titot ; fall through ; -------------------- end routine TIRNG ---------------------------------- ;============================================================================ ; Process Control System Time-Out of Command Input Data ;============================================================================ titot: ld a,(atime) ; get the control time-out or a jp nz,tisrd ld a,(crflag) ; test the CR Flag or a jp z,tisrd ld a,(iptr) ; get the input buffer pointer inc a ; bump up the input buffer pointer ld (iptr),a cp iblen ; check that it wasn't advanced past end jp nz,tito1 xor a ; reset the pointer back to start ld (iptr),a tito1: ld hl,ibuf ; point to next char slot ld l,a ld a,cr ld (hl),a ; save char to force a CR ld a,0ffh ; set the EOL flag ld (eol),a xor a ld (crflag),a ; reset the CR Flag ld (sflag),a ; and the star flag ld (pflag),a ; and the pflag jp tisrd ;--------------------- end routine TITOT ------------------------------------ ;============================================================================ ; Software Time Clock Update Routine ;============================================================================ ; This is a software functional emulation of the MM58167 IC ; which keeps track of hours, minutes and seconds in a ; format identical to the hardware registers in the IC. ; The value of the registers is actually in Packed BCD, so the ; count of 9 is followed by 10H (16 decimal). softc: ld hl,st10 ; 10 ms event counter call bump ld a,(st10) ; get the value or a ret nz ld a,100 ; preset to 100 ten ms. intervals ld (st10),a ld a,(msec) ; get the seconds cp 59h ; 59? jp nc,softc1 ; time to bump the minutes call cvth ld (msec),a ; save back ret softc1: xor a ; reset the seconds ld (msec),a ld a,(mmin) ; get the minutes cp 59h ; 59? jp nc,softc2 ; time to bump the hours call cvth ld (mmin),a ; save back ret softc2: xor a ; reset the minutes ld (mmin),a ld a,(mhrs) ; get the hours cp 23h ; 23? jp nc,softc3 ; time to reset to 00:00 and bump the date call cvth ld (mhrs),a ; save back ret softc3: xor a ; reset the hours ld (mhrs),a softc5: ld hl,dpermh ; point to the table of number of days/month ld a,(mmo) ; get the month dec a ; make it start at zero ld d,0 ld e,a ; put in DE add hl,de ; offset into table ld a,(mdt) ; get the date cp (hl) jp nc,softc6 ; time to reset to 1 call cvth ld (mdt),a ; save back ret softc6: ld a,1 ld (mdt),a ; reset the date to 1 ld a,(mmo) ; get the month cp 12h ; 12? jp nc,softc7 ; time to reset back to 1 call cvth ld (mmo),a ; save back ret softc7: ld a,1 ; reset back to january ld (mmo),a ld a,(myr) ; get the year cp 99h ; 99? jp nc,softc8 call cvth ld (myr),a ; save back ret softc8: xor a ; reset the units years ld (myr),a ld hl,mdfcty ; get the tens years inc (hl) ; bump up ret ; This routine makes the register count up in Packed BCD ; instead of binary to emulate the hardware registers ; in the MM58167 IC cvth: inc a ; bump the register ld b,a ; save and 00001111b ; look at lower nibble cp 0ah ; greater than 9? ld a,b ; restore ret nz ; return if not cvth1: and 11110000b ; zero out lower nibble add a,10h ; bump up upper nibble ret DPERMH: db 31h ; jan db 28h ; feb db 31h ; mar db 30h ; apr db 31h ; may db 30h ; jun db 31h ; jul db 31h ; aug db 30h ; sep db 31h ; oct db 30h ; nov db 31h ; dec ;---------------------------------------------------------------------------- ; BUMP - Bump Down a one byte counter in memory ;---------------------------------------------------------------------------- ; Enter with HL pointing to byte to count down bump: ld a,(hl) ; get the byte or a ret z ; return if counter is zero dec a ; bump down ld (hl),a ; save back ret ;---------------------------------------------------------------------------- ; BUMP2 - Bump Down a two byte counter in memory ;---------------------------------------------------------------------------- ; Enter with HL pointing to byte pair to count down ; Routine will return with A=0 and Zero Flag set ; when count = Zero ; Routine will return with A=0FFH and Carry Flag set ; when count = '1' bump2: ld c,(hl) ; get lsb inc hl ld b,(hl) ; get msb Counter now in BC ld a,b or a,c jp z,bump4 ; return if zero dec bc ; not zero, then bump down BC ld (hl),b ; save back msb dec hl ld (hl),c ; save back lsb ld a,b ; set the foreground task flag or a ; as counter passes through '1' jp nz,bump3 ld a,c cp 1 jp z,bump5 ; Counter is at any count except '0' or '1' bump3: ld a,0ffh ; return with NZ or a ret ; Counter is at '0' bump4: xor a ; return with A=0 and no flags ret ; Counter is at '1' bump5: ld a,0ffh ; set the foreground task flag or a ; return with A=0ffh and scf ; set carry flag ret ;----------------------------------------------------------------------------- ; Subroutine PREID - Tell Foreground that ID timer ; will be timed-out before the current hang time is over ;----------------------------------------------------------------------------- preid: ld de,1000 ; ten seconds (1000 10ms ticks) value in DE ld hl,(idtim) ; get the current ID timer value call subhd ; subtract DE from HL, HL=result ; CY is set if HLDE, plenty of ID timer left ld a,0ffh ; set-up for early ID ld (fidtm),a ; set the foreground task flag ret ;--------------------- end of file TISR.Z80 --------------------------------- subttl page ;============================================================================ ; GRSD - Get Receivers Delayed Status ; after Access/Release Delays ;============================================================================ grsd: push bc ld a,(vdcos) ; get 6M delayed COS ld b,a ld a,(udcos) ; get 450 delayed COS or a,b pop bc ret ;---------------------------------------------------------------------------- ; Subroutine CTEST - Test MM58167 Status Byte ;---------------------------------------------------------------------------- ; Entry: A = value read from the counter ; Exit: A = value read from the counter ; Flags: Z = value OK ; NZ = rollover during read ; Uses: AF, B ctest: ld b,a ; save value ld a,(cstat) ; read the status bit or a ; set flags ld a,b ; restore value ret subttl Console Display Routine page include ucrt.z80 subttl CRT Display Routine ;============================================================================ ; CRT screen control codes for port status display ;============================================================================ offset equ 31 col1 equ 42 ; col 42 c1off equ col1+offset col2 equ 53 ; col 53 c2off equ col2+offset col3 equ 62 ; col 62 c3off equ col3+offset ; This is the Status Display Skeleton which is written to the ; screen only once and re-written during a Refresh CRT Command (X) ; ; The CRT sequence for direct cursor positioning is ; ESC Y row col - where the ASCII offset 31 needs to be ; added to row and col. This sequence will only work with ; terminals which use ESC Y row col unless the sequence is ; modified. The GXYMSG routine also has ESC Y row col hard ; coded. ucrtt: ld a,(umode) ; get the mode byte cp 1 jp z,ucrm1 cp 2 jp z,ucrm2 cp 3 jp z,ucrm3 cp 4 jp z,ucrm4 cp 5 jp z,ucrm5 call vprint defb esc,'Y',1+offset,c3off,2,'Input Port P0',1 defb esc,'Y',2+offset,c3off,'Ctrl' defb esc,'Y',3+offset,c3off,'Stat' defb esc,'Y',4+offset,c3off,2,'Receivers P1',1 defb esc,'Y',5+offset,c3off,'Ctrl' defb esc,'Y',6+offset,c3off,'Stat' defb esc,'Y',7+offset,c3off,2,'Input Port P2',1 defb esc,'Y',8+offset,c3off,'Ctrl' defb esc,'Y',9+offset,c3off,'Stat' defb esc,'Y',10+offset,c3off,2,'DTMF Decoders',1 defb esc,'Y',11+offset,c3off,'Radio Digit:' defb esc,'Y',12+offset,c3off,'Phone Digit:' defb esc,'Y',13+offset,c3off,2,'Output Port P4',1 defb esc,'Y',14+offset,c3off,'Ctrl' defb esc,'Y',15+offset,c3off,'Stat' defb esc,'Y',16+offset,c3off,2,'Output Port P5',1 defb esc,'Y',17+offset,c3off,'Ctrl' defb esc,'Y',18+offset,c3off,'Stat' defb esc,'Y',19+offset,c3off,2,'Audio Gates P6',1 defb esc,'Y',20+offset,c3off,'Ctrl' defb esc,'Y',21+offset,c3off,'Stat' defb esc,'Y',22+offset,c3off,2,'TX/Patch P7',1 defb esc,'Y',23+offset,c3off,'Ctrl' defb esc,'Y',24+offset,c3off,'Stat',0 jp ucrma ucrm5: call vprint defb esc,'Y', 1+offset,c3off,2,'2M Channel 0',1 defb esc,'Y', 3+offset,c3off,2,'2M Channel 1',1 defb esc,'Y', 5+offset,c3off,2,'2M Channel 2',1 defb esc,'Y', 7+offset,c3off,2,'2M Channel 3',1 defb esc,'Y', 9+offset,c3off,2,'2M Channel 4',1 defb esc,'Y',11+offset,c3off,2,'2M Channel 5',1 defb esc,'Y',13+offset,c3off,2,'2M Channel 6',1 defb esc,'Y',15+offset,c3off,2,'2M Channel 7',1 defb esc,'Y',17+offset,c3off,2,'2M Channel 8',1 defb esc,'Y',19+offset,c3off,2,'2M Channel 9',1,0 jp ucrma ucrm4: call vprint defb esc,'Y', 1+offset,c3off,2,'Macro Cmd 0',1 defb esc,'Y', 3+offset,c3off,2,'Macro Cmd 1',1 defb esc,'Y', 5+offset,c3off,2,'Macro Cmd 2',1 defb esc,'Y', 7+offset,c3off,2,'Macro Cmd 3',1 defb esc,'Y', 9+offset,c3off,2,'Macro Cmd 4',1 defb esc,'Y',11+offset,c3off,2,'Macro Cmd 5',1 defb esc,'Y',13+offset,c3off,2,'Macro Cmd 6',1 defb esc,'Y',15+offset,c3off,2,'Macro Cmd 7',1 defb esc,'Y',17+offset,c3off,2,'Macro Cmd 8',1 defb esc,'Y',19+offset,c3off,2,'Macro Cmd 9',1,0 jp ucrma ucrm3: call vprint defb esc,'Y', 1+offset,c3off,2,'Speed Dial 0',1 defb esc,'Y', 3+offset,c3off,2,'Speed Dial 1',1 defb esc,'Y', 5+offset,c3off,2,'Speed Dial 2',1 defb esc,'Y', 7+offset,c3off,2,'Speed Dial 3',1 defb esc,'Y', 9+offset,c3off,2,'Speed Dial 4',1 defb esc,'Y',11+offset,c3off,2,'Speed Dial 5',1 defb esc,'Y',13+offset,c3off,2,'Speed Dial 6',1 defb esc,'Y',15+offset,c3off,2,'Speed Dial 7',1 defb esc,'Y',17+offset,c3off,2,'Speed Dial 8',1 defb esc,'Y',19+offset,c3off,2,'Speed Dial 9',1,0 jp ucrma ucrm2: call vprint defb esc,'Y', 1+offset,c3off,2,'450 TX Limit',1 defb esc,'Y', 3+offset,c3off,2,'Repeater Inactivity',1 defb esc,'Y', 5+offset,c3off,2,'Temp PL Override',1 defb esc,'Y', 7+offset,c3off,2,'DTMF Pass-Thru',1 defb 0 jp ucrma ucrm1: call vprint defb esc,'Y', 1+offset,c3off,2,'Event 0',1 defb esc,'Y', 3+offset,c3off,2,'Event 1',1 defb esc,'Y', 5+offset,c3off,2,'Event 2',1 defb esc,'Y', 7+offset,c3off,2,'Event 3',1 defb esc,'Y', 9+offset,c3off,2,'Event 4',1 defb esc,'Y',11+offset,c3off,2,'Event 5',1 defb esc,'Y',13+offset,c3off,2,'Event 6',1 defb esc,'Y',15+offset,c3off,2,'Event 7',1 defb esc,'Y',17+offset,c3off,2,'Event 8',1 defb esc,'Y',19+offset,c3off,2,'Event 9',1,0 ucrma: call vprint tl01: defb esc,'Y',1+offset,c1off,2,'ID Timer:',1 tl03: defb esc,'Y',3+offset,c1off,2,'6M RX:',1 tl05: defb esc,'Y',5+offset,c1off,2,'450 RX:',1 t107: defb esc,'Y',7+offset,c1off,2,'Aux TX:',1 t109: defb esc,'Y',9+offset,c1off,2,'LL Ctrl:',1 tl11: defb esc,'Y',11+offset,c1off,2,'Patch:',1 tl13: defb esc,'Y',13+offset,c1off,2,'Transmit:',1 tl15: defb esc,'Y',15+offset,c1off,2,'Date:',1 tl18: defb esc,'Y',18+offset,c1off,2,'Time:',1 t119: defb esc,'Y',19+offset,c1off,2,'Chime:',1,0 ret ;============================================================================ ; CRT Update Enable/Disable/Mode ;============================================================================ ucrtc: ld a,(uflag) ; get the update flag or a jp nz,ucroff ucron: ld a,0ffh ; set the update flag ld (uflag),a ret ucroff: xor a ; reset the update flag ld (uflag),a ret cmode: call rech ; get the char cp cr ; no arguements? jp z,cmodet ; step through modes cp '0' jp z,cmode0 cp '1' jp z,cmode1 cp '2' jp z,cmode2 cp '3' jp z,cmode3 cp '4' jp z,cmode4 cp '5' jp z,cmode5 jp error cmode0: xor a ld (umode),a jp cmmsg cmode1: ld a,1 ld (umode),a jp cmmsg cmode2: ld a,2 ld (umode),a jp cmmsg cmode3: ld a,3 ld (umode),a jp cmmsg cmode4: ld a,4 ld (umode),a jp cmmsg cmode5: ld a,5 ld (umode),a cmmsg: push af ; save the CRT Mode call menu ; print screen menu call stat ; print status line message defb 'CRT Update Mode ',0 pop af ; get the mode back add 30h ; make ASCII jp cout ; add mode number to status message and ret cmodet: ld a,(umode) ; get the current mode or a jp z,cmode1 ; if zero, make mode one cp 1 jp z,cmode2 ; if one, make mode 2 cp 2 jp z,cmode3 ; if two, make mode 3 cp 3 jp z,cmode4 ; if three, make mode 4 cp 4 jp z,cmode5 ; if four, make mode 5 jp cmode0 ; otherwise make mode zero ;---------------------------------------------------------------------------- ; Update the CRT port status display ucrt: ld a,(uflag) ; get the UCRT control flag or a ret z ld a,(eol) ; see if monitor loop is idle or a ; if EOL is nz (set), no pending command ret z ; Z is command pending, bypas ucrt ; This is the entry point UCRTE which is used to update the screen ; without testing the above flags ucrte: push hl push de push bc ld a,(muptim) ; preset update time ld (crt),a call curoff ; turn off cursor call gxymsg ; send WORKING message defb 24,col1 defb 1,'Working',0 ld a,(umode) ; get the control byte cp 1 ; mode 1 (Events Display)? jp z,umod1 cp 2 jp z,umod2 cp 3 jp z,umod3 cp 4 jp z,umod4 cp 5 jp z,umod5 ; jp umod0 ;----------------------------------------------------------------------------- ; CRT Update Mode 0 ;----------------------------------------------------------------------------- umod0: call at ; Port 0 / Interrupts (P0) defb 2,col3+6 ld a,(port0c) ld l,a call bits call at defb 3,col3+6 ld a,(port0) cpl ld l,a call bits call at ; Display Receivers (P1) defb 5,col3+6 ld a,(port1c) ld l,a call bits call at defb 6,col3+6 ld a,(port1) cpl ld l,a call bits call at ; Display Input Port 2 defb 8,col3+6 ld a,(port2c) ld l,a call bits call at defb 9,col3+6 ld a,(port2) cpl ld l,a call bits call at ; display the last Radio DTMF char in ASCII defb 11,75 ld a,(digitr) call cout call at ; display the last Phone DTMF char in ASCII defb 12,75 ld a,(digitp) call cout call at ; Display Output Port 4 defb 14,col3+6 ld a,(port4c) ld l,a call bits call at defb 15,col3+6 ld a,(port4s) ld l,a call bits call at ; Display Output Port 5 defb 17,col3+6 ld a,(port5c) ld l,a call bits call at defb 18,col3+6 ld a,(port5s) ld l,a call bits call at ; Display Audio Gates (P6) defb 20,col3+6 ld a,(port6c) ld l,a call bits call at defb 21,col3+6 ld a,(port6s) ld l,a call bits call at ; Display Transmitters (P7) defb 23,col3+6 ld a,(port7c) ld l,a call bits call at defb 24,col3+6 ld a,(port7s) ld l,a call bits jp ucrt3 ;----------------------------------------------------------------------------- ; CRT Update Mode 1 ;----------------------------------------------------------------------------- umod1: call at ; update scheduled event #0 defb 2,col3 ld hl,sch0 call ucev call at ; update scheduled event #1 defb 4,col3 ld hl,sch1 call ucev call at ; update scheduled event #2 defb 6,col3 ld hl,sch2 call ucev call at ; update scheduled event #3 defb 8,col3 ld hl,sch3 call ucev call at ; update scheduled event #4 defb 10,col3 ld hl,sch4 call ucev call at ; update scheduled event #5 defb 12,col3 ld hl,sch5 call ucev call at ; update scheduled event #6 defb 14,col3 ld hl,sch6 call ucev call at ; update scheduled event #7 defb 16,col3 ld hl,sch7 call ucev call at ; update scheduled event #8 defb 18,col3 ld hl,sch8 call ucev call at ; update scheduled event #9 defb 20,col3 ld hl,sch9 call ucev jp ucrt3 ;----------------------------------------------------------------------------- ; CRT Update Mode 2 ;----------------------------------------------------------------------------- umod2: call at ; Display 450 TX inactivity timer defb 2,col3 ld hl,(utxlim) call ptsec call at ; Display repeater inactivity timer defb 4,col3 ld hl,(unact) call ptsec call at ; Display Temp PL Override timer defb 6,col3 ld hl,(tmppl) call ptsec call at ; Display DTMF Pass-Thru timer defb 8,col3 ld hl,(dnulm) call ptsec jp ucrt3 ;----------------------------------------------------------------------------- ; CRT Update Mode 3 ;----------------------------------------------------------------------------- umod3: call at ; update speed dial #0 defb 2,col3 ld hl,dial0 call ucsd call at ; update speed dial #1 defb 4,col3 ld hl,dial1 call ucsd call at ; update speed dial #2 defb 6,col3 ld hl,dial2 call ucsd call at ; update speed dial #3 defb 8,col3 ld hl,dial3 call ucsd call at ; update speed dial #4 defb 10,col3 ld hl,dial4 call ucsd call at ; update speed dial #5 defb 12,col3 ld hl,dial5 call ucsd call at ; update speed dial #6 defb 14,col3 ld hl,dial6 call ucsd call at ; update speed dial #7 defb 16,col3 ld hl,dial7 call ucsd call at ; update speed dial #8 defb 18,col3 ld hl,dial8 call ucsd call at ; update speed dial #9 defb 20,col3 ld hl,dial9 call ucsd jp ucrt3 ;----------------------------------------------------------------------------- ; CRT Update Mode 4 ;----------------------------------------------------------------------------- umod4: call at ; update Macro Cmd #0 defb 2,col3 ld hl,mac0 call ucpm call at ; update Macro Cmd #1 defb 4,col3 ld hl,mac1 call ucpm call at ; update Macro Cmd #2 defb 6,col3 ld hl,mac2 call ucpm call at ; update Macro Cmd #3 defb 8,col3 ld hl,mac3 call ucpm call at ; update Macro Cmd #4 defb 10,col3 ld hl,mac4 call ucpm call at ; update Macro Cmd #5 defb 12,col3 ld hl,mac5 call ucpm call at ; update Macro Cmd #6 defb 14,col3 ld hl,mac5 call ucpm call at ; update Macro Cmd #7 defb 16,col3 ld hl,mac7 call ucpm call at ; update Macro Cmd #8 defb 18,col3 ld hl,mac8 call ucpm call at ; update Macro Cmd #9 defb 20,col3 ld hl,mac9 call ucpm jp ucrt3 ;----------------------------------------------------------------------------- ; CRT Update Mode 5 ;----------------------------------------------------------------------------- umod5: ld c,0 ; C = cycle counter (channel number) call at ; update 2M Channel 0 defb 2,col3 ld hl,twoc0 call utwo call at ; update 2M Channel 1 defb 4,col3 ld hl,twoc1 call utwo call at ; update 2M Channel 2 defb 6,col3 ld hl,twoc2 call utwo call at ; update 2M Channel 3 defb 8,col3 ld hl,twoc3 call utwo call at ; update 2M Channel 4 defb 10,col3 ld hl,twoc4 call utwo call at ; update 2M Channel 5 defb 12,col3 ld hl,twoc5 call utwo call at ; update 2M Channel 6 defb 14,col3 ld hl,twoc6 call utwo call at ; update 2M Channel 7 defb 16,col3 ld hl,twoc7 call utwo call at ; update 2M Channel 8 defb 18,col3 ld hl,twoc8 call utwo call at ; update 2M Channel 9 defb 20,col3 ld hl,twoc9 call utwo ;---------------------------------------------------------------------------- ucrt3: call at ; Display ID Timer defb 1,col2 ld hl,(idtim) call ptsec call at ; Display 6M RX timeout timer defb 3,col2 ld hl,(vrtim) call ptsec call at ; Display 450 RX timeout timer defb 5,col2 ld hl,(urtim) call ptsec call at ; Display Aux TX timeout timer defb 7,col2 ld hl,(attim) call ptsec call at ; Display Landline Access Time defb 9,col2 ld hl,(maxll) call ptsec call at ; Display Autopatch timeout timer defb 11,col2 ld hl,(teltim) call ptsec call at ; Display TX hang timer defb 13,col2 ld hl,(hang) call ptsec call rdtim ; update time and date in memory call at ; Display Date defb 15,col2-4 ucrt4: ld a,(mmo) ; get month 1 to 12 or a jp z,ucrt7 ; safety test, just in case zero dec a ; make 0 to 11 ld hl,4 ; number of bytes per table entry ld de,motbl ; table to use call scant ; scan table and print month ld a,' ' call cout call dim ucrt5: ld a,(mdt) ; get day call byte ld a,',' call cout ld a,(mdfcty) ; get century call byte ld a,(myr) ; get year call byte call at defb 16,col2-4 ucrt6: ld a,(mda) ; get the day of the week ld hl,10 ; number of bytes per table entry ld de,daywk ; table to use call scant ; scan table and print day of the week ucrt7: ld a,(chena) ; get the hourly chime status or a jp z,ucrt8 ; Z = chime not enabled call gxymsg defb 19,col1+7 defb 'ON ',0 jp ucrt9 ucrt8: call gxymsg defb 19,col1+7 defb 'OFF',0 ucrt9: call at defb 18,col1+7 ld a,(mhrs) ; get hours cp 12h ; AM or PM? jp c,ucrt11 ; its AM cp 12h ; is it noon jp z,ucrt13 ; yes, skip the subtraction cp 20h ; 8PM? jp z,ucrt10 cp 21h ; 9PM? jp z,ucrt10 sub 12h ; make into 12 hour format jp ucrt13 ucrt10: sub 18h ; make into 12 hour format jp ucrt13 ucrt11: or a ; is it 12 AM? jp nz,ucrt13 ld a,12h ; change it from 0 hours to 12 hours ucrt13: call byte ; print in ASCII ld a,':' call cout ; print the colon ucrt14: ld a,(mmin) ; get minutes call byte ; print in ASCII ld a,':' call cout ld a,(clkp) ; clock present? (0ffh = not there) or a jp z,ucrt15 ld a,(msec) jp ucrt16 ucrt15: ld a,(sec) call ctest jp nz,ucrt15 ; NZ = rollover during read ucrt16: call byte ld a,(mhrs) cp 12h jp c,ucrt17 ; C = AM call vprint defb ' PM',0 jp ucrt18 ucrt17: call vprint defb ' AM',0 ucrt18: ld a,(clkp) ; get the clock flag or a jp z,ucrt19 ; Z = clock IC present call gxymsg defb 19,col1+15 defb '(S)',0 ; software clock indicator jp ucrtx ucrt19: call gxymsg defb 19,col1+15 defb '(H)',0 ; hardware clock indicator ucrtx: call gxymsg ; clear WORKING message defb 24,col1 defb 2,' ',1,0 call prompt ; re-display READY Prompt pop bc pop de pop hl ret ;---------------------------------------------------------------------------- ; Subroutine SCANT - Scan a table ;---------------------------------------------------------------------------- ; Entry: HL = number of bytes per entry ; DE = Address of table to use ; A = the desired table entry ; NO RANGE CHECKING! ; Exit: String Printed at Console ; Uses: HL, DE, AF scant: push de ld d,0 ld e,a ; put A into DE call mulhd ; multiply month by number of bytes per entry pop de ; point to the table to use add hl,de ; add offset into table call pstr ret ;---------------------------------------------------------------------------- ; Month Table ;---------------------------------------------------------------------------- ; Each entry must contain the same number of bytes! ; (Four bytes per entry including trailing zero) ; 123 4 motbl: defb 'Jan',0 defb 'Feb',0 defb 'Mar',0 defb 'Apr',0 defb 'May',0 defb 'Jun',0 defb 'Jul',0 defb 'Aug',0 defb 'Sep',0 defb ' ',0 ; Padding needed because calendar defb ' ',0 ; output is packed BCD, not decimal defb ' ',0 defb ' ',0 defb ' ',0 defb ' ',0 defb 'Oct',0 defb 'Nov',0 defb 'Dec',0 ;---------------------------------------------------------------------------- ; Day-of-the-week Table ;---------------------------------------------------------------------------- ; Each entry must contain the same number of bytes! ; (Ten bytes per entry including trailing zero) ; 123456789 10 daywk: defb 'Sunday ',0 defb 'Monday ',0 defb 'Tuesday ',0 defb 'Wednesday',0 defb 'Thursday ',0 defb 'Friday ',0 defb 'Saturday ',0 ;---------------------------------------------------------------------------- ; Subroutine - PTSEC Print time in mm:ss format ;---------------------------------------------------------------------------- ; Enter with HL pointing to the timer to read ptsec: ld de,100 ; ticks are in 10 ms. intervals call divhd ; divide by 100 to get seconds push hl ; save total seconds ld de,60 call divhd ; divide by 60 to get remaining minutes ld a,l call padc ld a,':' ; print the colon call cout ld de,60 ; multiply by 60 call mulhd ; HL has current number remaining minutes ex de,hl pop hl ; retrieve total seconds into HL call subhd ; subtract 60 * remaining minutes ld a,l call padc ret ;--------------------------------------------------------------------------- ; Subroutine UCEV - Update CRT Scheduled Events ;--------------------------------------------------------------------------- ucev: ld a,(hl) cp 0ffh ; active and pending? jp nz,ucev1 ld a,'P' ; print (P)ending call cout jp ucev3 ucev1: cp 80h ; active and not pending? jp nz,ucev2 ld a,'A' ; print (A)ctive call cout jp ucev3 ucev2: ld a,'N' ; print (N)ot active call cout ucev3: call sngl ; print space inc hl ld a,(hl) ; get the priority byte or a jp nz,ucev4 ld a,'L' ; print L(ow) priority call cout jp ucev5 ucev4: ld a,'H' ; print H(igh) priority call cout ucev5: call sngl inc hl ld a,(hl) ; get the event hours call byte ; print ld a,':' call cout inc hl ld a,(hl) ; get the event minutes call byte ; print call dubl ; print 2 spaces ld b,6 ; print the next 6 chars in memory ucev6: inc hl ld a,(hl) call cout dec b jp nz,ucev6 ret ;----------------------------------------------------------------------------- ; Subroutine UCSD - Update Speed Dialer Display ;----------------------------------------------------------------------------- ucsd: ld a,(hl) ; get the first digit cp 0ffh ; 0ffh = empty slot jp z,ucse ld b,0 ; counter ucsd1: ld a,(hl) ; get the digit cp 0ffh ; done? ret z ; return add 30h ; make ASCII call cout ; print the digit inc hl ; next digit inc b ; bump count ld a,b ; get count cp 3 ; 3 digits printed? call z,ucdd ; yes = print dash char jp ucsd1 ; loop back for more ucdd: ld a,'-' jp cout ucse: call vprint defb 'Empty',0 ret ;----------------------------------------------------------------------------- ; Subroutine UCPM - Update Programmed Macro Commands Display ;----------------------------------------------------------------------------- ucpm: ld a,(hl) ; get the first digit cp 0ffh ; 0ffh = empty slot jp z,ucse ld b,5 ; counter ucpm1: ld a,(hl) ; get the digit call cout ; print the digit inc hl ; next digit dec b ; bump count jp nz,ucpm1 ; loop back for more ret ;----------------------------------------------------------------------------- ; Subroutine UTWO - Update Two Meter Frequencies Display ;----------------------------------------------------------------------------- utwo: ld a,(hl) ; get the first digit cp 0ffh ; 0ffh = empty slot jp z,ucse ld b,7 ; counter utwo1: ld a,(hl) ; get the digit call cout ; print the next digit utwo2: inc hl ; next digit dec b ; bump count jp nz,utwo1 ; loop back for more ld a,(hl) ; get offset control digit sub 30h ; convert from ascii or a jp z,utwos ; 0 = Simplex, 1 = Repeat, 2 = Inverse cp 2 ; auto offset mode? jp z,utwoi push hl call vprint rptstr: defb ' Rpt ',0 pop hl jp utwo3 utwoi: push hl call vprint invstr: defb ' Inv ',0 pop hl jp utwo3 utwos: push hl call vprint sxstr: defb ' Sx ',0 pop hl utwo3: inc hl ld a,(hl) ; get the power control digit sub 30h ; convert from ascii or a jp z,utwol ; 0 = Low Power, 1 = High Power push hl call vprint hpstr: defb 'HP ',0 pop hl jp utwo4 utwol: push hl call vprint lpstr: defb 'LP ',0 pop hl utwo4: ld a,(twoac) ; get the active channel cp c ; compare to currently displayed channel jp nz,utwo5 ld a,'*' ; print active channel indicator call cout inc c ; next channel ret utwo5: ld a,' ' ; clear active channel indicator call cout inc c ; next channel ret ; ------------------------ end of file -- UCRT.Z80 ------------------------- subttl page subttl Master Loop Foreground Routine page include master.z80 subttl Master Loop Foreground Routine ;============================================================================ ; MASTER LOOP (Foreground Routine) ;============================================================================ ;----------------------------------------------------------------------------- ; Foreground Task Address Table TASKADDR ;----------------------------------------------------------------------------- ; This is a table of address for the varoius Foreground Tasks. The ; order of the Task in the table determines its priority. The order ; and number of routines must exactly correspond with the number and ; order of the entries in the Foreground Task Flag Table (FGTF) in RAM. ; The Task Flag Table is a table of one byte entries. Each entry ; corresponds to a table of Task Addresses in ROM. When the Task Flag ; is set (by the Background Interrupt Routines) it will be serviced ; by the Foreground Routine according to priority. taskadr: defw beer ; Send Beer Message 1 defw toav ; 6M Time-Out Alarm 2 defw toau ; 450 Time-Out Alarm 3 defw tstid ; MCW ID 4 defw vctg ; send 6M Courtesy Tone 5 defw uctg ; send 450 Courtesy Tone 6 defw pctg ; Landline Courtesy Tone 7 defw dpatch ; Dump Autopatch 8 defw rtpl ; Temp PL Override Reset 9 defw rdnul ; End of DTMF Pass-Thru 10 defw rltx ; Link TX Timed-out 11 defw rllc ; Reset Landline Control 12 defw ucrtf ; Update CRT Screen 13 ; ----------------- The Master Looop starts here --------------------------- master: push hl ; save all registers push de push bc push af fore: ld hl,fgtf-1 ; point to start of task flag table ld de,taskadr-2 ; point to start of task addr table halt ; wait for next interrupt to synchronize ; It takes 10 cycles through the TISR Interrupt Routine ; to complete all system updates. Execute the Foreground ; Routine only after all 10 cycles have been completed. ; ld a,(intcnt) ; get the interrupt cycle counter ; cp 9 ; processes 0 thru 9 done? ; jp nz,masty ; nope, bail out fore1: call tick ; tick the watchdog call check ; check for pending task ; This is where the Foreground Tasks return ; >---->---+ ; | ; v jp c,mastx ; do the rest of the polled stuff if CY=1 ld a,l ; see if more tasks to check cp low fgtfe-1 jp nz,fore1 ; go back and do more ; The following subsystems are polled every pass through the Master Loop mastx: call llctl ; process landline control/ringdown access call schev ; process scheduled events call tstcrt ; process CRT power up/down test masty: pop af ; restore all registers pop bc pop de pop hl ret ;----------------------------------------------------------------------------- ; Subroutine TSTCRT - Test for CRT power up/down ;----------------------------------------------------------------------------- ; This is a foreground task which is polled during every ; pass and not prioritized by the Foreground Task Table tstcrt: ld a,(ttyc) ; read USART Status Information and dsrmsk ; only look at DSR Bit jp z,tstc1 ; DSR is active (CRT is on), set the UFLAG and reset the display ld a,(dsrflg) ; see if flag is reset (DSR coming on) or a ret nz ; NZ = already set, DSR was already on call onesec call clbuf call cmenu ; reset the screen call ucron ; enable refresh updates ld a,0ffh ; set the DSR flag ld (dsrflg),a ret ; DSR is inactive (CRT is off), reset the UFLAG tstc1: ld a,(dsrflg) ; see if flag is set (DSR going off) or a ret z ; Z = already reset, DSR was already off call onesec call ucroff ; disable screen refresh updates call clbuf ; clear the type-ahead buffer xor a ; reset the DSR flag ld (dsrflg),a ret ; Gobble up any chars which appear during CRT power up or down ; by resetting the type-ahead buffer system clbuf: xor a ld (iptr),a ld (optr),a ld a,cr call putbuf ret ;============================================================================= ; Foreground Tasks for the Master Loop ;============================================================================= ;----------------------------------------------------------------------------- ; Foreground Task TSTID - Test for Time to ID ;----------------------------------------------------------------------------- tstid: ld a,(port7s) ; are any TX on? and utx+vtx jp z,tstid1 ; don't ID if TX off unless Broadcast flag set call grsd ; get receivers delayed status jp nz,tstidx call sndid ; polite ID, wait for COS off to send ID jp tstid2 tstid1:ld a,(bidflg) ; get the Broadcast ID flag or a jp z,tstidx call grsd ; get receivers delayed status jp nz,tstidx ; polite ID, wait for COS off to send ID call sndsbd tstid2: xor a ld (bidflg),a ; reset the Broadcast ID flag scf tstidx: pop hl ret ;----------------------------------------------------------------------------- ; Foreground Task VCTG - Generate 6M Courtesy Tone ;----------------------------------------------------------------------------- vctg: ld a,(vctmod) ; get 6M courtesy tone mode ld b,a ; save or a ; Z = Disabled (mode 0) jp z,vcty ld a,(vdcos) ; 6M delayed COS or a jp nz,vctx ld a,b ; get mode back cp 1 ; mode 1 = first key-up only jp nz,vctg1 ld a,(cttflv) ; get 6M courtesy tone control flag or a ; see if first key-up jp nz,vcty ; NZ = already done ld a,0ffh ; set the done flag ld (cttflv),a vctg1: ld a,(fidtm) ; see if ID ready or a call nz,sndid call t800 ; set 800 Hz tone call tonon ; tone on call sec17 ; delay 1/7 second call t1200 ; set 1200 Hz tone call sec17 ; delay 1/7 second call tonoff ; tone off call qsec ; delay 1/4 second call lctg ; see if any link courtesy tones needed scf vcty: xor a ld (fvctm),a ; reset foreground task flag vctx: pop hl ret ;----------------------------------------------------------------------------- ; Foreground Task UCTG - generate 450 Courtesy Tone ;----------------------------------------------------------------------------- uctg: ld a,(uctmod) ; get 450 courtesy tone mode ld b,a ; save or a ; Z = Disabled (mode 0) jp z,ucty ld a,(udcos) ; 450 delayed COS or a jp nz,uctx ld a,b ; get mode back cp 1 ; mode 1 = first key-up only jp nz,uctg1 ld a,(cttflu) ; get 450 courtesy tone control flag or a ; see if first key-up jp nz,ucty ; NZ = already done ld a,0ffh ; set the done flag ld (cttflu),a uctg1: ld a,(fidtm) ; see if ID ready or a call nz,sndid call t1200 ; set 1200 Hz tone call tonon ; tone on call sec17 ; delay 1/7 second call t800 ; set 800 Hz tone call sec17 ; delay 1/7 second call tonoff ; tone off call qsec ; delay 1/4 second call lctg ; see if any link courtesy tones needed scf ucty: xor a ld (fuctm),a ; reset foreground task flag uctx: pop hl ret ;---------------------------------------------------------------------------- ; Subroutine LCTG - Generate Link Courtesy Tones ;---------------------------------------------------------------------------- ; This routine is called by both VCTG (6M) and UCTG (450) courtesy tone ; routines above. lctg: ld a,(cttflg) ; see if main TX has been on or a ; (skip aux courtesy tones ret nz ; except for first main TX key) ld a,0ffh ; set control flag ld (cttflg),a ; no aux courtesy tones next time ld a,(port7c) ; read control port and a1tx ; see if AUX TX #1 enabled jp z,lctg1 ; Z = transmitter not active call t1000 ; set 1000 Hz tone ld a,(mdfcb1) ; get the default character call cwl ; send the indicator character call qsec ; wait 1/4 second jp lctg2 ; go on to check AUX RX/TX #2 lctg1: ld a,(port1c) ; read control port and a1cos ; see if AUX RX #1 enabled jp z,lctg2 ; Z = receiver not active call t1000 ; set 1000 Hz tone ld a,(mdfct1) ; get the default character call cwl ; send the indicator character call qsec ; wait 1/4 second lctg2: ld a,(port7c) ; read control port and a2tx ; see if AUX TX #2 enabled jp z,lctg3 ; Z = transmitter not active call t660 ; set 660 Hz tone ld a,(mdfcb2) ; get the default character call cwl ; send the indicator character jp qsec ; wait 1/4 second and return lctg3: ld a,(port1c) ; read control port and a2cos ; see if AUX RX #2 enabled ret z ; Z = receiver not active call t660 ; set 660 Hz tone ld a,(mdfct1) ; get the default character call cwl ; send the indicator character jp qsec ; wait 1/4 second and return ;----------------------------------------------------------------------------- ; Foreground Task PCTG - generate Landline Courtesy Tone ;----------------------------------------------------------------------------- pctg: call tbeep4 ; beep the phone line call stat defb 'Landline close to Time-Out',0 xor a ld (fpctm),a ; reset foreground task flag scf pop hl ret ;----------------------------------------------------------------------------- ; Foreground Task DPATCH - Autopatch Time-Out ;----------------------------------------------------------------------------- dpatch: call ptchoff ; dump patch with call to Control System xor a ld (fpatm),a ; reset foreground task flag scf pop hl ret ;---------------------------------------------------------------------------- ; Foreground Task RTPL - Reset Temp PL Override ;---------------------------------------------------------------------------- rtpl: call tpld ; Reset with call to Control System call cbeep xor a ld (ftplm),a ; reset foreground task flag scf pop hl ret ;----------------------------------------------------------------------------- ; Foreground Task TOAV - 6M Time-Out Alarm ;----------------------------------------------------------------------------- toav: call t800 ; 6M RX Alarm call toa call grsd ; get receiver status jp nz,toavx ld hl,(mdfto) ; preset default RX time-out ld (vrtim),hl xor a ld (fvtom),a ; reset foreground task flag call stat defb '6M RX Time-Out Reset',0 scf toavx: pop hl ret ;----------------------------------------------------------------------------- ; Foreground Task TOAU - 450 Time-Out Alarm ;----------------------------------------------------------------------------- toau: call t1200 ; 450 RX Alarm call toa call grsd ; get receiver status jp nz,toaux ld hl,(mdfto) ; preset default RX time-out ld (urtim),hl xor a ld (futom),a ; reset foreground task flag call stat defb '450 RX Time-Out Reset',0 scf toaux: pop hl ret ;----------------------------------------------------------------------------- ; Subroutine TOA - Time-Out Alarm ;----------------------------------------------------------------------------- toa: call tonon ; time-out alarm ld a,25 ; 250 ms delay call delay call tonoff ld a,25 ; 250 ms delay call delay ret ;---------------------------------------------------------------------------- ; Foreground Task BEER - Send Beer Message after Time-Outs ;---------------------------------------------------------------------------- beer: call grsd ; get receiver status jp nz,beerx call sndbeer ; send the beer message xor a ld (fberm),a ; reset foreground task flag scf beerx: pop hl ret ;---------------------------------------------------------------------------- ; Foreground Task RDNUL - End of DTMF Pass-Thru ;---------------------------------------------------------------------------- rdnul: call cbeep call stat defb 'DTMF Pass-Thru Timed-Out',0 xor a ld (bdtmfr),a ; restore radio DTMF interrupts ld (fdnlm),a ; reset foreground task flag scf pop hl ret ;---------------------------------------------------------------------------- ; Foreground Task RLTX - Link Transmitters Timed-Out ;---------------------------------------------------------------------------- rltx: ld a,(port7c) ; get control byte and not (a1tx+a2tx) ; disable Aux TX bits ld (port7c),a ; save back call stat defb 'Aux Transmitters Timed-Out',0 xor a ld (fltxm),a ; reset foreground task flag scf pop hl ret ;---------------------------------------------------------------------------- ; Foreground Task RLLC - Reset Landline Control ;---------------------------------------------------------------------------- rllc: call llrst ; call the reset routine xor a ld (fltom),a ; reset foreground task flag scf pop hl ret ;---------------------------------------------------------------------------- ; Foreground Task UCRTF - Update CRT Screen ;---------------------------------------------------------------------------- ucrtf: call ucrt xor a ld (fucrm),a ; reset foreground task flag scf pop hl ret ;----------------------------------------------------------------------------- ; Check for Pending Tasks - CHECK ;----------------------------------------------------------------------------- ; This routine checks the table of Task Pending Flags (FGTF) in RAM and ; calls the appropriate Foreground Task if the flag is set. If the ; Foreground Task executes, it returns with a SCF:POP HL (carry flag ; set and HL pointing to the current task flag). If the Foreground Task ; did not execute (because of conditionals not satisfied within the task) ; then the task returns only with POP HL. The carry flag indicates that ; the task was executed so we have to start scanning for new pending tasks ; from the beginning again. check: inc hl ; point to next task pending flag ld a,(hl) ; get the flag or a ret z ; return if not set (Z) ; DE is now pointing to a word which contains the address ; of the Foreground Task we want to process chk1: push hl ; HL = Poistion in Task Flag Table ld a,l sub low fgtf ld de,taskadr-fgtf add hl,de ; calculate routine address ld e,a ld d,0 ; DE = offset value add hl,de ; HL = address in table ld e,(hl) inc hl ld d,(hl) ex de,hl ; HL = jump address jp (hl) ; go there ; ----------------------- end of file MASTER.Z80 ----------------------------- subttl Landline Control/Ringdown System page include llctl.z80 subttl Land-Line Ringdown and Control System Access ;---------------------------------------------------------------------------- ; Land-Line Ringdown and Control System Access ;---------------------------------------------------------------------------- llctl: ld a,(llful) ; is landline control unlocked? or a ret nz ld hl,(ansacc) ; control access pending? ld a,h or a,l ret nz ld hl,(anshld) ; phone call hold in progress? ld a,h or a,l jp nz,llct2 ld a,(llfhl) ; get the hold time-out flag or a call nz,llhlr ; reset from hold status ld a,(llfrt) ; inter-ring timed out? or a jp nz,tstrnt ld a,(llfrg) ; phone has rung? or a ret z ;----------------------------------------------------------------------------- ; Phone has rung ;----------------------------------------------------------------------------- tstrng: call stat defb 'Ring! #',0 xor a ld (llfrg),a ; reset the ring flag ld a,(mdfrgm) ; get the default max # of rings ld b,a ld a,(rgcnt) ; get the current ring counter inc a ; bump it up ld (rgcnt),a ; save back push af add a,30h ; make ascii-1 call cout ; print on screen pop af cp a,b ; did we reach the max # of rings? ret nz ; return if not ; Maximum number of rings is reached. Answer the phone. xor a ; enable DTMF interrupts from ld (bdtmft),a ; telephone line decoder ld (rgcnt),a ; reset the ring counter ld a,(port4s) ; access the landline relay or iclr ld (port4s),a ld hl,(mdfmxl) ; preset the max landline time ld (maxll),hl ld hl,(mdfacc) ; preset the access time ld (ansacc),hl ld hl,(mdfhld) ; preset the hold time ld (anshld),hl call stat defb 'Call answered. Waiting for access. ',0 jp prompt ; The inter-ring timer timed-out tstrnt: xor a ld (rgcnt),a ; clear the ring counter ld (llfrt),a ; clear the time-out flag call stat defb 'Incoming Ring Timed-Out.',0 jp prompt ; Control was not unlocked, do ringdown and wait awhile llct2: ld a,0ffh ; block DTMF interrupts from ld (bdtmft),a ; telephone line decoder ld a,(eol) ; command line active? or a ret z call llpm1 ; enable monitor mode call stat defb 'Incoming call holding. ',0 call prompt llct3: call ding ; send the ring tone call ding call ding call ding call ding call twosec ret ;-------------- Unlock Landline Control System ------------------------------ llun: ld hl,(anshld) ; hold time in progress? ld a,h or a,l jp z,error ; nope, zero came in from somewhere call stat defb 'Landline Control Unlock Successful.',0 call prompt xor a ; enable DTMF interrupts from ld (bdtmft),a ; telephone line decoder ld a,0ffh ld (llful),a ; unlock landline control jp tbeep2 ; sent confirmation tone to phone user ;-------------- Reset Landline Control System -------------------------------- llrst: call ptchfq ; turn patch off which signals phone user call stat defb 'Landline Control Reset',0 call prompt llrs1: ld hl,0 ld (ansacc),hl ; control access time ld (anshld),hl ; hold time ld (maxll),hl ; max landline time xor a ld (llful),a ; drop unlock flag ld (llfhl),a ; drop hold flag ld (llfan),a ; drop answer flag ld (llfrt),a ; clear the time-out flag ld (fltom),a ; reset foreground task flag ld a,0ffh ; block DTMF interrupts from ld (bdtmft),a ; telephone line decoder ld a,(port4s) ; turn-off landline relay which hangs-up phone and not (iclr+ptmon); and turn off Patch Monitor switch ld (port4s),a ret ;--------------- Enable Landline Monitor Mode -------------------------------- llpm: ld a,(llful) ; see if control system unlocked or a jp z,sndno call llpm1 call stat defb 'Landline Monitor Mode',0 call prena ; enabled jp tbeep2 ; send confirmation to phone user llpm1: ld a,(port7s) and not ptchg or ptchr ; turn-on only the patch relay ld (port7s),a ld a,(port4s) or ptmon ; turn-on Patch Monitor switch ld (port4s),a xor a ld (ptchm),a ; clear patch flag ret ;--------------- Disable Landline Monitor Mode ------------------------------- llpd: ld a,(llful) ; see if control system unlocked or a jp z,sndno llpd1: call ptchfq call stat defb 'Landline Monitor Mode',0 call prdis ; disabled ld a,(port4s) and not ptmon ; turn-off Patch Monitor switch ld (port4s),a ret ; -------------------- Beep signal to phone line user ---------------------- tbeep4: call tbeep2 ; 2 beeps and fall through for another pair tbeep2: call tbeep ; beep and fall through for a second beep tbeep: ld a,(bdtmft) ; get the current state of DTMF block flag push af ; save it ld a,0ffh ; block DTMF interrupts from ld (bdtmft),a ; telephone line decoder xor a or dgenc ; send tone signal to user via ld (port8),a ; DTMF dialer ld a,100/10 ; 100 ms. tone on call delay xor a ld (port8),a ; tone off ld a,100/10 ; 100 ms. tone off call delay pop af ; restore previous DTMF block state ld (bdtmft),a ret ; ---------------------- Release Landline Control -------------------------- llhlr: call ptchfq ; turn patch off which signals phone user call stat defb 'Landline Hold Timed-Out',0 call prompt jp llrs1 ; reset landline control system ; --------------------- end of file LLCTL.Z80 -------------------------------- subttl Scheduled Event Processing page include schev.z80 ;----------------------------------------------------------------------------- ; Subroutine SCHEV - Process Scheduled Events ;----------------------------------------------------------------------------- ; This routine is called from the Foreground schev: call rdtim ; read the clock chip (if there) ; and save in memory ; See if it's time for an hourly chime call grsd ; get main receivers status jp nz,sche14 ; skip chime if receivers active ld a,(chena) ; get the chime control flag or a jp z,sche1 ; Z = disabled ld a,(chdon) ; get the chime done flag or a jp nz,sche12 ; NZ = done ld a,(mmin) ; get the current minutes or a jp nz,sche1 ; NZ = not time yet call mbeep call halfsec call grsd ; get main receivers status again jp nz,sche14 ; skip speech if receivers active ld a,(cwena) ; get the speech/MCW mode cp 2 call z,stime ; speak the time if speech enabled ld a,0ffh ; set the chime done flag ld (chdon),a ld a,0ffh ; set the broadcast ID flag ld (bidflg),a ld hl,(idtim) ; time to ID? ld a,h or a,l jp nz,sche1 call sndsid ; send ID xor a ld (bidflg),a ; reset the broadcast ID flag ; Now, test the events to see if it is time to process any ; scheduled events sche1: ld b,0 ; number of events counter ld hl,sch0 ; point to first event sche2: ld a,(hl) ; get the event pending byte cp 0ffh jp nz,sche8 ; FF = Pending, 80 = Active, 00 = not Active inc hl ; point to priority byte sche3: inc hl ; point to event hours ld a,(mhrs) ; get the current hours cp (hl) ; equal? jp nz,sche6 inc hl ; point to event minutes ld a,(mmin) ; get the current minutes cp (hl) jp nz,sche5 ; Hours and minutes in event match current time dec hl dec hl ld a,(hl) ; get priority byte or a ; Z = low priority jp nz,sche3a call grsd ; see if main receivers are active jp nz,sche15 ; skip event processing completely if active sche3a: push hl call stat defb 'Scheduled Event #',0 ld a,b add 30h ; make ascii call cout call dubl ; two spaces call onesec pop hl dec hl ld a,80h ; mark the event as not pending ld (hl),a inc hl ; skip past Priority Byte, HH and MM inc hl inc hl inc hl ; point to control code ld c,6 ; number of bytes to move sche4: ld a,(hl) ; get the char call putbuf ; put in the type-ahead buffer inc hl ; next char dec c ; done with count? jp nz,sche4 ld a,cr ; append the trailing CR call putbuf jp sche9 sche5: dec hl ; backup from MM, HH and priority byte sche6: dec hl ; backup from MM and priority byte sche7: dec hl ; backup from priority byte sche8: ld de,10 ; we're at start of event (status byte) add hl,de ; offset to next event sche9: inc b ld a,b cp 10 jp c,sche2 ; go back for more events ; Now, test for 11:59 AM so that event pending updates can be made ld a,(eudon) ; get the event update done flag or a jp nz,sche13 ; NZ = done ld a,(mhrs) ; get the current hours cp 23h ; 11 pm? ret nz ld a,(mmin) ; get the current minutes cp 59H ; 11:59? ret nz ld hl,sch0 ; first event ld de,10 ; number of bytes per entry ld b,11 ; number of entries + 1 sche10: ld a,(hl) ; get the pending byte cp 80h ; active but not pending? jp nz,sche11 ld a,0ffh ; make active and pending ld (hl),a ; save back sche11: add hl,de ; point to next slot dec b jp nz,sche10 call stat defb 'Event Processing Updated',0 ld a,0ffh ; set the event update done flag ld (eudon),a ret ; Chime was done, reset the chime done flag sche12: ld a,(mmin) ; get the current minutes or a ; still zero? jp z,sche1 ; go process scheduled events xor a ; minutes advanced past zero ld (chdon),a ; reset the chime done flag jp sche1 ; go process scheduled events ; Event Update was done, reset the event update done flag sche13: ld a,(mmin) ; get the current minutes cp 59h ; still 59 minutes? ret z xor a ; minutes advanced to zero ld (eudon),a ; reset the event update done flag ret ; Receivers are in use, skip the chime completely sche14: ld a,0ffh ld (chdon),a ; set the chime done flag jp sche1 ; go process scheduled events ; Receivers are in use, skip the event processing completely sche15: dec hl ; go back to control byte ld a,80h ; mark the event as not pending ld (hl),a jp sche8 ; continue ;----------------------------------------------------------------------------- ; Subroutine SETSCH - Program Scheduled Events ;----------------------------------------------------------------------------- ; This routine is called from the control system setsch: ld de,sch0 ; start of the table to use ld hl,10 ; number of bytes per entry call mslot ; mslot is part of the macro code ; HL is now pointing to the event to program ld a,(clen) ; command line length or a jp z,setsc3 ; no args = toggle event active/not active ld a,0ffh ; first, mark the event ld (hl),a ; as active and pending call rech ; get the priority code 0=low, 1=high cp cr ; no char there? jp z,error call dchk ; convert to binary cp 2 ; greater than 1 jp nc,error inc hl ; point to priority byte cp 1 jp nz,setsc1 ld a,0ffh ld (hl),a ; save high priority jp setsc2 setsc1: xor a ld (hl),a ; save low priority setsc2: call gethx ; get the hours cp 24h ; greater than 23 hours? jp nc,error inc hl ; point to hours byte ld (hl),a ; save hours in event call gethx ; get minutes cp 60h ; greater than 59 minutes? jp nc,error inc hl ; point to minutes byte ld (hl),a ; save minutes in event inc hl ; point to control bytes ; store the next 6 bytes as a control code ld b,6 jp setma1 ; steal some code ; Toggle the event control byte if no command line parameters setsc3: ld a,(hl) ; get the current event status or a ; Z = not active jp z,setsc4 ; then make pending xor a ; must be active or pending ld (hl),a ; make event not active call ssfn ; speak 'function' jp sndoff ; say 'off' setsc4: ld a,0ffh ld (hl),a ; make event pending call ssfn ; speak 'function' jp sndon ; say 'on' ;============================================================================= ; Subroutine RDTIM - Read the Clock and save in memory ;============================================================================= rdtim: ld a,(clkp) ; clock present? (0ffh = not there) or a jp nz,rdtj ; NZ = software handling the calendar ld a,(month) ; get the current month call ctest jp nz,rdtim ; NZ = rollover during read ld (mmo),a ; save rdmd1: ld a,(date) ; get the current day of the month call ctest jp nz,rdmd1 ; NZ = rollover during read ld (mdt),a ; save rdmd2: ld a,(year) ; get the year register ld (myr),a ; save it in memory ld a,(hrs) ; get the current hours call ctest jp nz,rdtim ; NZ = rollover during read ld (mhrs),a ; save rdtm1: ld a,(min) ; get the current minutes call ctest jp nz,rdtm1 ; NZ = rollover during read ld (mmin),a ; save rdtm2: ld a,(sec) ; get the current seconds call ctest jp nz,rdtm2 ; NZ = rollover during read ld (msec),a ; save ; The math to convert Julian to Day-of-the-week is ; DOW = JUL - ( INT ( JUL / 7 ) * 7 ) rdtj: push hl push de push bc ld hl,timstr ; point to YY/MM/DD call bcd2jul ; convert to julian ; The Julian Date is in HL where 1 = Jan 1, 1978 dec hl ; start the date at zero push hl ; save it ld de,7 ; divide by 7 call divhd ; with integer result call mulhd ; multiply by 7 ex de,hl ; put subtrahend in DE pop hl ; get the julian date back as minuend call subhd ; subtract result in DE from julian in HL ; HL now has a number from 0 to 6 representing SUN to SAT ld a,l ld (mda),a ; save in memory pop bc pop de pop hl ret ;----------------------- end of file SCHEV.Z80 ------------------------------- subttl page ;============================================================================= ; Hardware Watchdog Timer Routines ;============================================================================= ; TICK is called from within the interrupt-driven background ; routine (TISR). This sets a one second timer. ; UNTICK is called from within the foreground Master Loop. ; As long as TICK and UNTICK are periodically called, the ; WatchDog bit will toggle on/off at approx. the rate at ; which the Master Loop is repeatedly executed. ; If the background routine TISR crashes, the WatchDog ; pulses will stop after the one second timer times-out. ; If the foreground Master Loop crashes, the WatchDog pulses ; will stop immediately. ; In any case, the actual time in which the WatchDog hardware ; timer can go without pulses from the processor is determined ; by the RC time constant of the timer -- approx. one second. tick: push af ld a,100 ; 1 sec watchdog time out ld (tickt),a pop af ret untick: push af ld a,(tickt) ; get the watchdog time out value or a jp z,untikz ld a,(tickm) or a jp nz,untik1 ld a,0ffh ; toggle state of tickm ld (tickm),a ld a,(port4s) ; tick ON or wdog ld (port4s),a pop af ret untik1: xor a ; toggle state of tickm ld (tickm),a ld a,(port4s) ; tick OFF and not wdog ld (port4s),a untikz: pop af ret ;============================================================================ ; Console Buffer Input Routine (CRT / DTMF) ;============================================================================ cin: push bc cin1: call master ; call the Master Loop Foreground Processor di ld a,(iptr) ; get the input buffer pointer ld b,a ; save it ld a,(optr) ; get the output buffer pointer ei cp a,b ; equal? jp z,cin1 ; if pending char cin2: call getbuf ; get the character pop bc ret ;----------------------------------------------------------------------------- ; PUTBUF - Put a character into the buffer ;----------------------------------------------------------------------------- ; ** Warning! ** PUTBUF is called from the interrupt routine KISR to ; save characters from the keyboard. It is imperative that PUTBUF save ; and restore all registers that it uses. ; Entry: A = Character to save in the buffer ; Exit: None ; Uses: None putbuf: di ; don't allow me to be bothered push hl ; whilst I put a character into the buffer push af ; save the char ld a,(iptr) ; get the current input pointer inc a ; mark one deposited ld (iptr),a cp iblen ; check that it wasn't advanced past end jp nz,putb1 xor a ; reset back to zero ld (iptr),a putb1: ld hl,ibuf ld l,a pop af ; get the char back ld (hl),a ; put into buffer pop hl ei ret ;----------------------------------------------------------------------------- ; GETBUF - Get a character from the buffer ;----------------------------------------------------------------------------- ; Get a character from the type-ahead buffer ; Entry: None ; Exit: A = Next pending character from the buffer ; Uses: None getbuf: di ; don't allow me to be bothered push hl ; whilst I get a character from the buffer ld a,(optr) ; get the output buffer pointer inc a ; mark one taken ld (optr),a cp iblen ; check that it wasn't advanced past end jp nz,getb1 xor a ; reset back to zero ld (optr),a getb1: ld hl,ibuf ld l,a ld a,(hl) ; get current char or a pop hl ei ret ;============================================================================ ; Console Output Routine ;============================================================================ cout: push af out2: ld a,(ttyc) ; read status and outmask jp z,out2 ; not ready out3: call tick ld a,(xon) ; get the XON status or a jp nz,out3 ; loop if XON WAIT status pop af and 07fh ; strip high bit ld (ttyd),a ; send data ret ;============================================================================ ; Main Menu ;============================================================================ menu: call tinit ; initialize CRT Terminal call cls ; clear screen call vprint defb 'WA1LMV Repeater Controller Vers. ' defb VERS/10+'0','.',VERS MOD 10+'0',cr,lf defb VMONTH/10+'0',VMONTH MOD 10+'0','/' defb VDAY/10+'0',VDAY MOD 10+'0','/' defb VCENT/10+'0',VCENT MOD 10+'0' defb VYEAR/10+'0',VYEAR MOD 10+'0' defb ' by Rick Swenton',cr,lf,0 if a2020 call gron ; enter graphics mode call vprint defb 'ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ',0 call groff ; exit graphics mode else defb '-------------------------------------' endif call vprint defb cr,lf defb 'A - Control Codes N - Voice ID' defb cr,lf defb 'B - Macro Codes O - Output' defb cr,lf defb 'C - CRT Mode P - Chime Control' defb cr,lf defb 'D - Set Tone Dev. Q - Curly' defb cr,lf defb 'E - Set Speech Dev. R - 450 PL Control' defb cr,lf defb 'F - (not used) S - 450 TX Control' defb cr,lf defb 'G - Set Date T - 6M PL Control' defb cr,lf defb 'H - Set Time U - 6M TX Control' defb cr,lf defb 'I - Input V - Autopatch' defb cr,lf defb 'J - Events W - Test Key TX' defb cr,lf defb 'K - Voice Time X - Refresh CRT' defb cr,lf defb 'L - (not used) Y - Refresh Status' defb cr,lf defb 'M - MCW ID Z - Master Reset' defb cr,lf defb '1 - 6M Temp PL 3 - Reset Temp PL' defb cr,lf defb '2 - 450 Temp PL 9 - DTMF Pass-Thru' defb 0 call ucrtt ; write display system skeleton call ucrte ; send one screen update ret cmenu: call menu cmen1: ld a,(merr) ; get the error byte cp 1 ; stack error #1? jp z,stkerr cp 2 ; execution error #2? jp z,exerr cp 3 ; hardware reset jp z,crst ret stkerr: call stat defb bell,'Stack Error #1! ',0 call cbeep ; 1 beep is stack error jp xxerr exerr: call stat defb bell,'Execution Error #2! ',0 call cbeep2 ; 2 beeps is execution error jp xxerr crst: call stat ; status line defb bell,'Controller reset!',7,0 call cbeep3 ; 3 beeps is normal reset xxerr: xor a ld (merr),a call onesec call sndid ; which will initially preset the ID timer ret error: call rmode ; restore current MCW/Speech Mode call stat ; status line defb 'Input Error!',0 call sndng call clstat ; clear again jp warm ; reset the stack ;----------------------------------------------------------------------------- ; Clear the Status Line and print new Status Message ;----------------------------------------------------------------------------- stat: ex (sp),hl ; save HL, get HL = string to print call clstat ; clear the status line and return cursor call pstr ; print the string ex (sp),hl ; restore HL and stack past message ret clstat: call gxymsg ; clear the status line defb 24,1 defb ' ' defb ' ',0 call at ; return cursor defb 24,1 ret ;----------------------------------------------------------------------------- ; Warm Start Entry ;----------------------------------------------------------------------------- warm: ld hl,warm ; return here push hl warm1: ei ; just in case ld a,(cwena) ; save current MCW/Speech Mode ld (cwtmp),a call inclr ; console line - includes Master Loop call rech cp cr ret z call alta defb 31 defb 'A' defw codes ; A - WA1LMV Control Code Emulator defb 'B' defw macod ; B - Macro Codes defb 'C' defw cmode ; C - CRT Mode defb 'D' defw tdev ; D - Test Tone Deviation defb 'E' defw sdev ; E - Test Speech Deviation defb 'F' defw error ; F - defb 'G' defw stdat ; G = Set Date defb 'H' defw sthrs ; H = Set Time defb 'I' defw iport ; I = INPUT from PORT/MEMORY defb 'J' defw setsch ; J = Events defb 'K' defw stime ; K - Voice Time defb 'L' defw error ; L - defb 'M' defw sndid ; M - MCW ID Start defb 'N' defw sndsid ; N - Voice ID Start defb 'O' defw oport ; O - OUTPUT to PORT/MEMORY defb 'P' defw chmt ; P - Chime Control defb 'Q' defw sndnuk ; Q - Curly Routine defb 'R' defw tupl ; R - 450 PL Control defb 'S' defw tutx ; S - 450 TX Control defb 'T' defw tvpl ; T - 6M PL Control defb 'U' defw tvtx ; U - 6M TX Control defb 'V' defw patch ; V - Autopatch on/off defb 'W' defw phtime ; W - Test Key TX - preset hang time to 5 mins defb 'X' defw cmenu ; X - Refresh Screen defb 'Y' defw ucrtc ; Y - Refresh Control defb 'Z' defw xreset ; Z - Master Reset defb '0' defw llun ; 0 - Unlock landline control defb '1' defw vplo ; 1 - Temp 6M PL override defb '2' defw uplo ; 2 - Temp 450 PL override defb '3' defw tpld ; 3 - Reset Temp PL Override defb '9' defw dnul ; 9 - DTMF Pass-Through alta: ex (sp),hl ld c,(hl) alt: inc hl cp (hl) inc hl jp nz,alu ld e,(hl) inc hl ld d,(hl) ex de,hl ex (sp),hl ret alu: dec c inc hl jp nz,alt jp error ; ;----------------------------------------------------------------------------- ; Stack Error - Display Message and restart controller ;----------------------------------------------------------------------------- irst: ld a,1 ld (merr),a ; set error #1 jp reset ;----------------------------------------------------------------------------- ; Execution Error - Display Message and restart controller ;----------------------------------------------------------------------------- erst: ld a,2 ld (merr),a ; set error #2 jp reset ;----------------------------------------------------------------------------- ; This is the entry point to Master Reset the controller ; AND pre-load RAM to the default settings in ROM ;----------------------------------------------------------------------------- xreset: call sndrst ; then fall through ld a,3 ld (merr),a ; set error #3 (hardware reset) ;----------------------------------------------------------------------------- ; This is the system-generated master reset entry point. ; A simple jump to address zero will cause a failure of the ; console port because the USART is already initialized. This ; routine will place the 8251 into mode instruction before ; jumping to zero. ;----------------------------------------------------------------------------- reset: di ld a,cmdrst ; put the 8251 into mode instruction ld (ttyc),a ; send to the chip jp startr ; now reset ;----------------------------------------------------------------------------- ; Mega-Beep! Alarm Clock and Chime Tone ;----------------------------------------------------------------------------- mbeep: call htime ; key the transmitters call onesec ; wait call t440 ; multi-freq super beep 440 Hz call tonon ; tone on ld a,6 ; 60 ms. inter-tone delay call delay call t660 ; 660 Hz. ld a,6 call delay call t800 ; 800 Hz. ld a,6 call delay call t1000 ; 1000 Hz. ld a,6 call delay call t1200 ; 1200 Hz. beep1: ld a,6 call delay beep2: call tonoff ret ;----------------------------------------------------------------------------- ; Simulate Phone Ringing Signal ;----------------------------------------------------------------------------- ding: push hl ld hl,(idtim) ; see if time to ID ld a,h or a,l jp nz,ding1 call sndid ding1: pop hl call htime ; phone ring tone call t440 ; set-up 440 Hz. call tonon ld a,6 ; delay is 60 ms call delay call t660 ; set-up 660 Hz. jp beep1 ; steal some code from above ;----------------------------------------------------------------------------- ; Control System Beep Tone ;----------------------------------------------------------------------------- cbeep3: call cbeep cbeep2: call cbeep ; and fall through cbeep: call htime ; key transmitters call halfsec ; control system tone call t1000 ; set-up 1 KHz. tone call tonon ld a,12 ; 120 ms delay call delay jp tonoff ;----------------------------------------------------------------------------- ; Set Audio Tones to various frequencies ;----------------------------------------------------------------------------- ; Calculation is Divisor = (clock/2) / Desired Freq (Hz.) t2000: ld hl,b2000 ; 2000 Hz. jp tone t1200: ld hl,b1200 ; 1200 Hz. jp tone t1000: ld hl,b1000 ; 1000 Hz. jp tone t900: ld hl,b900 ; 900 Hz. jp tone t800: ld hl,b800 ; 800 Hz. jp tone t660: ld hl,b660 ; 600 Hz. jp tone t550: ld hl,b550 ; 550 Hz. jp tone t500: ld hl,b500 ; 500 Hz. jp tone t480: ld hl,b480 ; 480 Hz. jp tone t440: ld hl,b440 ; 440 Hz. ; Set the tone frequency tone: ld (trate),hl ld a,00110110b ; PIT Control Word (counter 0, Mode 3 ld (pitctl),a ; send to PIC control port ld a,(trate) ; get Initial counter value LSB ld (pitc0),a ; send to PIC counter 0 ld a,(trate+1) ; get Initial counter value MSB ld (pitc0),a ; send to PIC counter 0 ret ;---------------------------- Time Delays ------------------------------------ twosec: ld a,200 ; two second delay jp delay onesec: ld a,100 ; one second delay jp delay halfsec:ld a,50 ; half second delay jp delay qsec: ld a,25 ; quarter second delay jp delay sec17: ld a,14 ; 1/7 second delay jp delay tsec: ld a,10 ; tenth second delay ; fall through ;============================================================================ ; Interrupt managed Time Delay ; (Enter with A = # of 10 ms ticks of delay desired) ;============================================================================ delay: ld (gpt),a dly1: call tick ; tick the watchdog ld a,(gpt) or a jp nz,dly1 ret subttl MCW Generation/Processing page include mcw.z80 subttl MCW Generation/Processing ;---------------------------------------------------------------------------- ; MCW Message Strings ;---------------------------------------------------------------------------- ; MCW messages are entered here in plain ASCII terminated by ; a trailing zero. Only letters, numbers and the "/" characters ; are currently supported. Blank space characters control ; spacing. okmsg: defb 'OK ',0 ngmsg: defb 'NG ',0 nomsg: defb 'NO ',0 idmsg: defb 'DE WA1LMV /R ',0 beermsg:defb 'BEER ',0 qrzmsg: defb 'QRZ ',0 rstmsg: defb 'RST ',0 onmsg: defb 'ON ',0 offmsg: defb 'OFF ',0 ;---------------------------------------------------------------------------- ;============================================================================ ; Send MCW or Speech Messages ;============================================================================ sndno: call tstcw ; check current Speech/MCW Mode jp nz,sndmno call ssfn ; say FUNCTION jp ssdis ; say DISABLED sndmno: call t660 ld hl,nomsg jp cw ; send NO sndcn: call tstcw jp nz,sndon1 call ssctl ; say CONTROL FUNCTION sndon: call tstcw jp z,sndson sndon1: call t660 ld hl,onmsg ; send ON jp cw sndcff: call tstcw jp nz,sndof1 call ssctl ; say CONTROL FUNCTION sndoff: call tstcw jp z,sndsoff sndof1: call t660 ld hl,offmsg ; send OFF jp cw sndok: call t660 ld hl,okmsg ; send OK jp cw sndng: call t660 ld hl,ngmsg ; send NG jp cw tstcw: ld a,(cwena) ; see if speech enabled cp 2 ; 2 = Speech Mode ret ; Send ID -- no test is made for CW enable because the ID ; should never be disabled sndid: ld hl,(mdfcwt) call tone ; set the MCW frequency ld a,1 ; set CWPTT flag ld (cwptt),a ld hl,(mdfid) ; preset default ID timer value ld (idtim),hl xor a ld (fidtm),a ; reset the foreground task flag ld (bidflg),a ; reset the Broadcast ID flag call ucrt call halfsec ld hl,idmsg ; send call letters jp cw2 ; bypass MCW enable test sndcst: call tstcw jp z,sndscr ; speak CONTROL RESET call t660 ld hl,rstmsg jp cw ; send RST in MCW sndrst: call tstcw jp z,sndsmr ; speak MASTER RESET sndrs1: call t660 ld hl,rstmsg push hl call cw ; send RST pop hl jp cw ; send again sndbeer:call t1000 ld a,1 ld (cwptt),a ; key transmitters call onesec ; wait for them to come on ld hl,beermsg ; BEER message push hl call cw ; send BEER pop hl call cw ; send again jp sndid ; now ID sndqrz: call t660 ld hl,qrzmsg ; send QRZ call cw jp sndid ;============================================================================ ; CW - Send MCW tones according to the following input: ; ; hl points to a string of characters to send ; 0 is the END-OF-STRING terminator ; ; Placing a NZ value in CWPTT will cause the interrupt service ; routine to key the transmitters. The SNDID routine enters ; at CW1. ; ;============================================================================ cw: ld a,1 ld (cwptt),a ; set the CW PTT flag cw1: ld a,(cwena) ; is MCW enabled? or a jp nz,cw2 ; no, then bail out xor a ld (cwptt),a ; reset the CW PTT flag ret cw2: ld a,(port7s) ; see if either transmitter and utx+vtx ; is on jp nz,cw3 call onesec ; wait for transmitter to come on cw3: push hl push de push bc cw4: ld a,(hl) ; get the character or a jp z,cwx ; quit if zero cp 20h ; space jp z,cw5 call cwl ; send the letter inc hl ; get next ascii character call sp1 jp cw4 cw5: call mcwdly ; perfect spacing calls for 4 call sp3 ; element delays. Do one now inc hl ; and call sp3 to do 3 more. jp cw4 ; Go past the space char and get more. cwx: xor a ld (cwptt),a ; reset the CW PTT flag pop bc pop de pop hl ret ;---------------------------------------------------------------------------- ; Send a letter in MCW ;---------------------------------------------------------------------------- ; Enter with A containing the ASCII value of the character ; to send in MCW cwl: push hl push de push bc push af cp 61h ; greater than ascii 'a'? jp c,cwlu ; carry =numbers/symbols/Upper Case and 5fh ; make upper case cwlu: sub 2eh ; ascii bias (start with period 2eh) ld d,0 ld e,a ; put result in DE ld hl,cwtbl ; point to char table add hl,de ; offset to desired char ld a,(hl) cwl1: ld b,a cp 80h jp z,cwl4 ; exit when shift results in 80h and 80h ; look at most significant bit jp z,cwl2 call dash ; 1 is a dash jp cwl3 cwl2: call dot ; 0 is a dot cwl3: ld a,b rl a ; rotate jp cwl1 cwl4: call sp0 ; space pop af pop bc pop de pop hl ret ; Send a Dash dash: call tonon call mcwdly ; keep tone on for 3 time intervals sp3: call mcwdly sp1: call mcwdly sp0: call tonoff jp mcwdly ; 1 interval inter-element space ; Send a tone dot: call tonon jp sp1 ; wait one interval and off again tonon: ld a,(port4s) ; turn-on tone or mcwt ; tone osc bit ld (port4s),a ret tonoff: ld a,(port4s) ; turn off tone and not mcwt ; tone osc bit ld (port4s),a ret ;========================= CW Character Table =============================== ; ; The most significant bit is tested. 1 is a dash, 0 is a dot. ; Finish with a 1. The byte is shifted left repeatedly ; until an 80H is left. ; ; Example: / is (_.._.) 1001 0100 is 94h ; 1 is (.____) 0111 1100 is 7ch ; ; Table is in ASCII numerical sequence ; ;============================================================================ cwtbl: defb 056h ; . defb 094h ; / defb 0fch ; 0 defb 07ch ; 1 defb 03ch ; 2 defb 01ch ; 3 defb 00ch ; 4 defb 004h ; 5 defb 084h ; 6 defb 0c4h ; 7 defb 0e4h ; 8 defb 0f4h ; 9 defb 080h ; : undefined defb 080h ; ; undefined defb 080h ; < undefined defb 080h ; = undefined defb 080h ; > undefined defb 032h ; ? defb 080h ; @ undefined defb 060h ; A defb 088h ; B defb 0a8h ; C defb 090h ; D defb 040h ; E defb 028h ; F defb 0d0h ; G defb 008h ; H defb 020h ; I defb 078h ; J defb 0b0h ; K defb 048h ; L defb 0e0h ; M defb 0a0h ; N defb 0f0h ; O defb 068h ; P defb 0d8h ; Q defb 050h ; R defb 010h ; S defb 0c0h ; T defb 030h ; U defb 018h ; V defb 070h ; W defb 098h ; X defb 0b8h ; Y defb 0c8h ; Z mcwdly: ld a,(mdfwpm) ; default dot length ld (idspd),a mcdly1: call tick ; tick the watchdog ld a,(idspd) or a jp nz,mcdly1 ret ;------------------------- end of file MCW.Z80 ------------------------------- subttl SSI-263 Speech System page include speech.z80 subttl SSI-263 Speech System ;============================================================================ ; Speech System ;============================================================================ speech: ld a,1 ld (cwptt),a ; set the CW PTT flag (not an ID) spch1: call tstcw ; see if Speech enabled jp nz,slx ; bail out if non-zero spch2: ld a,(mdfsr) ; get the default speech rate and 11110000b ; inflection is always 1000b lower nib or 00001000b ; rate values are 08 through f8 ld (rateinf),a ; set the rate/inflection ld a,(hl) ; get number of bytes to send ld c,a ; save inc hl sloop: ld a,(hl) ; get the filter frequency ld (filfreq),a ; set the filter frequency inc hl ld a,(hl) ; get the inflection and 00011111b ; only 5 bits allowed 0 to 31 sub 4 rlc a ; shift into upper position rlc a rlc a ld b,a ; save ld a,(mdfir) ; get the default inflection rate and 00000111b ; only 3 bits allowed 0 to 7 or a,b ld (inflect),a ; set the inflection and rate inc hl ld a,(mdfar) ; get the default articulation rate rlc a ; shift into upper position rlc a rlc a rlc a and 01111111b ; block usb (CTL bit) just in case ld b,a ; save ld a,(hl) ; get the desired amplitude and 00001111b ; only look at lower 4 bits (amplitude) or b ; or-in the articulation rate ld (cttramp),a ; set the articulation/amplitude inc hl ld a,(hl) and 00111111b or 01000000b ld (durphon),a ; load the phoneme inc hl sl2: ld a,(port0) ; get Request bit and spreq ; goes from low to high to request jp z,sl2 ; bit is hardware inverted, new phoneme call tick ; tick the watchdog dec c jp nz,sloop slx: xor a ld (sbase),a ; turn-off the SSI-263 ld (cwptt),a ; reset the CW PTT flag ret ;============================================================================= ; Speech Tables: ; ; 1 - Filter Frequency ; 2 - Inflection ; 3 - Articulation/Ramp ; 4 - Duration/Phoneme spap: ld hl,$+6 jp speech defb 10 ; number of 4-byte blocks in message ; FF INF AMP DPH defb 0deh,16,8,010h ; AW (autopatch) defb 0deh,16,8,010h ; AW defb 0deh,16,8,028h ; T defb 0deh,15,8,011h ; O defb 0deh,12,8,027h ; P defb 0deh,12,8,00ch ; AE defb 0deh,12,8,00ch ; AE defb 0deh,12,8,028h ; T defb 0deh,12,8,032h ; SCH defb 0deh,12,8,000h spat: ld hl,$+6 jp speech defb 5 ; number of 4-byte blocks in message ; FF INF AMP DPH defb 0deh,16,8,00ch ; AE (at) defb 0deh,16,8,00ch ; AE defb 0deh,16,8,028h ; T defb 0deh,12,8,000h defb 0deh,12,8,000h sptod: ld hl,$+6 jp speech defb 12 ; number of 4-byte blocks in message ; FF INF AMP DPH defb 0deh,12,8,0e8h ; T (today is) defb 0deh,14,8,0d6h ; U defb 0deh,16,8,0d6h ; U defb 0deh,18,8,025h ; D defb 0deh,16,8,008h ; A defb 0deh,16,8,008h ; A defb 0deh,14,8,001h ; E defb 0deh,14,8,000h defb 0deh,12,8,007h ; I defb 0deh,14,8,007h ; I defb 0deh,16,8,02fh ; Z defb 0deh,16,8,000h sptx: ld hl,$+6 jp speech defb 10 ; number of 4-byte blocks in message ; FF INF AMP DPH defb 0deh,16,8,028h ; T (transmit) defb 0deh,16,8,01dh ; R defb 0deh,16,8,00ch ; AE defb 0deh,16,8,00ch ; AE defb 0deh,16,8,038h ; N defb 0deh,16,8,030h ; S defb 0deh,16,8,037h ; M defb 0deh,16,8,007h ; I defb 0deh,16,8,028h ; T defb 0deh,15,8,000h spant: ld hl,$+6 jp speech defb 10 ; number of 4-byte blocks in message ; FF INF AMP DPH defb 0deh,14,8,00dh ; AE1 (antenna) defb 0deh,14,8,00dh ; AE1 defb 0deh,14,8,038h ; N defb 0deh,16,8,028h ; T defb 0deh,18,8,00ah ; EH defb 0deh,18,8,00ah ; EH defb 0deh,16,8,038h ; N defb 0deh,16,8,00eh ; AH defb 0deh,15,8,000h defb 0deh,15,8,000h sprx: ld hl,$+6 jp speech defb 7 ; number of 4-byte blocks in message ; FF INF AMP DPH defb 0deh,16,8,01dh ; R (receive) defb 0deh,16,8,001h ; E defb 0deh,16,8,030h ; S defb 0deh,16,8,001h ; E defb 0deh,16,8,001h ; E defb 0deh,16,8,033h ; V defb 0deh,15,8,000h smeter: ld hl,$+6 jp speech defb 8 ; number of 4-byte blocks in message ; FF INF AMP DPH defb 0deh,16,8,037h ; M (meter) defb 0deh,16,8,001h ; E defb 0deh,16,8,001h ; E defb 0deh,16,8,028h ; T defb 0deh,16,8,01ch ; ER defb 0deh,15,8,000h defb 0deh,15,8,000h defb 0deh,15,8,000h sp450: call s4 ; say 450 jp s50 sp6m: call s6 ; say 6 Meter jp smeter sp2m: call s2 ; say 2 Meter jp smeter sp10m: call s10 ; say 10 Meter jp smeter sndshe: ld hl,$+6 jp speech defb 7 ; number of 4-byte blocks in message ; FF INF AMP DPH defb 0deh,09,8,0ach ; HF (hello) defb 0deh,12,8,0cah ; EH defb 0deh,14,8,0cah ; EH defb 0deh,16,8,0e0h ; L defb 0deh,18,8,0a0h ; L defb 0deh,17,8,0d1h ; O defb 0deh,16,8,0e3h ; W sndgd: ld hl,$+6 jp speech defb 5 ; number of 4-byte blocks in message ; FF INF AMP DPH defb 0deh,12,8,026h ; KV (Good) defb 0deh,12,8,018h ; UH defb 0deh,12,8,018h ; UH defb 0deh,12,8,025h ; D defb 0deh,12,8,000h sndmn: ld hl,$+6 jp speech defb 8 ; number of 4-byte blocks in message ; FF INF AMP DPH defb 0deh,19,8,037h ; M (morning) defb 0deh,18,8,011h ; O defb 0deh,17,8,011h ; O defb 0deh,17,8,01dh ; R defb 0deh,16,8,038h ; N defb 0deh,15,8,007h ; I defb 0deh,12,8,039h ; NG defb 0deh,15,8,000h sndaf: ld hl,$+6 jp speech defb 10 ; number of 4-byte blocks in message; FF INF RMP DPH ; FF INF AMP DPH defb 0deh,12,8,00ch ; AE (afternoon) defb 0deh,12,8,00ch ; AE defb 0deh,12,8,034h ; F defb 0deh,12,8,028h ; T defb 0deh,12,8,01ch ; ER defb 0deh,18,8,038h ; N defb 0deh,17,8,016h ; U defb 0deh,16,8,016h ; U defb 0deh,15,8,038h ; N defb 0deh,15,8,000h sndeve: ld hl,$+6 jp speech defb 8 ; number of 4-byte blocks in message ; FF INF AMP DPH defb 0deh,18,8,001h ; E (evening) defb 0deh,18,8,001h ; E defb 0deh,17,8,033h ; V defb 0deh,16,8,038h ; N defb 0deh,15,8,007h ; I defb 0deh,15,8,007h ; I defb 0deh,12,8,039h ; NG defb 0deh,15,8,000h welmsg: ld hl,$+6 jp speech defb 13 ; FF INF AMP DPH defb 0deh,14,8,023h ; W (welcome) defb 0deh,16,8,00ah ; EH defb 0deh,18,8,020h ; L defb 0deh,16,8,029h ; K defb 0deh,14,8,018h ; UH defb 0deh,13,8,037h ; M defb 0deh,13,8,000h defb 0deh,13,8,028h ; T (to) defb 0deh,14,8,016h ; U defb 0deh,15,8,016h ; U defb 0deh,16,8,035h ; THV (the) defb 0deh,16,8,018h ; UH defb 0deh,16,8,000h ; sidmsg: ld a,1 ; set the CWPTT flag ld (cwptt),a ld hl,(mdfid) ; preset default ID timer value ld (idtim),hl xor a ld (fidtm),a ; reset foreground task flag ld (bidflg),a ; reset the Broadcast ID flag ld hl,$+6 jp spch1 defb 31 ; FF INF AMP DPH defb 0deh,17,8,025h ; D (W) defb 0deh,17,8,018h ; UH defb 0deh,17,8,024h ; B defb 0deh,17,8,020h ; L defb 0deh,17,8,004h ; Y defb 0deh,17,8,016h ; U defb 0deh,17,8,008h ; A (A) defb 0deh,18,8,008h ; A defb 0deh,17,8,001h ; E defb 0deh,16,8,023h ; W (1) defb 0deh,15,8,018h ; UH defb 0deh,15,8,038h ; N defb 0deh,15,8,000h ; defb 0deh,16,8,00ah ; EH (L) defb 0deh,16,8,020h ; L defb 0deh,16,8,00ah ; EH (M) defb 0deh,16,8,037h ; M defb 0deh,16,8,033h ; V (V) defb 0deh,17,8,033h ; V defb 0deh,18,8,001h ; E defb 0deh,17,8,001h ; E defb 0deh,16,8,000h defb 0deh,16,8,000h defb 0deh,16,8,01dh ; R (repeater) defb 0deh,16,8,001h ; E defb 0deh,16,8,027h ; P defb 0deh,17,8,001h ; E defb 0deh,15,8,001h ; E defb 0deh,13,8,028h ; T defb 0deh,11,8,01ch ; ER defb 0deh,15,8,000h ssfn: ld hl,$+6 jp speech defb 10 ; FF INF AMP DPH defb 0deh,16,8,034h ; F (function) defb 0deh,17,8,019h ; UH defb 0deh,18,8,039h ; NG defb 0deh,17,8,029h ; K defb 0deh,08,8,032h ; SCH defb 0deh,07,8,01bh ; UH3 defb 0deh,08,8,01bh ; UH3 defb 0deh,09,8,038h ; N defb 0deh,16,8,038h ; N defb 0deh,16,8,000h ; sndson: ld hl,$+6 jp speech defb 4 ; FF INF AMP DPH defb 0ddh,19,8,00eh ; AH (on) defb 0ddh,17,8,00eh ; AH defb 0ddh,15,8,038h ; N defb 0ddh,13,8,038h ; N sndsoff:ld hl,$+6 jp speech defb 4 ; FF INF AMP DPH defb 0ddh,19,8,010h ; AW (off) defb 0ddh,17,8,010h ; AW defb 0ddh,15,8,034h ; F defb 0ddh,13,8,034h ; F sndnuk: xor a ; reset both 6M and 450 ld (fvctm),a ; courtesy tone foreground flags ld (fuctm),a ; to eliminate trailing beep call htime ; the curly routine call onesec call t440 ; musical note A call tonon ; tone on call sec17 ; 1/7 second delay call t500 ; musical note B call sec17 ; 1/7 second delay call t550 ; musical note C# call sec17 ; 1/7 second delay call t500 ; musical note B call sec17 ; 1/7 second delay call tonoff ; tone off call sec17 ; 1/7 second delay call tonon call t550 ; musical note C# call sec17 ; 1/7 second delay call t440 ; musical note A call sec17 ; 1/7 second delay call tonoff ld a,(mdfsr) ; get current speech rate push af ld a,0b0h ; set up faster speech rate ld (mdfsr),a call sndnk pop af ld (mdfsr),a ; restore old speech rate call halfsec call t900 ; musical note high A call tonon ; tone on call sec17 ; 1/7 second delay call tonoff ; tone off call onesec ret sndnk: ld hl,$+6 jp speech defb 20 ; FF INF AMP DPH defb 0eeh,19,8,0f8h ; N (nuk, nuk ...) defb 0eeh,18,8,0f8h ; N defb 0eeh,17,8,0dbh ; UH3 defb 0eeh,16,8,0e9h ; K defb 0eeh,16,8,0c0h ; defb 0eeh,16,8,0f8h ; N defb 0eeh,15,8,0f8h ; N defb 0eeh,15,8,0dbh ; UH3 defb 0eeh,14,8,0e9h ; K defb 0eeh,14,8,0c0h ; defb 0eeh,13,8,0f8h ; N defb 0eeh,13,8,0f8h ; N defb 0eeh,12,8,0dbh ; UH3 defb 0eeh,12,8,0e9h ; K defb 0eeh,11,8,0c0h ; defb 0eeh,11,8,0f8h ; N defb 0eeh,11,8,0f8h ; N defb 0eeh,11,8,0dbh ; UH3 defb 0eeh,11,8,0e9h ; K defb 0eeh,11,8,0c0h ; ssmst: ld hl,$+6 jp speech defb 7 ; FF INF AMP DPH defb 0deh,12,8,037h ; M (Master) defb 0deh,14,8,00ch ; AE defb 0deh,16,8,00ch ; AE defb 0deh,15,8,030h ; S defb 0deh,11,8,028h ; T defb 0deh,12,8,01ch ; ER defb 0deh,16,8,000h ; ssdis: ld a,(cwena) ; speech mode enabled? cp 2 jp nz,sndoff ld hl,$+6 jp speech defb 11 ; FF INF AMP DPH defb 0deh,16,8,000h ; defb 0deh,16,8,025h ; D (Disabled) defb 0deh,16,8,007h ; I defb 0deh,16,8,030h ; S defb 0deh,17,9,008h ; A defb 0deh,18,10,008h ; A defb 0deh,17,9,001h ; E defb 0deh,16,8,024h ; B defb 0deh,16,8,020h ; L defb 0deh,16,8,020h ; L defb 0deh,16,8,025h ; D ssena: ld a,(cwena) ; speech mode enabled? cp 2 jp nz,sndon ld hl,$+6 jp speech defb 10 ; FF INF AMP DPH defb 0deh,16,8,000h ; defb 0deh,16,8,00ah ; E (Enabled) defb 0deh,16,8,038h ; N defb 0deh,17,9,008h ; A defb 0deh,18,10,008h ; A defb 0deh,17,9,001h ; E defb 0deh,16,8,024h ; B defb 0deh,16,8,020h ; L defb 0deh,16,8,020h ; L defb 0deh,16,8,025h ; D ssctl: call ssctl1 ; say CONTROL jp ssfn ; say FUNCTION ssctl1: ld hl,$+6 jp speech defb 12 ; FF INF AMP DPH defb 0deh,12,8,029h ; K (Control) defb 0deh,12,8,029h ; K defb 0deh,12,8,019h ; UH1 defb 0deh,13,8,038h ; N defb 0deh,14,8,038h ; N defb 0deh,15,8,028h ; T defb 0deh,17,8,01dh ; R defb 0deh,18,8,011h ; O defb 0deh,17,8,011h ; O defb 0deh,16,8,020h ; L defb 0deh,16,8,000h ; defb 0deh,16,8,000h ; ssusr: call ssusr1 ; say USER jp ssfn ; say FUNCTION ssusr1: ld hl,$+6 jp speech defb 6 ; FF INF AMP DPH defb 0deh,15,8,001h ; E (User) defb 0deh,16,8,016h ; U defb 0deh,18,8,016h ; U defb 0deh,17,8,02fh ; Z defb 0deh,16,8,01ch ; ER defb 0deh,16,8,000h ; spspd: ld hl,$+6 jp speech defb 12 ; FF INF AMP DPH defb 0deh,15,8,030h ; S (Speed Dial) defb 0deh,16,8,027h ; P defb 0deh,18,8,001h ; E defb 0deh,17,8,001h ; E defb 0deh,16,8,025h ; D defb 0deh,16,8,000h ; defb 0deh,12,8,025h ; D defb 0deh,14,8,00fh ; AH1 defb 0deh,14,8,00fh ; AH1 defb 0deh,14,8,001h ; E defb 0deh,14,8,022h ; LF defb 0deh,16,8,000h ; ssrst: ld hl,$+6 jp speech defb 7 ; FF INF AMP DPH defb 0deh,12,8,01dh ; R (Reset) defb 0deh,15,8,001h ; E defb 0deh,17,8,001h ; E defb 0deh,14,8,030h ; S defb 0deh,14,8,030h ; S defb 0deh,14,8,00ah ; EH defb 0deh,14,8,028h ; T sa: ld hl,$+6 jp speech defb 4 ; FF INF AMP DPH defb 0deh,14,8,0c8h ; A (A) defb 0deh,15,8,0c8h ; A defb 0deh,16,8,0c1h ; E defb 0deh,16,8,0c1h ; E sb: ld hl,$+6 jp speech defb 4 ; FF INF AMP DPH defb 0deh,14,8,0e4h ; B (B) defb 0deh,15,8,0e4h ; B defb 0deh,16,8,0c1h ; E defb 0deh,16,8,0c1h ; E sc: ld hl,$+6 jp speech defb 4 ; FF INF AMP DPH defb 0deh,14,8,0f0h ; S (C) defb 0deh,15,8,0f0h ; S defb 0deh,16,8,0c1h ; E defb 0deh,16,8,0c1h ; E sd: ld hl,$+6 jp speech defb 4 ; FF INF AMP DPH defb 0deh,14,8,0e5h ; D (D) defb 0deh,15,8,0e5h ; D defb 0deh,16,8,0c1h ; E defb 0deh,16,8,0c1h ; E se: ld hl,$+6 jp speech defb 3 ; FF INF AMP DPH defb 0deh,14,8,0c1h ; E (E) defb 0deh,15,8,0c1h ; E defb 0deh,16,8,0c1h ; E sf: ld hl,$+6 jp speech defb 4 ; FF INF AMP DPH defb 0deh,14,8,0cah ; EH (F) defb 0deh,15,8,0cah ; EH defb 0deh,16,8,0f4h ; F defb 0deh,16,8,0f4h ; F s0: ld hl,$+6 jp speech defb 5 ; FF INF AMP DPH defb 0deh,18,8,0efh ; Z (0) defb 0deh,16,8,0c1h ; E defb 0deh,14,8,0ddh ; R defb 0deh,14,8,0d1h ; O defb 0deh,14,8,0d1h ; O s1: ld hl,$+6 jp speech defb 4 ; FF INF AMP DPH defb 0deh,18,8,0e3h ; W (1) defb 0deh,16,8,0d8h ; UH defb 0deh,16,8,0d8h ; UH defb 0deh,14,8,0f8h ; N s2: ld hl,$+6 jp speech defb 3 ; FF INF AMP DPH defb 0deh,18,8,0e8h ; T (2) defb 0deh,16,8,0d6h ; U defb 0deh,14,8,0d6h ; U s3: ld hl,$+6 jp speech defb 4 ; FF INF AMP DPH defb 0deh,14,8,0f5h ; THV (3) defb 0deh,16,8,0ddh ; R defb 0deh,18,8,0c1h ; E defb 0deh,16,8,0c1h ; E s4: ld hl,$+6 jp speech defb 4 ; FF INF AMP DPH defb 0deh,18,8,0f4h ; F (4) defb 0deh,16,8,0d1h ; O defb 0deh,14,8,0d1h ; O defb 0deh,14,8,0dch ; ER s5: ld hl,$+6 jp speech defb 5 ; FF INF AMP DPH defb 0deh,18,8,0f4h ; F (5) defb 0deh,18,8,0cfh ; AH1 defb 0deh,16,8,0cfh ; AH1 defb 0deh,14,8,0c1h ; E defb 0deh,14,8,0f3h ; V s6: ld hl,$+6 jp speech defb 5 ; FF INF AMP DPH defb 0deh,18,8,0f0h ; S (6) defb 0deh,18,8,0f0h ; S defb 0deh,16,8,0c7h ; I defb 0deh,15,8,0e9h ; K defb 0deh,14,8,0f0h ; S s7: ld hl,$+6 jp speech defb 5 ; FF INF AMP DPH defb 0deh,18,8,0f0h ; S (7) defb 0deh,18,8,0cah ; EH defb 0deh,16,8,0f3h ; V defb 0deh,18,8,0cah ; EH defb 0deh,14,8,0f8h ; N s8: ld hl,$+6 jp speech defb 3 ; FF INF AMP DPH defb 0deh,18,8,0c8h ; A (8) defb 0deh,16,8,0c1h ; E defb 0deh,14,8,0e8h ; T s9: ld hl,$+6 jp speech defb 5 ; FF INF AMP DPH defb 0deh,18,8,0f8h ; N (9) defb 0deh,18,8,0cfh ; AH1 defb 0deh,16,8,0cfh ; AH1 defb 0deh,14,8,0c1h ; E defb 0deh,14,8,0f8h ; N s10: ld hl,$+6 jp speech defb 5 ; FF INF AMP DPH defb 0deh,18,8,0e8h ; T (TEN) defb 0deh,18,8,0e8h ; T defb 0deh,16,8,0cah ; EH defb 0deh,14,8,0cah ; EH defb 0deh,14,8,0f8h ; N s11: ld hl,$+6 jp speech defb 7 ; FF INF AMP DPH defb 0deh,16,8,0c1h ; E (ELEVEN) defb 0deh,16,8,0c1h ; E defb 0deh,17,8,0e0h ; L defb 0deh,18,8,0cah ; EH defb 0deh,17,8,0f3h ; V defb 0deh,16,8,0c2h ; E1 defb 0deh,15,8,0f8h ; N s12: ld hl,$+6 jp speech defb 5 ; FF INF AMP DPH defb 0deh,14,8,0e8h ; T (TWELVE) defb 0deh,15,8,0e3h ; W defb 0deh,16,8,0cah ; EH defb 0deh,15,8,0e1h ; L1 defb 0deh,14,8,0f3h ; V s13: ld hl,s13msg call speech jp steen s14: call s4 jp steen s15: ld hl,s15msg call speech jp steen s16: call s6 jp steen s17: call s7 jp steen s18: call s8 jp steen s19: call s9 jp steen s20: ld hl,s20msg call speech jp sty s30: ld hl,s13msg call speech jp sty s40: call s4 jp sty s50: ld hl,s15msg call speech jp sty s13msg: defb 3 ; FF INF AMP DPH defb 0deh,17,8,0f6h ; TH (THIRteen) defb 0deh,16,8,0dch ; ER defb 0deh,15,8,0dch ; ER s15msg: defb 4 ; FF INF AMP DPH defb 0deh,16,8,0f4h ; F (FIFteen) defb 0deh,18,8,0c7h ; I defb 0deh,18,8,0c7h ; I defb 0deh,16,8,0f4h ; F s20msg: defb 4 ; FF INF AMP DPH defb 0deh,14,8,0e8h ; T (TWENty) defb 0deh,15,8,0e3h ; W defb 0deh,16,8,0cah ; EH defb 0deh,15,8,0f8h ; N sty: ld hl,$+6 jp speech defb 3 ; FF INF AMP DPH defb 0deh,16,8,0e8h ; T defb 0deh,15,8,0c1h ; E defb 0deh,14,8,0c1h ; E steen: ld hl,$+6 jp speech defb 4 ; FF INF AMP DPH defb 0deh,16,8,0e8h ; T defb 0deh,17,8,0c1h ; E defb 0deh,16,8,0c1h ; E defb 0deh,15,8,0f8h ; N sp: ld hl,$+6 jp speech defb 3 ; FF INF AMP DPH defb 0deh,17,8,0e7h ; P (P) defb 0deh,16,8,0c1h ; E defb 0deh,14,8,0c1h ; E sm: ld hl,$+6 jp speech defb 3 ; FF INF AMP DPH defb 0deh,16,8,0cah ; E (M) defb 0deh,16,8,0f7h ; M defb 0deh,16,8,0f7h ; M sl: ld hl,$+6 jp speech defb 3 ; FF INF AMP DPH defb 0deh,16,8,00ah ; EH (L) defb 0deh,16,8,020h ; L defb 0deh,16,8,020h ; L timmsg: defb 15 ; FF INF AMP DPH defb 0deh,13,8,0f5h ; THV (The) defb 0deh,14,8,0ceh ; AH defb 0deh,14,8,0ceh ; AH defb 0deh,16,8,0c0h ; defb 0deh,18,8,0e8h ; T (time) defb 0deh,18,8,0cfh ; AH1 defb 0deh,16,8,0cfh ; AH1 defb 0deh,14,8,0c1h ; E defb 0deh,14,8,0f7h ; M defb 0deh,12,8,0c0h ; defb 0deh,14,8,0c7h ; I (is defb 0deh,16,8,0f0h ; S defb 0deh,16,8,0c0h ; defb 0deh,16,8,0c0h ; defb 0deh,16,8,0c0h ; sand: ld hl,$+6 jp speech defb 5 ; FF INF AMP DPH defb 0deh,16,8,0c0h ; defb 0deh,16,8,0cdh ; A (AND) defb 0deh,16,8,0f8h ; N defb 0deh,16,8,0e5h ; D defb 0deh,16,8,0c0h ; spnt: ld hl,$+6 jp speech defb 5 ; FF INF AMP DPH defb 0deh,16,8,0e7h ; P (POINT) defb 0deh,16,8,0d1h ; O defb 0deh,16,8,0c1h ; E defb 0deh,16,8,0f8h ; N defb 0deh,16,8,0e8h ; T ;============================================================================= ; Speak Letters or Numbers ;============================================================================= spkln: call alta defb 16 defb '0' defw s0 ; zero defb '1' defw s1 ; one defb '2' defw s2 ; two defb '3' defw s3 ; three defb '4' defw s4 ; four defb '5' defw s5 ; five defb '6' defw s6 ; six defb '7' defw s7 ; seven defb '8' defw s8 ; eight defb '9' defw s9 ; nine defb 'A' defw sa ; A defb 'B' defw sb ; B defb 'C' defw sc ; C defb 'D' defw sd ; D defb 'E' defw se ; E defb 'F' defw sf ; F sndsmr: call ssmst ; Send MASTER jp ssrst ; Send RESET sndscr: call ssctl1 ; Send CONTROL jp ssrst ; Send RESET sndstd: call tstcw ; see if speech enabled jp nz,sndid call stime ; speek the time call onesec jp sndsid ; Voice ID sndsid: call tstcw ; see if speech enabled jp nz,sndid call ucrt call halfsec ; wait for transmitter call welmsg ; welcome message jp sidmsg ; call sign sndsbd: call tstcw ; see if speech enabled jp nz,sndid ld a,2 ; set the ID PTT flag ld (cwptt),a call ucrt call halfsec ; wait for transmitter jp sidmsg ;----------------------------------------------------------------------------- ; Speak the Clock Time ;----------------------------------------------------------------------------- stime: call tstcw ; see if speech enabled jp nz,sndno call rdtim ; read the clock chip (if there) ; and save in memory ld a,1 ld (cwptt),a call htime call halfsec call ucrt call sndgd ; say GOOD ld a,(mhrs) ; get the hours cp 18h ; greater than 6 PM? jp nc,seve cp 12h ; greater than 12 noon? jp nc,saft call sndmn ; say MORNING jp stima seve: call sndeve jp stima saft: call sndaf stima: call onesec ld hl,timmsg call speech stimt: call shrs ld a,10 call delay stim1: ld a,(mmin) ; get the current minutes or a jp z,stimx cp 0ah ; under 10 minutes? jp c,stimx2 ; speak units of minutes (1 -> 9) cp 1ah ; under 20 minutes? jp c,stimx3 ; speak ELEVEN to NINETEEN and 0f0h ; 20, 30, 40 or 50 minutes? jp z,stimx4 call sten2 ; speak the tens of minutes call sunim ; speak the units of minutes stimx: call sec17 ; 1/7 sec delay stim2: ld a,(mhrs) cp 12h jp c,stimx1 call sp jp sm stimx1: call sa jp sm stimx2: call s0 ; time less than 10 minutes call sunim ; say "zero", then units of minutes jp stimx stimx3: call sten1 jp stimx stimx4: call sten2 jp stimx stret: ret shrs: ld a,(mhrs) ; get the current hours smom: call alta ; speak 24-hour time in defb 24 ; 12 hour format defb 0 defw s12 ; 12 AM defb 1 defw s1 ; 1 AM defb 2 defw s2 ; 2 AM defb 3 defw s3 ; 3 AM defb 4 defw s4 ; 4 AM defb 5 defw s5 ; 5 AM defb 6 defw s6 ; 6 AM defb 7 defw s7 ; 7 AM defb 8 defw s8 ; 8 AM defb 9 defw s9 ; 9 AM defb 10h defw s10 ; 10 AM defb 11h defw s11 ; 11 AM defb 12h defw s12 ; 12 PM defb 13h defw s1 ; 1 PM defb 14h defw s2 ; 2 PM defb 15h defw s3 ; 3 PM defb 16h defw s4 ; 4 PM defb 17h defw s5 ; 5 PM defb 18h defw s6 ; 6 PM defb 19h defw s7 ; 7 PM defb 20h defw s8 ; 8 PM defb 21h defw s9 ; 9 PM defb 22h defw s10 ; 10 PM defb 23h defw s11 ; 11 PM sunim: ld a,(mmin) ; get the current minutes and 0fh ; look at lower nibble smuni: call alta defb 10 defb 0 defw stret ; 0 MIN defb 1 defw s1 ; 1 MIN defb 2 defw s2 ; 2 MIN defb 3 defw s3 ; 3 MIN defb 4 defw s4 ; 4 MIN defb 5 defw s5 ; 5 MIN defb 6 defw s6 ; 6 MIN defb 7 defw s7 ; 7 MIN defb 8 defw s8 ; 8 MIN defb 9 defw s9 ; 9 MIN sten1: ld a,(mmin) ; get the current minutes and 0fh ; look at lower nibble smtn1: call alta defb 10 defb 0 defw s10 ; TEN minutes defb 1 defw s11 ; ELEVEN minutes defb 2 defw s12 ; TWELVE minutes defb 3 defw s13 ; THIRTEEN minutes defb 4 defw s14 ; FOURTEEN minutes defb 5 defw s15 ; FIFTEEN minutes defb 6 defw s16 ; SIXTEEN minutes defb 7 defw s17 ; SEVENTEEN minutes defb 8 defw s18 ; EIGHTEEN minutes defb 9 defw s19 ; NINETEEN minutes sten2: ld a,(mmin) ; get the current minutes and 0f0h ; look at upper nibble smtn2: call alta defb 4 defb 20h defw s20 ; TWENTY minutes defb 30h defw s30 ; THIRTY minutes defb 40h defw s40 ; FOURTY minutes defb 50h defw s50 ; FIFTY minutes ;----------------------------------------------------------------------------- ; Speak the Month/Date ;----------------------------------------------------------------------------- spmo: call tstcw ; see if speech enabled jp nz,sndno call sptod ; say "Today is" call halfsec spmo1: call rdtim ; read clock chip (if there) and ; save in memory ld a,(mmo) ; get the saved month call smom ; steal an available routine to speak 1 to 12 call halfsec ld a,(mdt) ; get the saved date cp 0ah ; under 10? jp c,smuni ; speak units of days (1 -> 9) cp 1ah ; under 20 days? jp c,spmo3 ; speak ELEVEN to NINETEEN and 0f0h ; 20, 30, 40 or 50 days? jp z,spmo4 ld a,(mdt) ; speak the tens of days and 0f0h ; look at upper nibble call smtn2 ld a,(mdt) ; speak the units of days and 0fh ; look at lower nibble jp smuni ; done spmo3: ld a,(mdt) and 0fh ; look at lower nibble jp smtn1 spmo4: ld a,(mdt) and 0f0h ; look at upper nibble jp smtn2 ;------------------------ end of file SPEECH.Z80 ----------------------------- subttl Control System page include control.z80 subttl Control System ;============================================================================ ; WA1LMV Repeater Control Code Emulator ;============================================================================ ; This routine emulates the control system of the old repeater ; using the sequences *2500 through *2599 as User Codes ; It also implememts an upper level system *6900 through *6999 ; for Control System codes codes: ld a,(clen) ; at least 4 chars needed cp 4 jp c,error call rech ; get character ld c,a ; save the char cp 'A' ; is it the silent command prefix? jp nz,codes1 ; (two *'s from DTMF or two A's from TTY?) ;----------------------------------------------------------------------------- ; Process User and Control Commands Silently ;----------------------------------------------------------------------------- call smode ; set silent mode call codes2 ; call CODES2 so we can come back call rmode ; restore the former MCW/Speech status ret ;----------------------------------------------------------------------------- codes1: ld a,(mudig1) ld b,a ld a,c ; get the original char back jp codes3 ; skip the RECH codes2: ld a,(mudig1) ld b,a call rech ; get character codes3: cp b ; is it user first unlock digit? jp z,ucode1 push af ld a,(mcdig1) ld b,a pop af cp b ; is it control first unlock digit? jp z,ccode1 jp error ucode1: ld a,(mudig2) ld b,a call rech ; get next character cp b ; is it the second unlock digit? jp nz,error ;----------------------- User Sub Command Dispatch Table --------------------- ld a,(uadflg) ; get the UAD flag or a jp nz,ucode2 ; bail out if UAD codes not enabled call sndno ; send NO ret ucode2: call rech ; get the next character call alta defb 10 ; ten commands in the table defb '0' defw unit0 ; process *nn00 through *nn09 defb '1' defw unit1 ; process *nn10 through *nn19 defb '2' defw unit2 ; process *nn20 through *nn29 defb '3' defw unit3 ; process *nn30 through *nn39 defb '4' defw unit4 ; process *nn40 through *nn49 defb '5' defw error ; process *nn50 through *nn59 defb '6' defw error ; process *nn60 through *nn69 defb '7' defw error ; process *nn70 through *nn79 defb '8' defw unit8 ; process *nn80 through *nn89 defb '9' defw unit9 ; process *nn90 through *nn99 ;----------------------------- Unit 00 Commands ---------------------------- unit0: call rech call alta defb 10 defb '0' defw ptchoff ; Autopatch OFF defb '1' defw ptchat ; Autopatch ON (automatic) defb '2' defw dialer ; Speed Dialer defb '3' defw spksd0 ; Speak Last Dialed Number defb '4' defw error defb '5' defw sndnuk ; Curly defb '6' defw stime ; Voice Time defb '7' defw mbeep ; super beep defb '8' defw sndid ; MCW ID defb '9' defw sndsid ; Voice ID ;----------------------------- Unit 10 Commands ---------------------------- unit1: call rech call alta defb 10 defb '0' defw a1rtd ; Aux RX/TX #1 Disable defb '1' defw a1rxe ; Aux RX #1 Enable defb '2' defw a1txe ; Aux TX #1 Enable defb '3' defw a1txd ; Aux TX #1 Disable defb '4' defw a1chan ; Aux Channel Set defb '5' defw spk2m ; Speak Two Meter Frequency defb '6' defw pgm2mu ; Set 2M Channel 0 Frequency defb '7' defw error defb '8' defw error defb '9' defw error ;----------------------------- Unit 20 Commands ---------------------------- unit2: call rech call alta defb 10 defb '0' defw a2rtd ; Aux RX/TX #2 Disable defb '1' defw a2rxe ; Aux RX #2 Enable defb '2' defw a2txe ; Aux TX $2 Enable defb '3' defw a2txd ; Aux TX #2 Disable defb '4' defw error defb '5' defw error defb '6' defw error defb '7' defw error defb '8' defw error defb '9' defw error ;----------------------------- Unit 30 Commands ---------------------------- unit3: call rech call alta defb 10 defb '0' defw utxld ; disable 450 TX activity limit defb '1' defw utxle ; enable 450 TX activity limit defb '2' defw error defb '3' defw error defb '4' defw chmof ; disable chime defb '5' defw chmon ; enable chime defb '6' defw spmo ; speak date defb '7' defw error defb '8' defw error defb '9' defw stnuk ; send time, ID and Curly routine ;----------------------------- Unit 40 Commands ---------------------------- unit4: call rech call alta defb 10 defb '0' defw error defb '1' defw ant1 ; antenna #1 defb '2' defw ant2 ; antenna #2 defb '3' defw error defb '4' defw error defb '5' defw error defb '6' defw error defb '7' defw error defb '8' defw error defb '9' defw error ;----------------------------- Unit 80 Commands ---------------------------- unit8: call rech call alta defb 10 defb '0' defw error defb '1' defw cwset ; CW/Speech Mode defb '2' defw error defb '3' defw vctset ; 6M Courtesy Tone Mode defb '4' defw uctset ; 450 Courtesy Tone Mode defb '5' defw error defb '6' defw error defb '7' defw error defb '8' defw error defb '9' defw error ;----------------------------- Unit 90 Commands ---------------------------- unit9: call rech call alta defb 10 defb '0' defw ptchoff ; full patch off defb '1' defw ptchon ; full patch on defb '2' defw error defb '3' defw error defb '4' defw error defb '5' defw error defb '6' defw llpd ; disable landline monitor mode (half patch) defb '7' defw llpm ; enable landline monitor mode (half patch) defb '8' defw llrst ; landline control reset defb '9' defw urst ; UAD Codes Master Reset ;------------------- Control Codes ----------------------------------------- ccode1: ld a,(mcdig2) ld b,a call rech ; get next character cp b ; second control unlock digit? jp nz,error ;------------------ Control Sub Command Dispatch Table --------------------- ccode2: call rech ; get the next character call alta defb 10 ; ten commands in the table defb '0' defw cnit0 ; process *nn00 through *nn09 defb '1' defw cnit1 ; process *nn10 through *nn19 defb '2' defw cnit2 ; process *nn20 through *nn29 defb '3' defw cnit3 ; process *nn30 through *nn39 defb '4' defw error ; process *nn40 through *nn49 defb '5' defw cnit5 ; process *nn50 through *nn59 defb '6' defw cnit6 ; process *nn60 through *nn69 defb '7' defw cnit7 ; process *nn70 through *nn79 defb '8' defw cnit8 ; process *nn80 through *nn89 defb '9' defw cnit9 ; process *nn90 through *nn99 ;---------------------- Control 00 Commands -------------------------------- cnit0: call rech call alta defb 10 defb '0' defw ptchdis ; Autopatch disable defb '1' defw ptchen ; Autopatch enable defb '2' defw pgmsd ; Program Speed Dialer defb '3' defw spksd ; Speak Speed Dialer Numbers defb '4' defw pgm2m ; Program 2M Channel Frequencies defb '5' defw error defb '6' defw error defb '7' defw error defb '8' defw error defb '9' defw error ;---------------------- Control 10 Commands -------------------------------- cnit1: call rech call alta defb 10 defb '0' defw error defb '1' defw sthrs ; set the clock time defb '2' defw stdat ; set the clock date defb '3' defw setsch ; program scheduled events defb '4' defw hsub ; subtract one hour (Standard Time) defb '5' defw hadd ; add one hour (Daylight Savings Time) defb '6' defw error defb '7' defw error defb '8' defw error defb '9' defw error ;---------------------- Control 20 Commands -------------------------------- cnit2: call rech call alta defb 10 defb '0' defw dplud ; 450 DTMF PL disable defb '1' defw dplue ; 450 DTMF PL enable defb '2' defw dplvd ; 6M DTMF PL disable defb '3' defw dplve ; 6M DTMF PL enable defb '4' defw dmud ; DTMF Mute disable defb '5' defw dmue ; DTMF Mute enable defb '6' defw error defb '7' defw error defb '8' defw error defb '9' defw error ;---------------------- Control 30 Commands -------------------------------- cnit3: call rech call alta defb 10 defb '0' defw memr ; memory read defb '1' defw memw ; memory write defb '2' defw tdevf ; Tone Deviation Test OFF defb '3' defw tdevn ; Tone Deviation Test ON defb '4' defw sdevf ; Speech Deviation Test OFF defb '5' defw sdevn ; Speech Deviation Test ON defb '6' defw error defb '7' defw error defb '8' defw error defb '9' defw error ;------------------------- Control 50 Commands ------------------------------ cnit5: call rech call alta defb 10 defb '0' defw macoff ; macro functions disabled defb '1' defw macon ; macro functions enabled defb '2' defw setmac ; program macro functions defb '3' defw uadd ; UAD Codes Disable defb '4' defw uade ; UAD Codes Enable defb '5' defw error defb '6' defw error defb '7' defw error defb '8' defw error defb '9' defw error ;------------------------- Conrrol 60 Commands ------------------------------ cnit6: call rech call alta defb 10 defb '0' defw error defb '1' defw phtime ; preset hang time defb '2' defw rgoff ; ring detect off defb '3' defw rgon ; ring detect on defb '4' defw error defb '5' defw error defb '6' defw error defb '7' defw error defb '8' defw error defb '9' defw error ;------------------------- Control 70 Commands ------------------------------ cnit7: call rech call alta defb 10 defb '0' defw vrxd ; 6M RX Disable defb '1' defw vrxe ; 6M RX Enable (with PL enabled) defb '2' defw vrpld ; 6M RX PL Disable defb '3' defw vpltof ; 6M PL Time-Out Inhibit Disable defb '4' defw vplton ; 6M PL Time-Out Inhibit Enable defb '5' defw vptod ; 6M PL Temp override Disable defb '6' defw vptoe ; 6M PL Temp override Enable defb '7' defw error defb '8' defw error defb '9' defw error ;--------------------- Control 80 Commands ---------------------------------- cnit8: call rech call alta defb 10 defb '0' defw urxd ; 450 RX Disable defb '1' defw urxe ; 450 RX Enable (with PL enabled) defb '2' defw urpld ; 450 RX PL Disable defb '3' defw upltof ; 450 PL Time-Out Inhibit Disable defb '4' defw uplton ; 450 PL Time-Out Inhibit Disable defb '5' defw uptod ; 450 Temp PL override Disable defb '6' defw uptoe ; 450 Temp PL override Enable defb '7' defw error defb '8' defw error defb '9' defw error ;---------------------- Control 90 Commands -------------------------------- cnit9: call rech call alta defb 10 defb '0' defw utxd ; 450 TX Disable defb '1' defw utxe ; 450 TX Enable defb '2' defw vtxd ; 6M TX Disable defb '3' defw vtxe ; 6M TX Enable defb '4' defw error defb '5' defw error defb '6' defw error defb '7' defw error defb '8' defw error defb '9' defw xreset ; Master Reset ;============================================================================ ; Control System ;============================================================================ ; Toggle Autopatch Enable patchc: ld a,(ptchc) ; read control byte or a jp z,ptchen ; was off, turn on ; was on, turn off (fall through ; Autopatch Disable ptchdis:call stat ; status line defb 'Autopatch',0 call prdis call spap call ssdis xor a ; reset control byte ld (ptchc),a ; save ret ; Autopatch Enable ptchen: ld a,0ffh ; set control byte ld (ptchc),a ; save call stat ; status line defb 'Autopatch',0 call prena call spap call ssena ret ; Toggle Autopatch ON/OFF patch: call smode call patcht jp rmode patcht: ld a,(ptchm) ; read status byte or a jp z,ptchon ; was off, turn on ; was on, turn off (fall through ; Autopatch OFF ptchoff: ld a,(llful) ; see if someone on landline control or a jp nz,ptchfq ; NZ = yes, dump patch quietly ld a,(ptchm) ; read status byte or a ; is patch on now? jp z,sndmno ptchf1: call ptchfq ; turn off call spap ; say "Autopatch" call sndoff ; say "off" call halfsec ld a,(clkp) ; clock chip present? (0ffh = not there) or a ret nz call sndson ; say "on" call halfsec call spmo1 ; speak the month/date call halfsec call spat ; say "at" call rdtim ; read time jp stimt ; say the time ; Autopatch OFF (quietly) ptchfq: call stat ; status line defb 'Autopatch OFF',0 ld a,(port7s) ; read status byte and not (ptchr+ptchg) ; disable bits ld (port7s),a ; save back xor a ld (ptchm),a ; clear patch on flag ld a,(llful) ; see if someone on landline control or a jp nz,tbeep2 ; signal for landline user and exit ret ; Autopatch ON ptchon: ld a,(ptchc) ; read control byte or a jp z,sndno ; send NO and return from there ld hl,0 ; clear possible answer hold time ld (anshld),hl call ptchoq ; turn patch off if it is on now call stat ; status line defb 'Autopatch ON',0 ld a,(llful) ; see if someone on landline control or a jp nz,ptchon2 ld a,0ffh ; block DTMF interrupts from ld (bdtmft),a ; telephone line decoder call spap ; say "Autopatch" call sndon ; say "ON" ld hl,(mdftel) ; preset patch timer ld (teltim),hl ; to default value ld a,(port4s) and not iclr ; drop possible landline hold relay ld (port4s),a ; just in case xor a ld (rgcnt),a ; clear ring counter ld (llfrt),a ; clear ring time-out flag ptchon1: ld a,(port7s) ; read status byte or ptchr+ptchg ; enable bits ld (port7s),a ; save back ld a,(port4s) and not ptmon ; disable monitor switch ld (port4s),a ; just in case ld a,0ffh ld (ptchm),a ; set patch on flag ret ptchon2: call tbeep2 jp ptchon1 ; Autopatch ON (Automatic) ptchat: ld a,(clen) ; Command String Length or a jp z,ptchon ; no trailing digits, just turn patch on ld hl,dial0 ; save number in dialer slot 0 push hl call pgmsd0 ; go and program slot 0 pop hl jp dialb ;----------------------------------------------------------------------------- ; Turn Patch off quietly -- used for turning patch on without ; having to turn it off first ptchoq: ld a,(ptchm) ; see if patch is on now or a ret z ; turn off if it is on call ptchfq ; turn patch off quietly call onesec ret ;----------------------------------------------------------------------------- ; Speed Dialer ;----------------------------------------------------------------------------- dialer: ld a,(llful) ; see if someone on landline control or a jp nz,sndno call ptchoq ; turn patch off if it is on now call dslot ; determine desired dialer slot dialb: ld a,(dmutc) ; get DTMF mute control byte or a ; 0FFH = enabled jp z,dialc ; 0 = disabled ld a,(port7c) and not ptchg ; mute the patch gate ld (port7c),a ld a,0ffh ; block DTMF interrupts from ld (bdtmft),a ; telephone line decoder dialc: ld a,(hl) ; get the first digit cp 0ffh ; is it 0ffh? jp z,nodial ; if the first digit is 0ffh, ; then the slot is empty push hl ; ptchon destroys HL call ptchon ; turn-on patch call onesec ; wait for dialtone call t440 ; set tone pitch call stat ; status line defb 'Dialing: ',0 pop hl dloop: ld a,(hl) ; get digit cp 0ffh ; end of entry? jp z,dloopx ; then done push af add 30h ; make ASCII call cout ; print on CRT pop af or a ; is it a zero? jp nz,dloop1 ld a,00001010b ; special case dloop1: and dgend ; data mask ld (port8),a ; send 4-bit digit to dialer port or dgenc ; raise the latch bit ld (port8),a ; send to dialer port ; The telco central office autodialer spec is 51 +-1 ms 50% duty cycle. ; I chose 60 ms here to be on the safe side. push af call tonon ; transpond tone ld a,60/10 ; 60 ms DTMF tone length call delay pop af and not dgenc ; drop latch bit ld (port8),a ; send to dialer port push af call tonoff ; transpond tone ld a,60/10 ; 60 ms interdigit delay call delay pop af inc hl ; point to next entry jp dloop dloopx: ld a,(port7c) or ptchg ; un-mute the patch gate ld (port7c),a ret nodial: xor a ; reset the MCW transpond flag ld (cwtf),a call stat ; status line defb 'Dialer slot not programmed',0 call sndmno ; send an MCW "no" jp dloopx ;----------------------------------------------------------------------------- ; Program Speed Dialer Slots ;----------------------------------------------------------------------------- pgmsd: call dslot ; set up the desired dialer slot pgmsd0: ld b,11 ; count up to 11 characters pgmsd1: call rech ; get next character cp cr ; end of line? jp z,pgmsdx call dchk ; convert to binary ld (hl),a ; save in the dialer slot ld a,b ; check max count or a jp z,pgmsde dec b inc hl ; next position in slot jp pgmsd1 ; go back for more characters pgmsdx: push hl call sndok ; send OK pop hl ld a,0ffh ; mark end of slot ld (hl),a ret pgmsde: ld a,0ffh ; mark end of slot ld (hl),a jp error ;----------------------------------------------------------------------------- ; Speak Numbers in Speed Dialer Slots ;----------------------------------------------------------------------------- spksd0: ld a,(cwena) ; see if MCW/Speech Disabled or a jp z,sndno ld a,0ffh ; set the MCW transpond flag ld (cwtf),a call t660 ld hl,dial0 ; point to slot jp spksd1 spksd: ld a,(cwena) ; see if MCW/Speech Disabled or a jp z,sndno ld a,0ffh ; set the MCW transpond flag ld (cwtf),a call t660 call dslot ; set-up the desired dialer slot spksd1: ld a,(hl) ; get the first digit cp 0ffh ; is it 0ffh? jp z,nodial ; if the first digit is 0ffh, ; then the slot is empty call stat ; status line defb 'Dialer: ',0 spksd2: ld a,(hl) ; get a digit cp 0ffh ; last one? jp z,spksdx push hl call nybl ; speak the digit pop hl inc hl ; next char jp spksd2 spksdx: xor a ld (cwtf),a ; reset the MCW transpond flag ret ;----------------------------------------------------------------------------- ; Subroutine - DSLOT Determine the desired dialer slot ;----------------------------------------------------------------------------- dslot: call rech ; get a character from the command line cp cr ; no char there? jp z,error push af call spspd ; speak "Dialer slot:" pop af push af call spkln ; speak the number of the slot pop af push af call halfsec pop af call dchk ; convert to binary ld hl,12 ; number of bytes per entry ld d,0 ld e,a ; get request into DE call mulhd ; multiply request by number of bytes ; per entry ld de,dial0 ; start of table to use add hl,de ; add offset into table ret ; HL points to desired dialer slot ;----------------- End of Subroutine DSLOT ----------------------------------- ;----------------------------------------------------------------------------- ; Macro Commands Control ;----------------------------------------------------------------------------- macoff: xor a ; Macro Commands OFF ld (mflag),a call macm call prdis jp sndcff macon: ld a,0ffh ; Macro Commands ON ld (mflag),a call macm call prena jp sndcn macm: call stat ; status line defb 'Macro Functions',0 ret ;----------------------------------------------------------------------------- ; Subroutine MACOD Process Macro Functions ;----------------------------------------------------------------------------- macod: ld a,(mflag) ; see if macro functions allowed or a jp z,sndno ld de,mac0 ; start of table to use ld hl,5 ; number of bytes per entry call rech ; get the char cp 'B' ; is it silent transpond char? jp z,macos ; yep, then silent call mslot1 ; determine macro slot, skip rech jp maco0 macos: ld a,0ffh ; set macro silent flag ld (macsil),a call mslot ; determine macro slot maco0: push hl ; save slot address ld hl,mbuf ; holding buffer for command tail maco1: call rech ld (hl),a ; save tail chars in buffer cp cr ; end of tail? jp z,maco2 ; then done inc hl jp maco1 maco2: ld a,(macsil) ; silent macro command? or a jp z,macoq ld a,'A' ; prefix silent command char call putbuf xor a ld (macsil),a ; reset macro silent flag macoq: pop hl ; get slot address back ; HL is pointing to desired macro function ; Copy the fucntion into the type-ahead buffer - IBUF ld b,5 ; number of bytes to move maco3: ld a,(hl) ; get the byte call putbuf ; save in the buffer inc hl dec b ; done? jp nz,maco3 ; loop until 5 chars added ld hl,mbuf ; now, append the command tail maco4: ld a,(hl) ; get the next tail char call putbuf ; save in the buffer cp cr ; end of line? ret z ; all done inc hl jp maco4 ; go back for more ;----------------------------------------------------------------------------- ; Subroutine SETMAC - Program Macro Functions ;----------------------------------------------------------------------------- setmac: ld de,mac0 ; start of table to use ld hl,5 ; number of bytes per entry call mslot ; set up desired macro slot ld b,5 ; count up to 5 chars setma1: call rech ; get next character cp cr ; end of line? jp z,sndok ; finished ld (hl),a ; save in the macro slot ld a,b ; check max count or a jp z,error ; too many chars dec b inc hl ; next position in slot jp setma1 ;----------------------------------------------------------------------------- ; Disable 450 RX PL (by enabling COS bit) ;----------------------------------------------------------------------------- urpld: call stat ; status line defb '450 Receiver PL',0 call prdis call sp450 call sprx call sp call sl call ssdis ld a,(port1c) ; read control byte and not urtos ; disable tos or urcos ; enable cos ld (port1c),a ; save back ret ; Disable 6M RX PL (by enabling COS bit) vrpld: call stat ; status line defb '6M Receiver PL',0 call prdis call sp6m call sprx call sp call sl call ssdis ld a,(port1c) ; read control byte and not vrtos ; disable tos or vrcos ; enable cos ld (port1c),a ; save back ret ; Disable 450 RX urxd: call stat ; status line defb '450 Receiver',0 call prdis call sp450 call sprx call ssdis ld a,(port1c) ; read control byte and not (urcos+urtos) ; disable bits ld (port1c),a ; save back ret ; Toggle 450 PL enable tupl: call smode call tuplt jp rmode tuplt: ld a,(port1c) ; read control byte and urcos ; control bit jp z,urpld ; COS was off, turn on ; COS was on, turn off (fall through) ; Enable 450 RX (with PL) urxe: ld a,(port1c) ; read control byte and not urcos ; disable cos or urtos ; enable tos ld (port1c),a ; save back call stat ; status line defb '450 Receiver (PL-ON)',0 call prena call sp450 call sprx call ssena ret ;----------------------------------------------------------------------------- ; Disable 6M PL Time-Out Inhibit vpltof: xor a ld (vpltf),a ; reset the 6M PL Time-Out Flag call vpltm ; print screen message call prdis call ssctl jp ssdis ; Enable 6M PL Time-Out Inhibit vplton: ld a,0ffh ld (vpltf),a ; set the 6M PL Time-Out Flag call vpltm ; print screen message call prena call ssctl jp ssena vpltm: call stat ; status line defb '6M PL Time-Out Inhibit',0 ret ;----------------------------------------------------------------------------- ; Disable 450 PL Time-Out Inhibit upltof: xor a ld (upltf),a ; reset the 450 PL Time-Out Flag call upltm ; print screen message call prdis call ssctl jp ssdis ; Enable 450 PL Time-Out Inhibit uplton: ld a,0ffh ld (upltf),a ; set the 450 PL Time-Out Flag call upltm ; print screen message call prena call ssctl jp ssena upltm: call stat ; status line defb '450 PL Time-Out Inhibit',0 ret ;----------------------------------------------------------------------------- ; Disable 6M RX vrxd: call stat ; status line defb '6M Receiver',0 call prdis call sp6m call sprx call ssdis ld a,(port1c) ; read control byte and not (vrcos+vrtos) ; disable bit ld (port1c),a ; save back ret ; Toggle 6M PL enable tvpl: call smode call tvplt jp rmode tvplt: ld a,(port1c) ; read control byte and vrcos ; control bit jp z,vrpld ; COS was off, turn on ; COS was on, turn off (fall through) ; Enable 6M RX (with PL) vrxe: ld a,(port1c) ; read control byte and not vrcos ; disable cos or vrtos ; enable tos ld (port1c),a ; save back call stat ; status line defb '6M Receiver (PL-ON)',0 call prena call sp6m call sprx call ssena ret ;----------------------------------------------------------------------------- ; Quiet/Verbose Command Response Control ; Save Mode smode: ld a,(cwena) ; save the current MCW/Speech mode ld (cwtmp),a xor a ; set mode 0 ld (cwena),a ret ; Restore Mode rmode: ld a,(cwtmp) ; restore the prev MCW/Speech mode ld (cwena),a ret ;----------------------------------------------------------------------------- ; Toggle 450 TX enable tutx: call smode call tutxt jp rmode tutxt: ld a,(port7c) ; read control byte and utx ; control bit jp z,utxe ; was off, turn on ; was on, turn off (fall through) ; Disable 450 TX utxd: call utxm ; print screen message call prdis call sp450 call sptx call ssdis ld a,(port7c) ; read control byte and not utx ; disable bit ld (port7c),a ; save back ret ; Enable 450 TX utxe: ld a,(port7c) ; read control byte or utx ; enable bit ld (port7c),a ; save back call utxm ; print screen message call prena call sp450 call sptx call ssena ret utxm: call stat ; status line defb '450 Transmitter',0 ret ;----------------------------------------------------------------------------- ; Toggle 6M TX enable tvtx: call smode call tvtxt jp rmode tvtxt: ld a,(port7c) ; read control byte and vtx ; control bit jp z,vtxe ; was off, turn on ; was on, turn off (fall through) ; Disable 6M TX vtxd: call vtxm ; print screen message call prdis call sp6m call sptx call ssdis ld a,(port7c) ; read control byte and not vtx ; disable bit ld (port7c),a ; save back ret ; Enable 6M TX vtxe: ld a,(port7c) ; read control byte or vtx ; enable bit ld (port7c),a ; save back call vtxm ; print screen message call prena call sp6m call sptx jp ssena vtxm: call stat ; status line defb '6M Transmitter',0 ret ;----------------------------------------------------------------------------- ; Disable Aux RX #1 a1rxd: ld a,(port1c) ; read control byte and not a1cos ; disable bit ld (port1c),a ; save back ret ; Enable Aux RX #1 a1rxe: call a1txd1 ; dump the transmitter if on ld a,(port1c) ; read control byte or a1cos ; enable bit ld (port1c),a ; save back call stat ; status line defb '2 Meter Receiver',0 call prena ld a,(cwena) ; get the MCW/Speech control byte cp 1 jp z,sndon1 call sp2m ; speak '2-Meter' jp sprx ; speak 'Receive' ; Disable Aux RX #2 a2rxd: ld a,(port1c) ; read control byte and not a2cos ; disable bit ld (port1c),a ; save back ret ; Enable Aux RX #2 a2rxe: call a2txd1 ; dump the transmitter if on ld a,(port1c) ; read control byte or a2cos ; enable bit ld (port1c),a ; save back call stat ; status line defb '10-Meter Receiver',0 call prena ld a,(cwena) ; get the MCW/Speech control byte cp 1 jp z,sndon1 call sp10m ; speak '10-meter' jp sprx ; speak 'Receive' ; Disable Aux TX #1 a1txd: call a1txm ; print screen message call prdis ld a,(cwena) ; get the MCW/Speech control byte cp 1 jp z,sndof1 call sp2m ; speak '2-meter' call sptx ; speak 'Transmit' jp sndsoff ; speak 'off' a1txd1: ld a,(port7c) ; read control byte and not a1tx ; disable bit ld (port7c),a ; save back ret ; Enable Aux TX #1 a1txe: ld a,(port1c) ; read control byte and a1cos ; see if receiver is enabled jp z,sndno ld a,(port7c) ; read control byte or a1tx ; enable bit ld (port7c),a ; save back ld hl,(mdfatt) ; preset Aux Transmit Time Limit ld (attim),hl call a1txm ; print screen message call prena ld a,(cwena) ; get the MCW/Speech control byte cp 1 jp z,sndon1 call sp2m ; speak '2-meter' jp sptx ; speak 'Transmit' a1txm: call stat ; status line defb '2-Meter Transmitter',0 ret ; Disable Aux TX #2 a2txd: call a2txm ; print screen message call prdis ld a,(cwena) ; get the MCW/Speech control byte cp 1 jp z,sndof1 call sp10m ; speak '10-Meter' call sptx ; speak 'Transmit' jp sndsoff ; speak 'off' a2txd1: ld a,(port7c) ; read control byte and not a2tx ; disable bit ld (port7c),a ; save back ret ; Enable Aux TX #2 a2txe: ld a,(port1c) ; read control byte and a2cos ; see if receiver is enabled jp z,sndno ld a,(port7c) ; read control byte or a2tx ; enable bit ld (port7c),a ; save back ld hl,(mdfatt) ; preset Aux Transmit Time Limit ld (attim),hl call a2txm ; print screen message call prena ld a,(cwena) ; get the MCW/Speech control byte cp 1 jp z,sndon1 call sp10m ; speak '10-Meter' jp sptx ; speak 'Transmit' a2txm: call stat ; status line defb '10-Meter Transmitter',0 ret ; Disable Both RX/TX #1 a1rtd: call a1rxd ; aux 1 RX disable call a1txd1 ; aux 1 TX disable call a1rtm ; print screen message call prdis ; print 'disabled' ld a,(cwena) ; get the MCW/Speech control byte cp 1 jp z,sndof1 call sp2m ; speak '2-meter call sprx ; speak 'receive' call sand ; speak 'and' call sptx ; speak 'transmit' jp sndsoff ; speak 'off' ; Disable Both RX/TX #2 a2rtd: call a2rxd ; aux 2 RX disable call a2txd1 ; aux 2 TX disable call a2rtm ; print screen message call prdis ; print 'disabled' ld a,(cwena) ; get the MCW/Speech control byte cp 1 jp z,sndof1 call sp10m ; speak '10-Meter' call sprx ; speak 'receive' call sand ; speak 'and' call sptx ; speak 'transmit' jp sndsoff ; speak 'off' a1rtm: call stat ; status line defb '2-Meter Receiver/Transmitter',0 ret a2rtm: call stat ; status line defb '10-Meter Receiver/Transmitter',0 ret ;----------------------------------------------------------------------------- ; Set Two Meter RX/TX Active Channel ;----------------------------------------------------------------------------- a1chan: call a1chm ; print screen message call rech ; get next character call cout ; echo to screen cp cr ; no char there jp z,error call dchk ; convert to binary jp sndok ; send OK to user a1chm: call stat defb '2-Meter set to Channel ',0 ret ;----------------------------------------------------------------------------- ; Speak Frequencies in Two Meter Channel Slots ;----------------------------------------------------------------------------- spk2m: ld a,(cwena) ; see if MCW/Speech Disabled or a jp z,sndno ld a,0ffh ; set the MCW transpond flag ld (cwtf),a call t660 ld de,twoc0 ; channel table start ld hl,9 ; 9 bytes per entry call rech ; get the channel character push af ; save the channel number call mslot1 ; set-up the desired channel slot pop af ; get the requested channel push af ; save back call cwl ; send in mcw call halfsec ; wait spk2m1: ld a,(hl) ; get the first digit cp 0ffh ; is it 0ffh? jp z,nofreq ; if the first digit is 0ffh, ; then the slot is empty call stat ; status line defb '2M Channel ',0 pop af call cout ; print the channel call vprint defb ': ',0 spk2m2: ld b,0 ; counter spk2m3: ld a,(hl) ; get a digit push bc call nybl ; speak the digit pop bc inc b ; bump count inc hl ; next digit ld a,b cp 7 ; speak only 7 digits (0 to 6) jp nz,spk2m3 ; loop back for more push hl ; save mode byte call halfsec ld a,' ' call cout ld a,(hl) sub 30h ; convert from ascii or a ; 0 = Simplex jp z,spk2m4 cp 2 ; 2 = Auto-Inverse mode jp z,spk2m5 ; The strings rptstr, sxstr, invstr, hpstr and lpstr ; are in the UCRT routine ld hl,rptstr push hl call pstr ; type "Repeat" pop hl call cw ; send "Repeat" in MCW jp spk2m5 spk2m4: ld hl,sxstr push hl call pstr ; type "Simplex" pop hl call cw ; send "Simplex" in MCW jp spk2m6 spk2m5: ld hl,invstr push hl call pstr ; type "Inverse" pop hl call cw ; send "Inverse" in MCW spk2m6: call halfsec pop hl inc hl ; get the power control byte ld a,(hl) sub 30h ; convert from ascii or a ; 0 = Low Power jp z,spk2m7 ld hl,hpstr push hl call pstr ; type "HP" pop hl call cw ; send "HP" in MCW jp spk2m8 spk2m7: ld hl,lpstr push hl call pstr ; type "LP" pop hl call cw ; send "LP" in MCW spk2m8: xor a ld (cwtf),a ; reset MCW transpond flag ret nofreq: xor a ; reset transpond flag ld (cwtf),a call stat defb 'Two Meter Channel not programmed.',0 jp sndmno ;----------------------------------------------------------------------------- ; Program Two Meter Channel Frequencies ;----------------------------------------------------------------------------- ; This entry point allows a user to change the frequency in chan zero pgm2mu: xor a ld (twoac),a ; set active channel to zero ld hl,twoc0 ; point to chan zero slot jp pgm2me ; ; This entry point allows a control operator to change any 2M chan freq. pgm2m: ld de,twoc0 ; start of table to use ld hl,9 ; number of bytes per entry call rech ; get the next char (chan #) push af ; save it call mslot1 ; set up desired channel slot pop af sub 30h ; convert from ascii ld (twoac),a ; set active channel pgm2me: ld b,6 ; count up to 6 incoming chars inc hl ; skip over the 1 inc hl ; skip over the 4 pgm2m1: call rech ; get next character ld c,a ; save it cp cr ; end of line? jp z,sndok ld a,b ; get the count cp 5 ; time to skip the decimal? jp nz,pgm2m2 inc hl ; skip over decimal point pgm2m2: ld a,c ; get the char back ld (hl),a ; save in memory ld a,b ; get the count or a jp z,error dec b ; bump down the count inc hl ; next digit in slot jp pgm2m1 ;----------------------------------------------------------------------------- ; 6M Courtesy Tone Mode Control vctset: call vctm ; print screen message call rech ; get the next character cp '2' ; mode 2 - each key-up jp z,vct1 cp '1' ; mode 1 - first key up jp z,vct1 cp '0' ; mode 0 - disabled jp nz,error vct1: call cout ; print the char on the screen sub 30H ; convert to binary ld (vctmod),a ; save the mode call sndok ret vctm: call stat ; status line defb '6M Courtesy Tone Mode ',0 ret ;---------------------------------------------------------------------------- ; 450 Courtesy Tone Mode Control uctset: call uctm ; print screen message call rech ; get the next character cp '2' ; mode 2 - each key-up jp z,uct1 cp '1' ; mode 1 - first key up jp z,uct1 cp '0' ; mode 0 - disabled jp nz,error uct1: call cout ; print the char on the screen sub 30H ; convert to binary ld (uctmod),a ; save the mode call sndok ret uctm: call stat ; status line defb '450 Courtesy Tone Mode ',0 ret ;----------------------------------------------------------------------------- ; Enable UAD functions uade: ld a,0ffh ld (uadflg),a call uadm ; print screen message call prena call ssusr jp ssena ; Disable UAD functions uadd: xor a ld (uadflg),a call uadm ; print screen message call prdis call ssusr jp ssdis uadm: call stat ; status line defb 'User Functions',0 ret ;----------------------------------------------------------------------------- cadm: call stat ; status line defb 'Control Functions',0 ret ;---------------------------------------------------------------------------- ; DTMF Mute Control dmue: ld a,0ffh ld (dmutc),a ; set the DTMF Mute enabled flag call dmum ; print screen message call prena jp sndcn dmud: xor a ld (dmutc),a ; reset the DTMF Mute enabled flag call dmum ; print screen message call prdis jp sndcff dmum: call stat ; status line defb 'DTMF Mute',0 ret ;----------------------------------------------------------------------------- ; DTMF PL Control 6M enable dplve: ld a,0ffh ld (dtplv),a call dplvm ; print screen message call prena jp sndcn ; DTMF PL Control 6M disable dplvd: xor a ld (dtplv),a call dplvm ; print screen message call prdis jp sndcff dplvm: call stat ; status line defb '6M DTMF PL',0 ret ;----------------------------------------------------------------------------- ; DTMF PL Control 450 enable dplue: ld a,0ffh ld (dtplu),a call dplum ; print screen message call prena jp sndcn ; DTMF PL Control 450 disable dplud: xor a ld (dtplu),a call dplum ; print screen message call prdis jp sndcff dplum: call stat ; status line defb '450 DTMF PL',0 ret ;----------------------------------------------------------------------------- ; Control Ring Detector rgon: ld a,(port1c) or ring ld (port1c),a call rngm ; print screen message call prena jp sndcn rgoff: ld a,(port1c) and not ring ld (port1c),a call rngm ; print screen message call prdis jp sndcff rngm: call stat ; status line defb 'Ring Detector',0 ret ;----------------------------------------------------------------------------- ; Chime Control chmt: ld a,(chena) ; get the chime enable byte or a jp nz,chmof ; if on (NZ) then turn on chmon: ld a,0ffh ld (chena),a ; turn on call chmm ; print screen message call prena call ssfn jp sndon chmof: xor a ld (chena),a ; turn off call chmm ; print screen message call prdis call ssfn jp sndoff chmm: call stat ; status line defb 'Hourly Chime',0 ret ant2: ld a,(port7c) ; get TX control byte ld b,a ; save for later and not (vtx+utx) ; disable main transmitters now ld (port7c),a call halfsec ; wait ld a,(port7s) ; switch to antenna #1 or antt ld (port7s),a ld a,b ; get previous control byte ld (port7c),a ; restore transmitters call halfsec ; wait call antm ; print screen message ld a,'2' call cout call prena call spant call s2 jp ssena ant1: ld a,(port7c) ; get TX control byte ld b,a ; save for later and not (vtx+utx) ; disable main transmitters now ld (port7c),a call halfsec ; wait ld a,(port7s) ; switch to antenna #1 and not antt ld (port7s),a ld a,b ; get previous control byte ld (port7c),a ; restore transmitters call halfsec ; wait call antm ; print screen message ld a,'1' call cout call prena call spant call s1 jp ssena antm: call stat ; status line defb 'Antenna #',0 ret ;----------------------------------------------------------------------------- ; UAD Codes Master Reset urst: call smode xor a ld (cwena),a ; disable MCW/Speech call ptchoff ; patch off call a1rtd ; Aux RX/TX #1 off call a2rtd ; Aux RX/TX #2 off call dmue ; DTMF Mute enable call llrst ; reset landline control call stat ; status line defb 'User Functions RESET',0 call rmode ; restore previous state call tstcw ; see if speech enabled jp nz,urst1 call ssusr ; say USER jp ssrst ; say RESET urst1: ld hl,rstmsg jp cw ; send "reset" prena: call vprint defb ' Enabled',0 ret prdis: call vprint defb ' Disabled',0 ret ;============================================================================ ; Set the time ;============================================================================ sthrs: call gethx ; get the hours cp 24h ; greater than 23 hours? jp nc,error ld (hrs),a ; save in clock chip ld (mhrs),a ; save in memory call gethx ; get the minutes cp 60h ; greater than 59 minutes? jp nc,error ld (min),a ; save in clock chip ld (mmin),a ; save in memory ld a,(clen) ; see if user entered seconds or a jp nz,sthr1 xor a ; zero out the seconds ld (sec),a ; save in clock chip ld (msec),a ; save in memory jp sthr2 sthr1: call gethx ; get the seconds cp 60h ; greater than 59 seconds? jp nc,error ld (sec),a ; save in clock chip ld (msec),a ; save in memory sthr2: call ucrte ; update the screen call stat ; status line defb 'Clock Time Set',0 jp sndok ; Subtract one hour from the time for return to ; Standard Time hsub: ld a,(clkp) ; get the clock present flag or a jp nz,nohs ; ffh = no clock ld a,(hrs) ; read the clock chip hours or a ; is it 00:xx? jp z,wraps ; Z = wrap to 23:xx cp 20h ; is it 8 PM? call z,subbcd ; adjust for packed BCD cp 10h ; is it 10 AM? call z,subbcd ; adjust for packed BCD sub 1 ; decrement hours ld (hrs),a ; save back into clock hexit: call sndok ; send OK call halfsec ld a,(cwena) ; check speech mode cp 2 ; speech enabled? call z,stime ; speak the time ret ; all done subbcd: sub 5 ; decrement from 20h to 19h ret ; or from 10h to 9h wraps: ld a,23h ; preset to 23:xx ld (hrs),a ; save back into clock jp hexit ; go and speak the time ; Clock Chip not there, do operations on time in memory nohs: ld a,(mhrs) ; read the hours in memory or a ; is it 00:xx? jp z,wrams ; Z = wrap to 23:xx cp 20h ; is it 8 PM? call z,subbcd ; adjust for packed BCD cp 10h ; is it 10 AM? call z,subbcd ; adjust for packed BCD sub 1 ; decrement hours ld (mhrs),a ; save back into memory jp hexit ; go and speak the time wrams: ld a,23h ; preset to 23:xx ld (mhrs),a ; save back into memory jp hexit ; go and speak the time ; Add one hour to the time for return to ; Daylight Savings Time hadd: ld a,(clkp) ; get the clock present flag or a jp nz,noha ; ffh = no clock ld a,(hrs) ; read the clock chip hours cp 23h ; is it 23:xx? jp z,wrapa ; Z = wrap to 00:xx cp 19h ; is it 7 PM? call z,addbcd ; adjust for packed BCD cp 9h ; is it 9 AM? call z,addbcd ; adjust for packed BCD add 1 ; increment hours ld (hrs),a ; save back into clock jp hexit ; go and speak the time addbcd: add 5 ; increment from 19h to 20h ret ; or from 9h to 10h wrapa: xor a ; preset to 00:xx ld (hrs),a ; save back into clock jp hexit ; go and speak the time ; Clock Chip not there, do operations on time in memory noha: ld a,(mhrs) ; read the hours in memory cp 23h ; is it 23:xx? jp z,wrama ; Z = wrap to 23:xx cp 19h ; is it 7 PM? call z,addbcd ; adjust for packed BCD cp 9h ; is it 9 AM? call z,addbcd ; adjust for packed BCD add 1 ; increment hours ld (mhrs),a ; save back into memory jp hexit ; go and speak the time wrama: xor a ; preset to 00:xx ld (mhrs),a ; save back into memory jp hexit ; go and speak the time ; Send the time, ID and Curly routine ; (mostly for Noon and Midnight chimes from the scheduler) stnuk: ld a,(chena) ; see if hourly chime enabled or a jp nz,sndnuk ; go right to curly routine call mbeep ; mega beep chime ld a,(cwena) ; check speech mode cp 2 ; speech enabled? call z,stime ; speak the time call halfsec call sndsid ; speak the ID call halfsec jp sndnuk ; do curly ;============================================================================ ; Set the date ;============================================================================ stdat: call gethx ; get two ascii chars and make hex cp 13h ; greater than December? jp nc,error ld (month),a ; save month in IC ld (mmo),a ; save month in memory call gethx cp 32h ; greater than 31? jp nc,error ld (date),a ; save date in IC ld (mdt),a ; save date in memory ld a,(clen) ; how many digits left? cp 2 ; full 4-digit year entered? jp z,stda2 ; Z = no, skip century entry call gethx ld (mdfcty),a ; save century stda2: call gethx ld (year),a ; save year in IC ld (myr),a ; save year in memory stda3: call ucrte ; update the screen call stat ; status line defb 'Clock Date Set',0 call sndok ret ;============================================================================= ; MCW/Speech Mode Control ;============================================================================= cwset: call rech ; get the next char cp '2' ; mode 2? jp z,enasp ; enable Speech/CW mode cp '1' ; mode 1? jp z,enacw ; enable CW-Only mode cp '0' ; mode 0? jp nz,error discw: xor a ; disable CW/Speech ld (cwena),a ; (does not disable ID) call stat ; status line defb 'Speech/MCW Disabled',0 call ssfn jp sndoff enacw: ld a,1 ; enable MCW Mode ld (cwena),a call stat ; status line defb 'MCW-only Mode Enabled',0 call ssfn jp sndon enasp: call chksp ; see if chip is there jp z,sndmno ; send NO (mode 1 was forced) ld a,2 ; enable Speech Mode ld (cwena),a call stat ; status line defb 'Speech Mode Enabled',0 call ssfn jp sndon ;============================================================================= ; Set Transmitter Hang Timer (This will key the transmitters) ;============================================================================= ihtim: ld a,(mdfit) ; preset ID PTT to default value ld (idptim),a jp htime lhtim: ld a,(mdflt) ; preset hang timer to default value ld (lhang),a ; for link transmitters htime: push hl ld hl,(mdfht) ; preset hang timer to default value ld (hang),hl ; for main transmitters pop hl ret ; Preset the hang time to five minutes to key the ; transmitters for testing phtime: call sndok call halfsec call sndid ; force ID now to reset ID timer call onesec ld hl,5*60*100 ; preset HL to five minutes ; (5 mins) * (60 sec/min) * 100 ticks/sec -- 10 ms per tick ld (hang),hl ; preset the hang timer call stat ; status line defb '** Transmitters Keyed! **',0 ret ;----------------------------------------------------------------------------- ; 6M Temporary Receiver PL Override ;----------------------------------------------------------------------------- vplo: ld a,(uadflg) ; get the UAD enable flag or a ret z ld a,(port1c) ; get the control byte and vrcos+vrtos ; see if receiver is enabled ret z ld a,(vplom) ; get the enable control byte or a ret z ; Z = Disabled ld a,0ffh ld (pltv),a ; set the 6M temp PL override flag ld hl,(mdftpl) ; get the default Temp PL time limit ld (tmppl),hl ; preset the time call vptom ; print screen message call vprint defb ' Active',0 ret ;----------------------------------------------------------------------------- ; 450 Temporary Receiver PL Override ;----------------------------------------------------------------------------- uplo: ld a,(uadflg) ; get the UAD enable flag or a ret z ld a,(port1c) ; get the control byte and urcos+urtos ; see if receiver is enabled ret z ld a,(uplom) ; get the enable control byte or a ret z ; Z = Disabled ld a,0ffh ld (pltu),a ; set the 450 temp PL override flag ld hl,(mdftpl) ; get the default Temp PL time limit ld (tmppl),hl ; preset the time call uptom ; print screen message call vprint defb ' Active',0 ret ;----------------------------------------------------------------------------- ; Force Reset 6M and 450 Temp PL Override ;----------------------------------------------------------------------------- tpld: ld hl,0 ld (tmppl),hl ; reset the timer xor a ; reset 6M and 450 temp PL override flags ld (pltv),a ld (pltu),a call stat ; print screen message defb 'Temp PL Override Reset',0 ret ;----------------------------------------------------------------------------- ; 6M Temporary Receiver PL Override Control ;----------------------------------------------------------------------------- vptod: xor a ld (vplom),a call vptom ; print screen message call prdis ; disabled jp sndcff vptoe: ld a,0ffh ld (vplom),a call vptom ; print screen message call prena ; enabled jp sndcn vptom: call stat ; status line defb '6M Temp PL Override',0 ret ;----------------------------------------------------------------------------- ; 450 Temporary Receiver PL Override Control ;----------------------------------------------------------------------------- uptod: xor a ld (uplom),a call uptom ; print screen message call prdis ; disabled jp sndcff uptoe: ld a,0ffh ld (uplom),a call uptom ; print screen message call prena ; enabled jp sndcn uptom: call stat ; status line defb '450 Temp PL Override',0 ret ;----------------------------------------------------------------------------- ; Memory Read with voice/MCW readout ;----------------------------------------------------------------------------- memr: jp iport1 ;----------------------------------------------------------------------------- ; Memory Write with voice/MCW readout ;----------------------------------------------------------------------------- memw: call readhl ; read the port or address push hl ; save push hl call readhl ; read the data ld a,l pop hl ld (hl),a ld a,0ffh ld (cwtf),a ; set the MCW transpond flag call t660 ; 660 Hz. tone pitch call clstat call gxymsg defb 24,1 defb 'Address/Memory: ',0 pop hl ; get the address back call tyhl call sngl call halfsec ; put space in case of speech ld a,(hl) ; get the byte ld l,a call byte call sngl jp bits ret ; ---------------------------------------------------------------------------- ; Control 450 TX Transmit Time Limit ;----------------------------------------------------------------------------- utxld: xor a ld (limuhf),a call utlm ; print screen message call prdis ; disabled jp sndcff utxle: ld a,0ffh ld (limuhf),a call utlm ; print screen message call prena ; enabled jp sndcn utlm: call stat ; status line defb '450 TX Activity Limit ',0 ret ;----------------------------------------------------------------------------- ; Tone Deviation Test ;----------------------------------------------------------------------------- ; Toggle Test Tone tdev: ld a,(port4s) ; read status byte and mcwt ; device bit jp z,tdevn ; was off, turn on ; was on, turn off (fall through) ; Turn-Off Test Tone tdevf: ld a,(port4s) ; read the status byte and not(mcwt) ; drop the device bit ld (port4s),a ; save back ld hl,0 ld (hang),hl ; unkey the transmitters call stat defb 'Test Tone OFF',0 ret ; Turn-On Test Tone tdevn: ld a,(port7s) ; see if landline monitor or and ptchr ; autopatch is active jp nz,sndno ; (patch relay is on for both) ld hl,(mdfcwt) ; set to default MCW pitch call tone ld a,(port4s) ; read the status byte or mcwt ; set device bit ld (port4s),a ; save back ld hl,5*60*100 ; preset HL to 5 minutes ld (hang),hl ; key transmitters call stat defb '** Test Tone + Transmit! **',0 ret ;----------------------------------------------------------------------------- ; Speech Deviation Test ;----------------------------------------------------------------------------- ; Toggle Test Speech sdev: ld a,(sdevm) ; read status byte or a jp z,sdevn ; was off, turn on ; was on, turn off (fall through) ; Turn-Off Test Speech sdevf: call tstcw ; see if speech allowed jp nz,sndno xor a ; drop the status byte ld (sdevm),a ; save back ld (durphon),a ; turn off speech chip call stat defb 'Test Speech OFF',0 call halfsec call sndcff ; this will also unkey the TX ret ; Turn-On Test Speech sdevn: call tstcw ; see if speech allowed jp nz,sndno ld a,(port7s) ; see if landline monitor or and ptchr ; autopatch is active jp nz,sndno ; (patch relay is on for both) ld a,0ffh ; set status byte ld (sdevm),a ; save back call halfsec call stat defb '** Test Speech + Transmit! **',0 call sndcn ; speak something to preset registers ld hl,5*60*100 ; preset HL to 5 minutes ld (hang),hl ; key transmitters call halfsec ld a,0eh ; say "Ahhhh" ld (durphon),a ret ; ------------------------ end of file CONTROL.Z80 --------------------------- subttl page ;============================================================================ ; Input a line from the Console and put it ; into the buffer. Carriage return ends the ; line. Rubout or CTRL H corrects last ; entry. ;============================================================================ inclr: call prompt ld a,0ffh ; set EOL flag ld (eol),a incl: push hl push bc ld hl,cbuf ; buffer address ld (cptr),hl ; save pointer ld c,0 ; count inpli: call cin ; get char or wait push af xor a ; reset EOL flag ld (eol),a pop af cp ctrh ; backspace? jp z,inplb cp del ; delete? jp z,inplb cp cr ; end of input? jp z,inplc cp 'a' ; if less than lower case 'a' jp c,inpl3 ; then already upper case cp 'z'+1 ; if greater than lower case 'z' jp nc,inpl3 ; then not a lower case letter and 5fh ; make upper inpl3: ld (hl),a ; into buffer ld a,cblen-1 ; buffer size cp c ; full? jp z,inplf ld a,(hl) ; get char inc hl ; increment pointer inc c ; and count inple: call cout ; print char jp inpli ; next char inplf: ld a,bell ; buffer is full, call cout ; ring the bell jp inpli ; End of input line inplc: ld a,c ; count ld (clen),a ; save or a pop bc pop hl ret ; Delete prior character if any inplb: ld a,c ; char count or a ; zero? jp z,inpli ; yes dec hl ; back pointer dec c ; and count call vprint ; send BS,SPACE,BS chars defb backup,' ',backup,0 jp inpli prompt: call gxymsg defb 22,1 defb 15,'Ready >' defb ' ',0 call at defb 22,9 call curon ; turn-on cursor ret ; Input HL from console readhl: push de push bc ; Save registers ld hl,0 ; clear rdhl2: call rech ; get character cp cr jp z,rdhl5 ; line feed call nib ; to binary jp c,rdhl4 ; not hex add hl,hl ; times 2 add hl,hl ; times 4 add hl,hl ; times 8 add hl,hl ; times 16 or l ; add new character ld l,a jp rdhl2 ; next ; Check for blank at end rdhl4: cp apos ; apostrophe jp z,rdhl5 ; ASCII input cp (' '-'0') and 0ffh jp nz,error ; no rdhl5: pop bc pop de ; restore registers ret ; Convert ASCII characters to Binary nib: sub '0' ; ASCII bias ret c ; <0 cp 'F'-'0'+1 ccf ; invert ret c ; error, >F cp 10 ccf ; invert ret nc ; number 0-9 sub 'A'-'9'-1 cp 10 ; skip to ret ; letter A-F ; Start new line, give address crhl: call stat ; status line jp tyhl ; Input from any port or memory address iport1: ld a,0ffh ld (cwtf),a ; set the MCW Transpond Flag call t660 ; 660 Hz MCW Pitch iport: call stat ; status line defb 'Address/Memory: ',0 call readhl ; port or address call tyhl call sngl call halfsec ld a,(hl) ; get the byte ld l,a call byte call sngl ; Print L register in binary (8080 Version) bits: ld b,8 ; 8 bits bit2: ld a,l add a,a ; shift left ld l,a ld a,'0'/2 ; half of zero adc a,a ; double + carry call cout ; print the bit dec b jp nz,bit2 ; 8 times xor a ld (cwtf),a ; reset the MCW Transpond Flag ret ; Output Byte to Port or Memory ; Format is: O,PORT or MEMORY,BYTE oport: call readhl ; port or address push hl ; save call readhl ; data ld a,l pop hl ld (hl),a ret ; Type one or two spaces. dubl: call sngl sngl: ld a,' ' jp cout ; Fetch a character into A from command line rech: push hl ld hl,clen ; Command string length ld a,(hl) or a ld a,cr ; Fake CR from empty buffer jp z,recx dec (hl) ld hl,(cptr) ; Pointer to command buffer ld a,(hl) inc hl ld (cptr),hl ; Pointer to command buffer recx: pop hl ret ; Type A as two nibbles word: ld a,d call byte ld a,e byte: push bc push af rra rra rra rra call nybl pop af pop bc nybl: cp '.' ; is it a decimal point? jp z,nybld and 0fh add a,90h daa adc a,40h daa nybld: call cout ; A to console ld b,a ; save the character ld a,(cwtf) ; MCW Transpond flag set? or a ret z ld a,(cwena) ; MCW and Speech Disabled? or a ret z ; Mode 0 is both disabled cp 2 ; speech enabled? (Mode 2) jp z,nybl1 call tsttx ; tey transmitters ld a,(mdfwpm) ; get the existing MCW speed ld c,a ; save it ld a,90 ; slow it down ld (mdfwpm),a ld a,b ; get the char back call cwl ; send it in MCW ld a,16 call delay ; wait ld a,c ; get the old speed back ld (mdfwpm),a ; restore it ret nybl1: push de push bc call tsttx ; key transmitters ld a,b ; get the char back call spkln ; speak it ld a,50 ; inter-digit delay call delay pop bc pop de ret ; Type hl as four nibbles tyhl: ex de,hl call word ex de,hl ret ;----------------------------------------------------------------------------- ; AT - Position Cursor at coordinates specified directly after the CALL ;----------------------------------------------------------------------------- ; Format: CALL AT ; DEFB rr,cc ; ; where: rr - is the decimal row coordinate ; cc - is the decimal column coordinate at: ex (sp),hl ; save HL, get HL = coordinates call at1 ex (sp),hl ; restore hl and stack past the message ret ;-------- AT1 is a subroutine because it is also called by GXYMSG ------------ at1: ld a,esc ; first, send ESC Y call cout ld a,'Y' call cout ld a,(hl) ; get row add a,31 ; add offset call cout ; send inc hl ld a,(hl) ; get column add a,31 ; add offset call cout ; send inc hl ; point to the next byte ret ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; GXYMSG - Direct Cursor Positioning and print text string ;----------------------------------------------------------------------------- ; Format: CALL GXYMSG ; DEFB rr,cc ; DEFB 2,'text'1,0 ; ; where: rr - is the decimal row coordinate ; cc - is the decimal column coordinate ; where: 1 = dim video command ; 2 = bright video command ; 'text' is any ASCII text delimited by quotes ; and terminated with a trailing zero gxymsg: ex (sp),hl ; Save HL, get HL = coordinates call at1 gxym1: call pstr ex (sp),hl ; restore hl and stack past the message ret ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; VPRINT - Inline Print Routine ;----------------------------------------------------------------------------- ; Format: CALL vprint ; DEFB 1,'text',2,0 ; ; where: 1 = dim video command ; 2 = bright video command ; 'text' is any ASCII text delimited by quotes ; and terminated with a trailing zero vprint: ex (sp),hl call pstr ex (sp),hl ; restore hl and stack past the message ret ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; PSTR - Print the String pointed to by HL ;----------------------------------------------------------------------------- ; Format: LD HL,MSG ; CALL PSTR ; ..................... ; MSG: DEFB 1,'text',2,0 ; ; where: 1 = dim video command ; 2 = bright video command ; 'text' is any ASCII text delimited by quotes ; and terminated with a trailing zero pstr: ld a,(hl) ; get the character inc hl ; point to next one or a ; zero? (end of string) ret z ; yes, return cp 2 ; bright? jp z,pstb cp 1 ; dim? jp z,pstd call cout ; send the character jp pstr ; go back for more pstb: call bright ; process bright or normal video command jp pstr pstd: call dim ; process dim or reverse video command jp pstr ;----------------------------------------------------------------------------- ; Bright or Normal Video Routine ;----------------------------------------------------------------------------- bright: push hl ld hl,bristr ; point to bright or normal video string brigh1: ld a,(hl) ; get the character or a jp z,brigh2 ; zero is end of string call cout ; send the char inc hl ; point to next one jp brigh1 ; loop back brigh2: pop hl ret ;----------------------------------------------------------------------------- ; Dim or Reverse Video Routine ;----------------------------------------------------------------------------- dim: push hl ld hl,dimstr ; point to the dim or reverse video string jp brigh1 ; re-use above code ;----------------------------------------------------------------------------- ; Cursor ON Routine ;----------------------------------------------------------------------------- curon: push hl ld hl,constr ; point to cursor on string jp brigh1 ; re-use above code ;----------------------------------------------------------------------------- ; Cursor OFF Routine ;----------------------------------------------------------------------------- curoff: push hl ld hl,cofstr ; point to cursor off string jp brigh1 ; re-use above code ;----------------------------------------------------------------------------- ; Clear Screen Routine ;----------------------------------------------------------------------------- cls: push hl ld hl,clsstr ; point to clear screen string jp brigh1 ; re-use above code ;----------------------------------------------------------------------------- ; Initialize Terminal Routine ;----------------------------------------------------------------------------- tinit: push hl ld hl,inistr ; point to init terminal string jp brigh1 ; re-use above code ;----------------------------------------------------------------------------- ; Enter Graphics Mode ;----------------------------------------------------------------------------- gron: push af if a2020 ld a,esc call cout ld a,'H' call cout ld a,2 call cout endif ; a2020 if heath ld a,esc call cout ld a,'F' call cout endif ; heath pop af ret ;----------------------------------------------------------------------------- ; Exit Graphics Mode ;----------------------------------------------------------------------------- groff: push af if a2020 ld a,esc call cout ld a,'H' call cout ld a,3 call cout endif ; a2020 if heath ld a,esc call cout ld a,'G' call cout endif ; heath pop af ret ; -- END Subroutines AT, GXYMSG, VPRINT, PSTR, BRIGHT, DIM, CURON, CUROFF --- ;----------------------------------------------------------------------------- subttl ** Subroutines ** page include rptsubs.z80 ; File of subroutines for WA1LMV Controller ;----------------------------------------------------------------------------- ; GETHX - Read two ASCII characters from the command line ; and convert to binary ;----------------------------------------------------------------------------- gethx: call rech ; get the next command line digit call nib ; convert to binary jp c,error ; not hex rlc a rlc a rlc a rlc a ld b,a ; save call rech call nib jp c,error ; not hex or a,b ret ;----------------------------------------------------------------------------- ; Subroutine MSLOT - Determine Memory Slot ;----------------------------------------------------------------------------- ; Entry - DE points to start of the table to use ; HL = number of bytes per entry ; Exit - HL points to desired memory slot mslot: call rech ; get next char mslot1: cp cr ; no char there? jp z,error call dchk ; test value push de ld d,0 ; HL = number of bytes per entry ld e,a ; get request into DE call mulhd ; multiply request by number of bytes ; per entry pop de ; point to table to use add hl,de ; add offset into table ret ; HL is pointing to desired memory slot ;----------------------------------------------------------------------------- ; Subroutine DCHK Convert character to binary and only allow 0 to 9 ;----------------------------------------------------------------------------- dchk: call nib ; convert to binary jp c,error ; not hex cp 0ah ; greater than 9? jp nc,error ; only 0 to 9 allowed ret ;---------------------------------------------------------------------------- ; Library: ZSLIB ; Version: 3.0 ; Module: BCD2JUL ; Version: 1.1 ; Author: Gene Pizzetta ; Date: July 9, 1991 ; Changes: Was destroying BCD date in buffer, an undocumented feature. ; Now uses a scratch buffer. ; ; Version: 1.0 ; Author: Bridger Mitchell, Howard Goldstein ; Date: April 16, 1988 ; ; BCD2JUL -- BCD to Julian date routine. ; ; Entry: HL = address of date string in BCD yy mm dd ; Exit: HL = Julian date (1/1/78 = 1) ; Uses: HL ; Notes: Covers from January 1, 1978 to December 31, 2077. If year is ; greater than 78, this routine wraps to the next century. ; ; BIN2JUL -- Binary to Julian date routine. ; ; Entry: HL = address of date string in binary yy mm dd ; Exit: HL = Julian date (1/1/78 = 1) ; Uses: HL ; Notes: Covers from January 1, 1978 to December 31, 2077. If year is ; greater than 78, this routine wraps to the next century. ; ; PUBLIC BCD2JUL ; PUBLIC BIN2JUL ; EXTRN JBCD2BN,DPERMO ; ZSLIB ; BCD to Julian date BCD2JUL: push af push bc push de ld de,tmpbuf ; DE -> temporary buffer push de ; save buffer address ld b,3 ; convert BCD yy mm dd to binary BINLP: ld a,(hl) ; at HL... call JBCD2BN ld (de),a inc hl inc de dec b jp nz,BINLP pop hl ; recover buffer address in HL pop de pop bc pop af ; fall thru... ; Binary to Julian date BIN2JUL: push af push bc push de ld a,(hl) ; A = year inc hl push af ld a,(hl) ld c,a pop af inc hl push hl ; save pointer to day push af ; save year ; Set HL = initial Julian value of 12/31/77 ld hl,0 sub 78 jp z,B2JUL3 jp nc,B2JUL0 add a,100 ; greater than 78, assume next century B2JUL0: ld b,a ; B = number of years greater than 78 ld a,1 ; init modulo 4 counter ld de,365 ; days/year B2JUL1: add hl,de ; calc Julian value of (1/1/year - 1) inc a and 3 ; every 4 years, jp nz,B2JUL2 inc hl ; ..add 1 for leap year B2JUL2: dec b jp nz,B2JUL1 ; HL now = number of days in years before current year B2JUL3: pop af and 3 ; if current year == leap year jp nz,B2JUL5 ld a,c cp 3 ; ..and month >= March jp c,B2JUL5 inc hl ; ..add the extra day (Feb 29) B2JUL5: ld b,c ; B = month = number of months + 1 to sum ld de,DPERMO ; point at table jp B2JUL7 B2JUL6: call ADDHL ; add number of days in this month inc de ; bump table pointer B2JUL7: dec b jp nz,B2JUL6 pop de ; pointer to day call ADDHL pop de pop bc pop af ret ADDHL: ld a,(de) ; add day of current month ADDA2HL:add l ld l,a ret nc inc h ret JBCD2BN: push de ld e,a ; save original byte and 0fh ld d,a ; lower nibble ld a,e and 0f0h ; mask LSN rrca ; x2 ld e,a rrca rrca ; x4 add a,e ; x8 add a,d ; x10 pop de ret DPERMO: db 31 ; jan db 28 ; feb db 31 ; mar db 30 ; apr db 31 ; may db 30 ; jun db 31 ; jul db 31 ; aug db 30 ; sep db 31 ; oct db 30 ; nov db 31 ; dec ;----------------------------------------------------------------------------- ; MOVEIT - Move a block of memory from one location to another ; ; Entry: BC = number of bytes to move ; HL = Source Address ; DE = Destination Address ;----------------------------------------------------------------------------- moveit: ld a,(hl) ; get the source byte ld (de),a ; put in destination location inc hl ; increment source pointer inc de ; increment destination pointer dec bc ; decrement byte counter ld a,b ; test for zero in A because or a,c ; dec bc does not affect flags jp nz,moveit ; loop back if more bytes left to copy ret ;----------------------------------------------------------------------------- ; PADC -- Print A as two decimal characters ;----------------------------------------------------------------------------- padc: push bc ; save registers push af ; ; Print Routine padc1: ld b,10 ; print tens call pac add '0' ; convert to ASCII call cout ; print pop af ; restore A pop bc ; restore registers ret ; Print result of division of A by B w/leading space (intiger division) pac: ld c,0 ; set count pacl: sub b ; compute count jp c,pacd inc c ; increment count jp pacl pacd: add a,b ; add B back in ld e,a ; save A pacd1: ld a,c ; get count add '0' ; convert to decimal call cout ; print it ld a,e ; restore A ret ;---------------------------------------------------------------------------- ; SUBHD -- Subtract DE from HL, result in HL ; Return with HL=result, CARRY set if HL DE ld a,h cp d ; H > D? jp c,dovfl ; zero result if H < D jp nz,dnovfl ld a,l cp e ; L > E? jp c,dovfl ; zero result if HL < DE dnovfl: ld b,16 ; 16 loops dvhd: call shftlh ; shift divident left push hl ; save dividend ld hl,(acc) ; get acc call shflch ; rotate acc and move in carry ld (acc),hl ; new acc ld a,l ; low comparison sub e ; compare and subtract ld l,a ld a,h ; high comparison sbc a,d ; compare and subtract ld h,a jp c,dvhd0 ld (acc),hl ; save new acc pop hl ; get dividend ld a,l ; place in A 1 to quotient or 1 ld l,a jp dvhd1 dvhd0: pop hl ; get dividend and leave lsb at zero dvhd1: dec b ; count down jp nz,dvhd dvret: pop bc pop af ret dovfl: ld hl,0 ; result is zero jp dvret ; Shift Routines shftlh: ; shift HL left push af and a ; clear carry shfl: ld a,l ; shift low rla ; rotate 9-bit acc left ld l,a ld a,h ; shift high rla ld h,a jp nc,okret pop af scf ; set carry for overflow ret okret: pop af or a ; clear carry for no overflow ret shflch: ; shift HL left, but shift in carry flag push af jp shfl ; ---------------------------------------------------------------------------- ; Subroutine TSTTX - Key Main Transmitters. Wait for them ; to come on. Keep them keyed if already on. ; ---------------------------------------------------------------------------- tsttx: ld a,(port7s) ; get current status of transmitters and utx+vtx call z,tsttx1 ; if not on, wait for them to come up jp htime ; keep them on tsttx1: call htime jp onesec ; wait ;----------------------------------------------------------------------------- ; Check for existance of the SSI-263 Speech Chip ;----------------------------------------------------------------------------- ; Entry: none ; Exit: Flag - NZ = speech chip present and ready ; Z = speech chip not ready or not there ; also forces CW/Speech mode 1 ; Uses: A chksp: call halfsec ; should be stable ld a,(port0) and spreq ; look at request bit ret nz ; chip there and ready ld a,1 ; force MCW mode 1 ld (cwena),a ret ;---------------------- end of file RPTSUBS.Z80 ------------------------------ if $ gt 7fffh Program is greater than 32K! endif psiz macro plen .printx plen endm .radix 16 .printx .printx The last program address in hex is --> psiz %$ .printx .printx .radix 10 .printx The size in 128 byte records is --> psiz %(($/128)+1) .printx eject include memory.z80 subttl RAM Storage Locations ;============================================================================ ; System RAM storage definitions ;============================================================================ org rambase ;---------------------------------------------------------------------------- ; Warning! ibuf is a circular buffer which must start at an even ; page boundary. Only one byte is used to index into the buffer. ; The buffer size can be changed by varying IBLEN up to 256 but ; it will be of no value unless CBLEN is also increased. iblen equ 32 ibuf: defs iblen ; set up 32 byte character buffer ; ************************* DO NOT MOVE IBUF! **************************** ;---------------------------------------------------------------------------- iptr: defs 1 ; interrupt driven input pointer to ibuf optr: defs 1 ; CIN driven output pointer to ibuf cblen equ 32 cbuf: defs cblen cptr: defs 2 ; Pointer to cbuf clen: defs 1 ; Command string length port0s: defs 1 ; I/O Port status bytes port1s: defs 1 port2s: defs 1 port4s: defs 1 port5s: defs 1 port6s: defs 1 port7s: defs 1 intcnt: defs 1 ; interrupt cycle counter idtim: defs 2 ; ID timer idspd: defs 1 ; ID dot length timer (speed) trate: defs 2 ; PIT tone rate counter value crt: defs 1 ; status refresh time eol: defs 1 ; end-of-line flag (monitor loop idle) vrtim: defs 2 ; 6M RX time-out timer urtim: defs 2 ; 450 RX time-out timer acf: defs 1 ; Aux R1 cos flag bcf: defs 1 ; Aux R2 cos flag acc: defs 2 ; temp accumulator (mulhd, divhd routines) ovfl: defs 1 ; overflow flag (mulhd, divhd routines) vadly: defs 1 ; 6M Access Delay vrdly: defs 1 ; 6M Release Delay vgdly: defs 1 ; 6M audio Access Delay uadly: defs 1 ; 450 Access Delay urdly: defs 1 ; 450 Release Delay ugdly: defs 1 ; 450 audio Access Delay aadly: defs 1 ; Aux R1 Access Delay ardly: defs 1 ; Aux R1 Release Delay badly: defs 1 ; Aux R2 Access Delay brdly: defs 1 ; Aux R2 Release Delay vdcos: defs 1 ; 6M Delayed COS udcos: defs 1 ; 450 Delayed COS adcos: defs 1 ; Aux R1 Delayed COS bdcos: defs 1 ; Aux R2 Delayed COS pltv: defs 1 ; 6M temp PL override flag pltu: defs 1 ; 450 temp PL override flag tmppl: defs 2 ; temp PL override Timer gpt: defs 1 ; General Purpose Timer cwptt: defs 1 ; CW PTT flag teltim: defs 2 ; Patch timer ptchm: defs 1 ; Autopatch Control flag hang: defs 2 ; Transmitter Hang Timer rmute: defs 1 ; Radio DTMF Mute timer tmute: defs 1 ; Telephone DTMF Mute timer digitr: defs 1 ; last Radio DTMF digit memory digitp: defs 1 ; last Phone DTMF digit memory dtmfn: defs 1 ; DTMF Decoder select byte bdtmfr: defs 1 ; Radio DTMF interrupt block control bdtmft: defs 1 ; Telephone DTMF interrupt block control rdvdly: defs 1 ; Radio DTMF Data Valid Delay dnulm: defs 2 ; DTMF Pass-Through Delay atime: defs 1 ; Control time-out timer crflag: defs 1 ; CR Flag bidflg: defs 1 ; Broadcast ID flag cwtf: defs 1 ; CW Transpond flag alpha: defs 1 ; DTMF Alpha character flag lhang: defs 1 ; Link TX Hang Time xon: defs 1 ; X-ON/X-OFF wait status tickt: defs 1 ; Watchdog Tick time out time tickm: defs 1 ; Watchdog state toggle sflag: defs 1 ; star flag (control sequence pending) pflag: defs 1 ; pound flag (macro sequence pending) mampm: defs 1 ; AM/PM indicator idptim: defs 1 ; ID PTT Hang Timer rgdlya: defs 1 ; ring detect access delay timer rgdlyr: defs 1 ; ring detect release delay timer rgcnt: defs 1 ; ring count rgird: defs 2 ; inter-ring delay ansacc: defs 2 ; answer access time anshld: defs 2 ; answer hold time maxll: defs 2 ; maximum landline time llfrg: defs 1 ; ring flag llfan: defs 1 ; answer time out flag llful: defs 1 ; unlock flag llfhl: defs 1 ; hold time out flag llfrt: defs 1 ; ring time out flag clkp: defs 1 ; clock present flag timstr equ $ myr: defs 1 ; year storage mmo: defs 1 ; month storage mdt: defs 1 ; date storage mhrs: defs 1 ; hours storage mmin: defs 1 ; minutes storage msec: defs 1 ; seconds storage st10: defs 1 ; tens of milliseconds storage mda: defs 1 ; day of the week mahrs: defs 1 ; alarm hours storage mamin: defs 1 ; alarm minutes storage cinti: defs 1 ; clock/calendar interrupt status pending cwtmp: defs 1 ; Temporary storage for CWENA attim: defs 2 ; Aux TX time Limit chdon: defs 1 ; chime done flag tmpbuf: defs 3 ; julian date conversion buffer eudon: defs 1 ; event update done flag utxlim: defs 2 ; 450 TX usage limit time unact: defs 2 ; inactivity timer dsrflg: defs 1 ; DSR flag cttflg: defs 1 ; aux courtesy tone flag cttflv: defs 1 ; 6M courtesy tone flag cttflu: defs 1 ; 450 courtesy tone flag sdevm: defs 1 ; Speech Deviation Test control flag macsil: defs 1 ; Silent Macro Command flag org 08200h ; move to next page boundary ; This is the table of Foreground Task Flags. It must be in exactly ; the same order as the Task Address Table in the Foreground ; routine of the Master Loop. The order determines priority. fgtf equ $ ; Foreground Task Flag Table fberm: defs 1 ; Send BEER message 1 fvtom: defs 1 ; 6M Time-Out Alarm 2 futom: defs 1 ; 450 Time-Out Alarm 3 fidtm: defs 1 ; ID Timed-Out 4 fvctm: defs 1 ; 6M Courtesy Tone Request 5 fuctm: defs 1 ; 450 Courtesy Tone Request 6 fpctm: defs 1 ; Landline Courtesy Tone 7 fpatm: defs 1 ; Patch Timed-Out 8 ftplm: defs 1 ; Temp PL Override Timed-Out 9 fdnlm: defs 1 ; DTMF Pass-Thru Timed-Out 10 fltxm: defs 1 ; Aux TX Timed-Out 11 fltom: defs 1 ; Landline Control Timed-Out 12 fucrm: defs 1 ; Update CRT Screen 13 fgtfe equ $ ; mark table end ;============================================================================ ; Memory Storage for System Start-Up Variables ;============================================================================ ; WARNING! This table must be in the same sequence ; and contain the same number of assigned storage locations ; as there are bytes in the System Data Table in ROM. ; It can start anywhere as long as it fits in memory. ramdat equ $ ; location to begin storing system data table ; Input Port Control Bytes: port0c: defs 1 ; Input Port 0 port1c: defs 1 ; Receivers P1 port2c: defs 1 ; Input Port 2 ; Output Port Control Bytes port4c: defs 1 ; Output Port 4 port5c: defs 1 ; Output Port 5 port6c: defs 1 ; Audio Gates P6 port7c: defs 1 ; Transmitters P7 uflag: defs 1 ; CRT update control umode: defs 1 ; CRT update mode mflag: defs 1 ; Macro Functions control uadflg: defs 1 ; UAD Functions control cwena: defs 1 ; MCW/Speech Mode vctmod: defs 1 ; 6M Courtesy Tone Mode uctmod: defs 1 ; 450 Courtesy Tone Mode dmutc: defs 1 ; DTMF Mute control ptchc: defs 1 ; Autopatch control dtplv: defs 1 ; 6M DTMF PL control dtplu: defs 1 ; 450 DTMF PL control vpltf: defs 1 ; 6M PL inhibit timeout control upltf: defs 1 ; 450 PL inhibit timeout control vplom: defs 1 ; 6M temp PL override control flag uplom: defs 1 ; 450 temp PL override control flag chena: defs 1 ; chime enable control byte limuhf: defs 1 ; 450 TX inactivity time limit control flag ; User Functions (*2500 Series) mudig1: defs 1 ; first unlock digit mudig2: defs 1 ; second unlock digit ; Control Functions (*6900 Series) mcdig1: defs 1 ; first unlock digit mcdig2: defs 1 ; second unlock digit ; Default time constants memory stoarge area mdfht: defs 2 ; default main tx hang time mdflt: defs 1 ; default aux tx hang time mdfit: defs 1 ; default IDPTT time mdfcwt: defs 2 ; MCW tone rate counter value mdfid: defs 2 ; default ID timer time 7 mins. mdfto: defs 2 ; default Time Out timer 3 Mins. mdfvad: defs 1 ; default 6M access delay mdfvrd: defs 1 ; default 6M release delay mdfvgd: defs 1 ; default 6M audio access delay mdfuad: defs 1 ; default 450 access delay mdfurd: defs 1 ; default 450 release delay mdfugd: defs 1 ; default 450 audio access delay mdfaad: defs 1 ; default Aux R1 access delay mdfard: defs 1 ; default Aux R1 release delay mdfbad: defs 1 ; default Aux R2 access delay mdfbrd: defs 1 ; default Aux R2 release delay mdfatt: defs 2 ; default Aux TX Time Limit mdftpl: defs 2 ; default Temp PL Override Time Limit mdfulm: defs 2 ; default 450 TX inactivity limit mdfina: defs 2 ; default inactivity limit reset time mdfwpm: defs 1 ; default MCW dot length (speed) mdftel: defs 2 ; default patch timer mdfctl: defs 1 ; default control system time-out mdfrut: defs 1 ; default Radio DTMF Mute delay mdftut: defs 1 ; default Telephone DTMF Mute delay mdfrdv: defs 1 ; default Radio DTMF Data Valid Delay mdfnul: defs 2 ; default DTMF Pass-Through Delay mdfrgm: defs 1 ; default # of rings to answer mdfird: defs 2 ; default inter-ring delay mdfacc: defs 2 ; ring control access delay mdfhld: defs 2 ; answer hold time mdfmxl: defs 2 ; default maximum landline time mdfpct: defs 2 ; default landline courtesy tone time muptim: defs 1 ; CRT refresh time 1 sec. mdfct1: defs 1 ; Default RX #1 Indicator Char mdfct2: defs 1 ; Default RX #2 Indicator Char mdfcb1: defs 1 ; Default TX #1 Indicator Char mdfcb2: defs 1 ; Default TX #2 Indicator Char mdfsr: defs 1 ; Default Speech Rate mdfir: defs 1 ; Default Inflection Rate mdfar: defs 1 ; Default Articulation Rate mdfrd: defs 1 ; Default ring detect delay mdfcty: defs 1 ; Default century dial0: defs 12 ; speed dialer entries dial1: defs 12 dial2: defs 12 dial3: defs 12 dial4: defs 12 dial5: defs 12 dial6: defs 12 dial7: defs 12 dial8: defs 12 dial9: defs 12 mac0: defs 5 ; Programmed Macro Codes mac1: defs 5 mac2: defs 5 mac3: defs 5 mac4: defs 5 mac5: defs 5 mac6: defs 5 mac7: defs 5 mac8: defs 5 mac9: defs 5 sch0: defs 10 ; Scheduled Events sch1: defs 10 sch2: defs 10 sch3: defs 10 sch4: defs 10 sch5: defs 10 sch6: defs 10 sch7: defs 10 sch8: defs 10 sch9: defs 10 twoc0: defs 9 ; Two Meter Frequencies twoc1: defs 9 twoc2: defs 9 twoc3: defs 9 twoc4: defs 9 twoc5: defs 9 twoc6: defs 9 twoc7: defs 9 twoc8: defs 9 twoc9: defs 9 twoac: defs 1 ; Two Meter Active Channel ;---------------------------------------------------------------------------- ; CRT Parameters Storage ;---------------------------------------------------------------------------- inistr: defs 7 ; terminal initialization string dimstr: defs 5 ; dim or reverse video string bristr: defs 5 ; bright or normal video string clsstr: defs 5 ; clear screen string constr: defs 5 ; cursor ON string cofstr: defs 5 ; cursor OFF string ;---------------------------------------------------------------------------- memend equ $ ; mark the end of the RAM data table mbuf: defs 32 ; command tail storage datend equ $ ; Place the stack at the very top of memory. ; We know where it is so we can test for a run-away program. org ramtop-256 defs 255 stack: defs 0 ; this is location 08fffh org ramtop merr: defs 1 ; controller error type byte memlen equ memend-ramdat ; calculate the length of the RAM data table if syslen ne memlen err1 equ junk1 ; error out if table lengths don't match endif if datend ge stack-255 err2 equ junk2 ; error out if data reaching stack area endif ; ------------------------ end of file MEMORY.Z80 ---------------------------- end ;--------------------------- end of file RPT.Z80 -----------------------------