📄 dc550_interrupt.s43
字号:
;*****************************************************************************;
;* CONFIDENTIAL *;
;* Sigpro Copyright 2003, All rights reserved *;
;*****************************************************************************;
;* CLIENT: Telematrix *;
;* PROJECT: DC550 Digital Centrex Phone *;
;* FILE: dc550_hwinit.s43 *;
;*****************************************************************************;
;* This file contains the interrupt handler routine for Timer A *;
;*****************************************************************************;
#define __ASSEMBLY__ 1
#include "dc550_local.h"
#include "dc550_interrupt.h"
#define TELEPHONE 1
NAME dc550_interrupt(16)
RSEG CODE
PUBLIC interrupt_counter
PUBLIC interrupt_state
PUBLIC interrupt_rxmessage
PUBLIC interrupt_txmessage
PUBLIC interrupt_rxready
PUBLIC interrupt_txready
PUBLIC interrupt_txmsgerror
PUBLIC interrupt_init
PUBLIC interrupt_timer_handler
PUBLIC parityErrors
PUBLIC addressErrors
PUBLIC collisionsOnTx
PUBLIC interrupt_buzzercounter
EXTERN ledBlinkData
EXTERN ledState
EXTERN display_usingbus
;******************************************************************************
;* CENTREX MODEM CONSTANTS
;******************************************************************************
INT_TIME EQU 192
PERIOD_8K EQU 383
PERIOD_HF EQU 23
THRESHOLD EQU 10h
;******************************************************************************
;* INTERRUPT LEVEL RESERVED REGISTERS
;******************************************************************************
#define cosine_sum R4
#define sine_sum R5
;******************************************************************************
;* FUNCTION: void interrupt_init(void)
;******************************************************************************
;* DESCRIPTION:
;* This function initializes the variables for the one interrupt handler.
;******************************************************************************
interrupt_init:
MOV #0,&interrupt_counter ; interrupt_counter = 0
MOV #0,&interrupt_state ; interrupt_state = 0
MOV #0,&interrupt_rxmessage ; interrupt_rxmessage = 0
MOV.B #0,&interrupt_rxready ; interrupt_rxready = 0
MOV #0,&interrupt_txmessage ; interrupt_txmessage = 0
MOV.B #0,&interrupt_txready ; interrupt_txready = 0
MOV #0,&interrupt_modemstate ; interrupt_modemstate = A
MOV #0,&interrupt_rxcounter ; interrupt_rxcounter = -3
MOV #0,&interrupt_rxbuffer ; interrupt_rxbuffer = 0
MOV #0,&interrupt_txcounter ; interrupt_txcounter = 0
MOV #0,&interrupt_txbuffer ; interrupt_txbuffer = 0
MOV.B #0,&interrupt_rxparity ; interrupt_rxparity = 0
MOV.B #0,&interrupt_rxmsgerror ; interrupt_rxmsgerror = 0
MOV.B #0,&interrupt_txparityak ; interrupt_txparityak = 0
MOV.B #0,&interrupt_txmsgerror ; interrupt_txmsgerror = 0
MOV.B #03h,&interrupt_tx8khzsamples ; interrupt_tx8khzsamples = 4
MOV #0010h,&interrupt_rtcounter ; interrupt_rtcounter = 0x10
MOV #0,&interrupt_tvcounter ; interrupt_tvcounter = 0
CLR &numWinSamples ; numWinSamples = 0;
CLR &winIdx ; winIdx = 0;
CLR &sin_win_sum ; sin_win_sum = 0;
CLR &cosin_win_sum ; cosin_win_sum = 0;
CLR &parityErrors ; parityErrors = 0;
CLR &addressErrors ; addressErrors = 0;
CLR &collisionsOnTx ; collisionsOnTx = 0;
MOV #01h,interrupt_agcthreshold ; interrupt_agcthreshold = 0x01
MOV #0,interrupt_buzzercounter ; interrupt_buzzercounter = 0
CLR.W &led_switch ; led_switch = 0
RET
;******************************************************************************
;* FUNCTION: void interrupt_timer_handler(void)
;******************************************************************************
;* DESCRIPTION:
;* This interrupt handler is called once every 31.25 microseconds by Timer A
;* through the interrupt vector defined below. The interrupt handler has
;* five possible states:
;* 0. In State 0, it initializes Timer B (used for the carrier signal for
;* transmission), switches the State variable to 1, and returns
;* 1. In State 1, it runs the modem transmit code, switches the State
;* variable to 2, and returns
;* 1. In State 2, it updates the LEDs, switches the State variable to 3, and
;* returns
;* 3. In State 3, it increments the interrupt_counter (used to track the
;* passage of time), updates the interrupt_buzzercounter and switches
;* the buzzer pin if necessary, switches the State variable to 4,
;* and returns
;* 4. In State 4, it runs the modem receive code, switches the State
;* variable to 1, and returns
;* All states are executed perpetually except for State 0, which only runs
;* once. The interrupt handler also reads a sample from the ADC in all
;* states. Each set of 4 samples can then be evaluated in the modem receive
;* code to see if they constitute a 1 or a 0.
;*
;* The modem, which is run in states 1 and 4, also has multiple states:
;* A. Hunting for carrier
;* B. Verifying a detected carrier
;* C. Receiving bits
;* D. Acknowledging receipt of bits
;* E. Transmitting bits for start, direction, address, and command
;* F. Transmitting repeat bit
;* G. Transmitting collision bit
;* H. Transmitting parity bit
;* I. Receiving acknowledgement
;* J. <Obsolete>
;* K. <Obsolete>
;* L. Vegetating for a fixed amount of time
;*
;* NOTES:
;* + Every time State B is entered, rxcounter must be set to -3
;* + Only B or G and get into A, only A can get into B, only D or F or I can
;* get into G, and only E can get into F or I, so D and E MUST set
;* timerb_period to PERIOD_HF.
;* + Since Interrupt 1 reads the first sine sample, it gets R5 for free
;* + rxmsgerror gets set to 0x20 if the collision bit on the message was set.
;* The message is then ignored, and rxmsgerror gets set to 0, regardless of
;* parity or anything else.
;* + rxmsgerror gets set to 0x11 if the parity was wrong. The message is then
;* ignored, and rxmsgerror gets set to 0x01.
;* + txmsgerror is 0x01 when a PACK is not received. The message is then
;* retransmitted with the repeat bit set.
;* + txmsgerror ix 0x02 when a PACK is not received twice in a row. In
;* this case, the message will be dropped.
;* + txmsgerror is 0x04 when a collision is detected. The message is then
;* retransmitted, but without the repeat bit set.
;* + Because of the averaging algorithm, our rxcounter = 0 on the receive
;* side is currently 250us after the t = 0 described in the NIS spec
;******************************************************************************
;******************************************************************************
;* INTERRUPT_STATE_0
;******************************************************************************
;* Interrupt State 0 only executes once; it is used to initialize Timer B in
;* syncwith the Timer A interrupt
;******************************************************************************
INTERRUPT_STATE_0
; Sets up Timer_B for N*32KHz Toggle Rate
; Since the system does not have a digital to analog converter,
; Timer_B is used to generate the 8KHz signal for a 1 bit. A 0 bit
; uses a 128KHz signal, which is then drowned out using a band pass
; filter.
mov #PERIOD_HF,&interrupt_timerb_period
mov #PERIOD_HF,&TBCCR0
;set outmode 4 for toggle, delayed loard of TBCCR0
mov #00280h,&TBCCTL0
#if TDB
mov #00214h,&TBCTL ;start TIMER_B up mode, select SMCLK as input clock
#else
mov #00114h,&TBCTL ;start TIMER_B up mode, select ACLK as input clock
#endif
; 34 KHz receive code
MOV &ADC12MEM0,cosine_sum
; Increment to State 1
MOV #2,&interrupt_state
RETI
;******************************************************************************
;* INTERRUPT_STATE_1
;******************************************************************************
;* Interrupt State 1 runs the modem transmit code.
;******************************************************************************
INTERRUPT_STATE_1
; This must happen immediately before Timer B rolls over so that the
; interrupt handler and Timer B remain in sync
MOV interrupt_timerb_period,&TBCCR0;
ADD interrupt_modemstate,pc
JMP int1A
JMP int1r ; The transmit side doesn't really do
JMP int1r ; anything in states B and C
JMP int1D
JMP int1E
JMP int1F
JMP int1G
JMP int1H
JMP int1I
JMP int1r ; The transmit side doesn't really do
JMP int1r ; anything in states J and K
;The pc will automatically jump through for State L
; Interrupt 1, State L (Vegetating for a fixed amount of time)
int1L: DEC interrupt_tvcounter ; tvcounter--;
JNZ int1r ; if(tvcounter) break;
MOV #10h,interrupt_rtcounter ; else { rtcounter = 2ms;
MOV #0,interrupt_modemstate ; modemstate = A;
JMP int1r ; break; }
; Interrupt 1, State K (Verifying carrier, transmit disabled)
; The transmit side doesn't really do anything here
; timerb_period should be PERIOD_HF
; int1K: JMP int1r
; Interrupt 1, State J (Hunting for carrier, transmit disabled)
; The transmit side doesn't really do anything here
; timerb_period should be PERIOD_HF
; int1J: JMP int1r
; Interrupt 1, State I (Receiving acknowledgement)
; timerb_period should be PERIOD_HF
int1I: INC interrupt_txcounter; ; txcounter++;
CMP #0098h,interrupt_txcounter
JL int1r ; if(txcounter < 19ms) break;
CMP.B #1,interrupt_txparityak ; // Reverse logic below
JL int1I4 ; if(txparityak >= 1) {
MOV.B #0,interrupt_txready ; txready = 0;
MOV #10h,interrupt_tvcounter ; tvcounter = 2ms;
MOV.B #0,interrupt_txmsgerror ; txmsgerror = 0;
MOV #22,interrupt_modemstate ; modemstate = L;
JMP int1r ; break; }
; //There was no ack
int1I4: MOV #10h,interrupt_tvcounter ; else { tvcounter=2ms;
XOR.B #01h,interrupt_txmsgerror ; txmsgerror ^= 1;
JNZ int1I5 ; // if no ack 2x, drop the msg
MOV.B #2,interrupt_txmsgerror ; if(!txmsgerror) txmsgerror=2;
MOV #01h,interrupt_agcthreshold ; interrupt_agcthreshold = 0x01
MOV.B #0,interrupt_txready ; txready=0;
MOV #10h,interrupt_tvcounter ; tvcounter = 2ms;
int1I5: MOV #22,interrupt_modemstate ; modemstate = L;
JMP int1r ; break;
; Interrupt 1, State H (Transmitting parity bit)
int1H: INC interrupt_txcounter ; txcounter++;
CMP #0080h,interrupt_txcounter; //Reverse logic below
JL int1r ; if( 16ms have elapsed ) {
MOV #PERIOD_HF,interrupt_timerb_period
BIT.B #04h,interrupt_txmsgerror ; timerb_period = PERIODHF;
JNZ int1H4 ; if((txmsgerror&0x04)==0) //RL
MOV.B #0,interrupt_txparityak ; txparityak = 0;
MOV #16,interrupt_modemstate ; modemstate = I;
JMP int1r ; break;
int1H4: MOV #28h,interrupt_tvcounter ; else { //There was a collision
MOV.B #0,interrupt_txmsgerror ; tvcounter=5ms;txmsgerror=0;
MOV #22,interrupt_modemstate ; modemstate=L;
JMP int1r ; break;
; Interrupt 1, State G (Transmitting collision bit)
int1G: INC interrupt_txcounter ; txcounter++;
CMP #0078h,interrupt_txcounter; //Reverse logic below
JL int1r ; if( 15ms have elapsed ) {
MOV #14,interrupt_modemstate ; modemstate = H
MOV #0,numWinSamples ; clear window variables
MOV #0,winIdx
MOV #0,sin_win_sum
MOV #0,cosin_win_sum ; // parity bit is between 15ms
BIT.B #01h,interrupt_txparityak ; // and 16ms
JNZ int1G4 ; if (txparityak==0)
MOV #PERIOD_HF,interrupt_timerb_period
JMP int1r ; timerb_period = PERIOD_HF;
int1G4: MOV #PERIOD_8K,interrupt_timerb_period
JMP int1r ; else{timerb_period=PERIOD_8K;
; Interrupt 1, State F (Transmitting repeat bit)
int1F: INC interrupt_txcounter ; txcounter++;
CMP #0070h,interrupt_txcounter; //Reverse logic below
JL int1r ; if( 14ms have elapsed ) {
MOV #12,interrupt_modemstate ; modemstate = G
MOV #0,numWinSamples ; clear window variables
MOV #0,winIdx
MOV #0,sin_win_sum
MOV #0,cosin_win_sum ; // collision bit is between 14ms
BIT.B #04h,interrupt_txmsgerror ; // and 15ms
JNZ int1F4 ; if((txmsgerror&0x04)==0) //RL
MOV #PERIOD_8K,interrupt_timerb_period
XOR.B #01h,interrupt_txparityak ; timerb_period=PERIOD_8K;
JMP int1r ; txparityak ^= 0x01; }
int1F4: MOV #PERIOD_HF,interrupt_timerb_period
JMP int1r ; else timerb_period=PERIOD_HF;
; Interrupt 1, State E
; (Transmitting bits for start, direction, address, and command)
int1E: INC interrupt_txcounter ; txcounter++;
BIT #7,interrupt_txcounter ; //Reverse logic below
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -