; SLdt 250519 ;OSCILLATOR=INTERNAL OSCILLATOR .INCLUDE "TN85def.inc" ;------------REGISTER DEFINITION-------------- .DEF T1COUNTER=R0 .DEF STATUS=R1 .DEF DEFDUR=R2 .DEF DEFOCT=R3 .DEF BPM0=R4 .DEF BPM1=R5 .DEF NEWPRE=R6 .DEF NEWOCR=R7 .DEF T00=R8 .DEF T01=R9 .DEF NOTE=R10 .DEF DURATION=R11 .DEF OCTAVE=R12 .def null = r15 ;------------DATA SPACE DEFINITION-------------- ;------------INTERRUPT VECTOR-------------- .ORG 0X0 RJMP INIT .ORG PCI0addr;0X2 RJMP PC_INT .ORG OC0Aaddr;0X6 RJMP T0_INT .INCLUDE "ringtones.inc" .CSEG ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;START OF PROGRAM AND INITIALIZING ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ INIT: ;INITIALIZING I/O PORTS LDI R16,0B00100111 OUT DDRB,R16 SBI PORTB,3 SBI PORTB,4 ;ENABLING PULLUP ;INITIALIZING STACK ;LDI R16,0X9F ;OUT SPL,R16 ;DISABLE ANALOG COMPARATOR SBI ACSR,ACD ;INITAILIZING REGISTERS CLR ZL CLR ZH clr null ;INITIALIZING TIMER0 LDI R16,254 OUT OCR0A,R16 LDI R16,0B00000010 OUT TCCR0A,R16 ; WGM01: CTC auf OCR0A LDI R16,0B00000011 OUT TCCR0B,R16 ; /64 LDI R16,(1<<OCIE0A);0B00000100 OUT TIMSK,R16 ; OCIE0A ;INITIALIZING PIN CHANGE INT LDI R16,(1<<PCINT3)|(1<<PCINT4) OUT PCMSK,R16 LDI R16,(1<<PCIE) OUT GIMSK,R16 SEI HERE: RJMP HERE ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;PIN CHANGE INTERRUPT (USED FOR KEY HANDLING) ;USED REGISTER:R16,R17 ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ PC_INT: ;WAIT FOR SOME SECONDS TO PREVENT BOUNCING LDI R16,20 RCALL WAITMS ;CHECK PB3 SBIC PINB,3 RJMP PC_INT0 ;SET STATUS REGISTER INTO RING LDI R16,0X1 OR STATUS,R16 RETI PC_INT0: SBIC PINB,4 RETI ;TURN OFF THE RING ;BY TURNING OC0A TO ;NORMAL PORT OPERATION IN R16,TCCR0A ANDI R16,0B10111111 OUT TCCR0A,R16 CBI PORTB,0 ;INCREASE INTERRUPT DURATION ;TO THE MAXIMUM (ABOUT 16MS) LDI R16,255 OUT OCR0A,R16 LDI R16,0B00000011 OUT TCCR0B,R16 ;RESET NOTE POINTER CLR ZL CLR ZH ;STORE NEW RINGTONE ADDRESS IN E2PROM LDI R16,0 RCALL READROM MOV R17,R16 INC R17 LDI R16,1 RCALL READROM CP R16,R17 BRSH PC_INT1 LDI R17,1 PC_INT1: LDI R16,0 RCALL WRITEROM ;SET STATUS REGISTER INTO RING LDI R16,0X1 OR STATUS,R16 RETI ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;TIMER 0 INTERRUPT (USED FOR RING) ;USED REGISTER:R16,R17,R24,R25,ZH,ZL ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ T0_INT: SBRC STATUS,0 RJMP T0_INT1 ;RING FLAG IS CLEAR ;SO IS IT STILL RINGING? CLR R16 CP ZL,R16 CPC ZH,R16 BRNE T0_INT0 RETI T0_INT0: ;TURN OFF THE RING ;BY TURNING OC0A TO ;NORMAL PORT OPERATION IN R16,TCCR0A ANDI R16,0B10111111 OUT TCCR0A,R16 CBI PORTB,0 ;INCREASE INTERRUPT DURATION ;TO THE MAXIMUM (ABOUT 16MS) LDI R16,255 OUT OCR0A,R16 LDI R16,0B00000011 OUT TCCR0B,R16 ;RESET NOTE POINTER CLR ZL CLR ZH ;SET STATUS REGISTER INTO NOT RINGING LDI R16,0XFE AND STATUS,R16 RETI T0_INT1: ;RING FLAG IS SET ;SO TEST THE NOTE POINTER TST ZL BRNE T0_INT2 TST ZH BRNE T0_INT2 ;NOTE POINTER IS ZERO ;SO LOAD RINGTONE TABLE ADDRESS ;FROM E2PROM LDI R16,0 RCALL READROM LSL R16 MOV R17,R16 RCALL READROM MOV ZL,R16 MOV R16,R17 INC R16 RCALL READROM MOV ZH,R16 ;LOAD DEFAULTS LPM DEFDUR,Z+ LPM DEFOCT,Z+ LPM BPM0,Z+ LPM BPM1,Z+ RJMP T0_INT3 T0_INT2: ;TEST NEW PRESCALAR VALUE ;IF ZERO THEN TURN OFF THE RING TST NEWPRE BREQ T0_INT0 OUT OCR0A,NEWOCR OUT TCCR0B,NEWPRE ;IF NOTE IS "P" THEN SET NPO LDI R16,'P' CP NOTE,R16 BRNE T0_INT2A IN R16,TCCR0A ANDI R16,0B10111111 OUT TCCR0A,R16 CBI PORTB,0 RJMP T0_INT2B T0_INT2A: ;TURN ON THE RING IN R16,TCCR0A ORI R16,0B01000000 OUT TCCR0A,R16 T0_INT2B: ;DECREASE COUNTER LDI R16,1 CLR R17 SUB T00,R16 SBC T01,R17 ;COMPARE COUNTER WITH 0 CLR R16 CP T00,R16 CPC T01,R16 BREQ T0_INT3 RETI T0_INT3: ;LOAD THE NEXT NOTE LPM NOTE,Z+ ;IF NOTE IS ZERO THEN STOP PLAYING TST NOTE BRNE T0_INT4 CLR NEWPRE RETI T0_INT4: ;LOAD DEFAULTS MOV OCTAVE,DEFOCT MOV DURATION,DEFDUR ;CHECK BIT 7 OF NOTE SBRS NOTE,7 RJMP T0_INT5 ;IF BIT7 IS ONE THEN ;NEXT BYTE CONTAINS ;OCTAVE AND DURATION LPM R17,Z+ MOV OCTAVE,R17 LDI R16,7 AND OCTAVE,R16 MOV DURATION,R17 LSR DURATION LSR DURATION LSR DURATION INC DURATION T0_INT5: ;CLEAR NOTE MSB LDI R16,127 AND NOTE,R16 ;IF NOTE IS "P" THEN SET OCTAVE TO 3 LDI R16,'P' LDI R17,3 CPSE NOTE,R16 MOV R17,OCTAVE MOV OCTAVE,R17 ;KEEP NOTE POINTER IN STACK PUSH ZH PUSH ZL ;LOAD OCTAVE TABLE ADDRESS MOV R16,OCTAVE LDI ZL,LOW(OCTAVE3<<1) LDI ZH,HIGH(OCTAVE3<<1) T0_INT6: CPI R16,4 BRNE T0_INT7 LDI ZL,LOW(OCTAVE4<<1) LDI ZH,HIGH(OCTAVE4<<1) T0_INT7: CPI R16,5 BRNE T0_INT8 LDI ZL,LOW(OCTAVE5<<1) LDI ZH,HIGH(OCTAVE5<<1) T0_INT8: CPI R16,6 BRNE T0_INT9 LDI ZL,LOW(OCTAVE6<<1) LDI ZH,HIGH(OCTAVE6<<1) T0_INT9: CPI R16,7 BRNE T0_INT10 LDI ZL,LOW(OCTAVE7<<1) LDI ZH,HIGH(OCTAVE7<<1) T0_INT10: ;FIND NOTE THROUGH TABLES LPM R16,Z ADIW ZH:ZL,5 CPSE R16,NOTE RJMP T0_INT10 SBIW ZH:ZL,4 ;LOAD PRESCALAR AND OCR LPM NEWPRE,Z+ LPM NEWOCR,Z+ ;(12f)/TEMPO LPM R24,Z+ LPM R25,Z MOV ZL,BPM0 MOV ZH,BPM1 RCALL Di16U ;% * 40 LDI R24,40 LDI R25,0 RCALL Mp16u ;% / DURATION MOV R24,ZL MOV R25,ZH MOV ZL,DURATION CLR ZH RCALL Di16U MOV T00,ZL MOV T01,ZH POP ZL POP ZH RETI ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;READ E2PROM ROUTINE ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ READROM: out EEARH,null OUT EEARL,R16 SBI EECR,EERE IN R16,EEDR RET ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;WRITE E2PROM ROUTINE ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ WRITEROM: out EEARH,null OUT EEARL,R16 OUT EEDR,R17 SBI EECR,EEMPE SBI EECR,EEPE WRITEROM0: SBIC EECR,EEPE RJMP WRITEROM0 RET ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;16/16 UNSIGNED DIVISION ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Di16u: MOV R22,ZL MOV R23,ZH MOV ZL,R24 MOV ZH,R25 CLR R24 SUB R25,R25 LDI R20,0x11 d16u1: ROL ZL ROL ZH DEC R20 BRNE d16u2 RET d16u2: ROL R24 ROL R25 SUB R24,R22 SBC R25,R23 BRCC d16u3 ADD R24,R22 ADC R25,R23 CLC RJMP d16u1 d16u3: SEC RJMP d16u1 ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;16x16 unsigned multiply ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Mp16u: clr r23 clr r22 ldi r21,0x10 lsr zh ror zl m16u1: brcc m16u2 add r22,r24 adc r23,r25 m16u2: ror r23 ror r22 ror zh ror zl dec r21 brne m16u1 ret ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;Wait milliseconds ;FOR 1MHZ OSC ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ WAITMS: PUSH R20 PUSH R21 _Wms: LDI R20,20 _Wms1: LDI R21,17 _Wms2: DEC R21 BRNE _Wms2 DEC R20 BRNE _Wms1 DEC R16 BRNE _Wms POP R21 POP R20 RET