Because I intend to start doing Lena's tutorials soon, I decided to brush up on my minimal knowledge of ASM so as to not go in completely blind.
For that purpose I decided to give myself a mini-project with the following theme:
I have created a simple and basic phone-to-phone system using the Deeds Digital Circuit Simulator (DDcS) and the Deeds Micro Computer Emulator (DMCE).This system can fully simulate a phone call between two parties by means of equivalents for real-world actions such as talking, picking up the phone, etc. The design is based on ISDN: “Integrated Services Digital Network, a set of communications standards for simultaneous digital transmission of voice, video, data, and other network services over the traditional circuits of the public switched telephone network.”
Problem Description:
Create and implement an ISDN telephony system by creating a digital circuit schematic which contains 2 or 3 processors, 2 of them for the phones, and an optional one for an ISDN switch. Then code, using DMCE, the operating systems of these devices in the Assembly language for the Z80 processor.
Architecture:
Z80 - Reference Link
Tool for development:
Deeds (containing the Deeds Main Browser; The d-AsTAssistant Browser; The d-DcS Digital Circuit Simulator; The d-FsM Finite State Machine Simulator; The d-McE Micro-Computer Emulator) - Reference Link
Implementation:
In the first version of the project I attempted to create a telephony network using 2 phones, acted by two Z80 processors, and a switch, also acted by a Z80 processor. I created the digital circuits schematic by connecting the two phones in an identical way to the switch. By this I mean that the I/O interfaces of the phones are connected in a very specific way to the switch so as to create universality, which allowed me to build only one operating system which works on both phones, and symmetry, which allows theoretically unlimited expansion, as long as the switch can accept the inputs of the phones. Due to big problems caused by synchronization between the phones and the switch, I was forced to abandon the 2 phone/1 switch design, and decided instead to just remove the switch and implement the system with 2 directly connected phones.
Assumptions:
Due to not being able to actually pass voice as information, and due to not being able to make the phones actually ring, a series of assumptions had to be made in order to be able to simulate the phones:
1. The ringer shall be a binary output which stays as 1 while the phone is ringing and at 0 while the phone is not ringing.
2. The talking (once a call is established) shall be simulated using switches for talking, and binary outputs for incoming chatter.
3. The clock speed is set as follows:
4. The Phone ID as well as the dialer are inputted using dip-switches due to the fact that a 0-9 digit input type was unable to be implemented in the design. (i.e. I couldn't really be bothered)
Also, due to not having a switch in the design anymore, there is one very important step that cannot be performed:
After a call has ended it is vital that the phone processors enter a reset state for a very short period of time in order to prevent any DE-synchronization between them. This is an action which would be performed by the switch by sending a 1 bit through a wire connected to the Reset input of the phones.
How to make a call:
- Once the OS has been loaded in both the phones the system is ready for testing.
- In order to do so the clock rate must be set as follows: . The multiplier is irrelevant to the synchronization, so it can be adjusted to x1 or x10 in order to be able to follow the code on the processors.
- Once DDcS is simulating the circuit, the Phone ID’s must be inputted using the given dip-switches (for explanation see Assumptions), and the phone which is making the call has to input the other phone's ID in his dialer.
- Once this step has been completed the call can be made by setting the Call/Drop input of the calling phone to ON (default: OFF).
- The immediate response (if using a x100 multiplier) will be a 1 in the Ringer output of the phone which is being called. Once that has been established, the second party can answer the call by setting the Call/Drop input to ON (default: OFF).
- Once the second party answers the call, the call is established (assuming a x100 multiplier; lower multipliers might require some time before call is established) and voice communication can begin. Setting the L.Talk of any of the phones (simulates talking in the microphone) to 1 will trigger a response in setting the P.Talk (simulates sounds in the headset) of the other phone to 1.
- To end a call either of the parties has to set the Call/Drop input to OFF (default: OFF). At this point the reset switch should be set to ON and then to OFF (default: OFF) before another call is attempted.
I/O:
PHONE
IA – phone ID
IB – dialed number
IC – incoming call phone number
ID0 – local talking
ID1 – external talking
ID2 – incoming call
ID3 – call activate/deactivate
OA – caller ID
OB0 – ringer
OB1 – external talking
OD – outgoing call local no/dialed no
Version 1 (Non-Working & Deprecated) Schematic:
Version 2 (Working and Implemented) Schematic:
Phone Source Code (Working, Implemented, part of Version 2):
;===================================================================================
;||ver 2.0 ||
;|| ||
;|| ==ISDN Phone== ||
;|| Assembly Source Code ||
;|| Mordred ||
;|| ||
;|| ||
;|| ||
;===================================================================================
ORG 0000 ;ORGanizes at the first memory address location
JP init ;jumps to the initialization sub-routine
init: ; initialization / boot procedure
IN A,(00) ;stores the input of IA (PHONE ID) in the A register
LD B, A ;copies the A register to the B register, the register which holds the local phone's id
LD A, 0 ;stores the value 0 in A
OUT (00), A ;resets the CALLER ID output to 00
JP idle ;jumps to the idle state
idle: ;a loop that makes the phone wait for an incoming or outgoing phonecall
LD A, 0 ;stores the value 0 in A
OUT (00), A ;resets the CALLER ID output to 00
OUT (01), A ;resets the RINGER output to 0
IN A, (03) ;stores the input of ID (CALL/DROP,DIAL IN,TALK IN, L.TALK) in the A register
LD H, A ;copies the A register to H so that we can manipulate the inputs
BIT 2, H ;checks if DIAL IN is set to 1
JP NZ, callIn ;if DIAL IN is set to 1 it means we have an incoming phone call, jumps to callIn
BIT 3, H ;checks if CALL/DROP is set to 1
JP NZ, callOut ;if CALL/DROP is set to 1 but DIAL IN is set to 0 it means we have an outgoing phone call, jumps to callOut
JP idle ;if no call is being made jumps back to idle
callIn: ;sub-routine for incoming calls
LD A, 0 ;command used for syncing purposes
LD A, 1 ;command used for syncing purposes
LD A, 2 ;command used for syncing purposes
IN A, (03) ;stores the input of ID (CALL/DROP,DIAL IN,TALK IN, L.TALK) in the A register
LD L, A ;copies the A register to L so that we can manipulate the inputs
IN A, (02) ;stores the input of IC (INCOMING NO.) to the A register
OUT (00), A ;outputs the input of IC on the CALLER ID output
BIT 3, L ;checks if the user answered before the ringer starts
JP Z, ringer ;if the user did not answer yet, the ringer starts
;RET
callOut: ;sub-routine for outgoing calls
IN A, (03) ;stores the input of ID (CALL/DROP,DIAL IN,TALK IN, L.TALK) in the A register
LD L, A ;copies the A register to L so that we can manipulate the inputs
LD A, B ;loads Phone ID into the A register
OUT (03), A ;outputs Phone ID on the Outgoing No output
IN A, (02) ;stores the input of IB (DIALER) in the A register
OUT (03), A ;ouputs the input of IB on the Outgoing No output
JP callEst ;once everything has been done the phone call is established, jumps callEst
;RET
callEst: ;sub-routine for an established call (voice)
LD A, 0 ;stores the value 0 in A
OUT (01), A ;resets the RINGER output to 0
IN A, (03) ;stores the input of ID (CALL/DROP,DIAL IN,TALK IN, L.TALK) in the A register
LD D, A ;copies the A register to D so that we can manipulate the inputs
BIT 3, D ;checks if the call is still active
JP Z, idle ;if the call is not still active, jumps idle
BIT 1, D ;checks if there is incoming voice
CALL NZ, voiceIn ;calls the voiceIn function due to incoming voice
;BIT 0, D
;CALL NZ, voiceOut
;The above lines are commented out because the phone that makes the
;call does not need to know if the local user is talking or not
JP callEst ;jumps back to call established until the call is not active anymore
voiceIn: ;sub-routine for incoming voice after call establishment
IN A, (03) ;stores the input of ID (CALL/DROP,DIAL IN,TALK IN, L.TALK) in the A register
LD E, A ;copies the A register to E so that we can manipulate the inputs
LD A, 2 ;loads the value 10 into the A register
OUT (01), A ;sets P.TALK to active, so as to simulate activity in the headset
BIT 1, E ;checks if there is voice in
JP NZ, voiceIn ;if there is voice in it jumps back to the start of the sub-routine
LD A, 0 ;loads the value 0 in the A register
OUT (02), A ;resets P.TALK and RINGER because there is no more voice in
RET ;returns to callEst
;voiceOut: ;sub-routine for outgoing voice after call establishment - not needed in this problem
ringer: ;sub-routine for the ringer between callIn and callEst
IN A, (03) ;stores the input of ID (CALL/DROP,DIAL IN,TALK IN, L.TALK) in the A register
LD C, A ;copies the A register to C so that we can manipulate the inputs
LD A, 1 ;loads the value 1 to the A register
OUT (01), A ;sets RINGER to active so as to simulate activity from the ringer
BIT 3, C ;checks if the call was established
JP NZ, callEst ;if call was established jumps to callEst
JP ringer ;else jumps back to start of the sub-routine
Switch Source Code (Non-Working, Non-Implemented, part of Version 1):
;===================================================================================
;||ver 1.0 ||
;|| ||
;|| ==ISDN Switch== ||
;|| Assembly Source Code ||
;|| Mordred ||
;|| ||
;|| ||
;|| ||
;===================================================================================
ORG 0000 ;ORGanizez at the first memory address location
JP init ;jumps to the initialization sub-routine
init: ;initialization/boot procedure
JP idle ;jumps to the idle state
idle: ;a loop that makes the switch wait for activity from one of the phone sets
IN A, (01) ;stores the input of IB in the A register
LD B, A ;memorizez the value of A in B for manipulation
BIT 6, B ;we check if there is an incoming call from phone 1 to phone 2
JP NZ, callRou12 ;if there is we jump to the subroutine callRouting12
IN A, (03) ;stores the input of ID in the A register
LD C, A ;memorizez the value of A in C for manipulation
BIT 6, C ;we check if there is an incoming call from phone 2 to phone 1
JP NZ, callRou21 ;if there is we jump to the subroutine callRouting21
JP idle ;if there are no calls active jumps back to idle
callRou12: ;sub-routine which prepares the phones for call establishment
IN A, (00) ;loads the PHONE ID into the A registry
LD H, A ;memorizez PHONE ID in H registry
CALL sync12 ;calls the synchronization sub-routine
LD A, 2 ;loads "1" into the A registry bit 1
OUT (02), A ;activates DIAL IN for phone 2
LD A, H ;loads the PHONE ID into A
OUT (03), A ;outputs the PHONE ID to phone 2 for its CALLER ID output
CALL wait12 ;waits for phone 2 to answer
LD A, 2 ;loads "1" into the A registry bit 1
OUT (01), A ;confirmation that call is established
JP callEst ;once call was established (wait12 has finished it's looping) jumps to the callEst sub-routine
callRou21: ;sub-routine which prepares the phones for call establishment
IN A, (02) ;loads the PHONE ID into the A registry
LD H, A ;memorizez PHONE ID in H registry
CALL sync21 ;calls the synchronization sub-routine
LD A, 2 ;loads "1" into the A registry bit 1
OUT (01), A ;activates DIAL IN for phone 1
LD A, H ;loads the PHONE ID into A
OUT (00), A ;outputs the PHONE ID to phone 1 for its CALLER ID ouput
CALL wait21 ;waits for phone 1 to answer
LD A, 2 ;loads "1" into the A registry bit 1
OUT (02), A ;confirmation that call is established
JP callEst ;once call was established (wait12 has finished it's looping) jumps to the callEst sub-routine
callEst: ;sub-routine for an established call (voice)
IN A, (01) ;copies the input on IB to check call activity
LD E, A ;loads the value for manipulation
IN A, (03) ;copies the input on ID to check call activity
CP E ;compares the inputs to check that both phones still have the call active
JP NZ, idle ;jumps to idle if the call is not active
BIT 7, A ;checks if phone 1 has the call active
JP Z, idle ;jumps to idle if the call is not active
BIT 7, E ;checks if phone 2 has the call active
JP Z, idle ;jumps to idle if the call is not active
;CALL announce
IN A, (01) ;copies the input of IB to check voice activity
BIT 7, A ;checks if there is voice communication active
CALL NZ, voice12 ;calls the voice12 sub-routine if there is voice active
IN A, (03) ;copies the input of IC to check voice activity
BIT 7, A ;checks if there is voice communication active
CALL NZ, voice21 ;calls the voice21 sub-routine if there is voice active
JP callEst ;jumps back to callEst until the call is dropped
;announce: ;sub-routine which announces that the call was established to both the connected phones
; LD A, 2
; OUT (01), A
; OUT (02), A
; RET
wait12: ;sub-routine which loops until the dialled phone connection is established
IN A, (03)
LD D, A
BIT 6, D ;once the dialed phone "picks up" the loop is ended and the program resumes
RET NZ
JP wait12
wait21: ;sub-routine which loops until the dialed phone connection is established
IN A, (01)
LD D, A
BIT 6, D ;once the dialed phone "picks up" the loop is ended and the program resumes
RET NZ
JP wait21
voice12: ;sub-routine which announces phone 2 if the user on phone 1 is talking
LD A, 1
OUT (02), A
IN A, (01)
BIT 7, A
JP NZ, voice12
RET
voice21: ;sub-routine which announces phone 1 if the user on phone 2 is talking
LD A, 1
OUT (01), A
IN A, (03)
BIT 7, A
JP NZ, voice21
RET
sync12: ;sub-routine which synchronizes the switch with the phones in regards to 2 phone number outputs over 1 line
IN A, (00)
LD L, A ;DIALED NO
CP H
RET NZ
JP sync12
sync21: ;sub-routine which synchronizes the switch with the phones in regards to 2 phone number outputs over 1 line
IN A, (02)
LD L, A ;DIALED NO
CP H
RET NZ
JP sync21