[ บทความ : ตัวอย่างสำหรับ 68HC11 V2 ตอนที่ 11 ] ทดสอบติดต่อกับ Output Compare(OCX) เพื่อสร้างเสียงดนตรี |
ตัวอย่างซอร์สโค้ดสำหรับติดต่อกับระบบ Output Compare(OCX) เพื่อสร้างเสียงดนตรี กับบอร์ด CP-68HC11 V2 สำหรับการเขียนเพื่อเป็นโปรแกรมมอนิเตอร์เป็นดังนี้
;/**********************************/; ;/* Demo Program For OutputCompare */; ;/* Timer Run Interrupt Mode */; ;/* Used OCX : Generate Music Note */; ;/* Hardware : ET-CP68HC11 Ver 2.0 */; ;/* Complier : AS11NEW.EXE (V1.03) */; ;/**********************************/; ; ;/***************************/; ;/*** I/O Register Equate ***/; ;/***************************/; ; IOREGS EQU $1000 ; Start of I/O Register PORTA EQU IOREGS+$00 ; I/O Port-A PIOC EQU IOREGS+$02 ; I/O Control Register PORTC EQU IOREGS+$03 ; I/O Port-C PORTB EQU IOREGS+$04 ; I/O Port-B PORTCL EQU IOREGS+$05 ; I/O Control Register DDRC EQU IOREGS+$07 ; Data Direction Register-C PORTD EQU IOREGS+$08 ; I/O Port-D DDRD EQU IOREGS+$09 ; Data Direction Register-D PORTE EQU IOREGS+$0A ; I/O Port-E CFORC EQU IOREGS+$0B ; Force Output Compare OC1M EQU IOREGS+$0C ; OC1 Mask Bits OC1D EQU IOREGS+$0D ; OC1 Data Bits?? TCNT EQU IOREGS+$0E ; Timer Count Register TIC1 EQU IOREGS+$10 ; Input Capture #1 TIC2 EQU IOREGS+$12 ; Input Capture #2 TIC3 EQU IOREGS+$14 ; Input Capture #3 TOC1 EQU IOREGS+$16 ; Output Compare #1 TOC2 EQU IOREGS+$18 ; Output Compare #2 TOC3 EQU IOREGS+$1A ; Output Compare #3 TOC4 EQU IOREGS+$1C ; Output Compare #4 TOC5 EQU IOREGS+$1E ; Output Compare #5 TCTL1 EQU IOREGS+$20 ; Timer Control Register #1 TCTL2 EQU IOREGS+$21 ; Timer Control Register #2 TMSK1 EQU IOREGS+$22 ; Timer Mask #1 TFLG1 EQU IOREGS+$23 ; Timer Flags #1 TMSK2 EQU IOREGS+$24 ; Timer Mask #2 TFLG2 EQU IOREGS+$25 ; Timer Flags #2 PACTL EQU IOREGS+$26 ; Pulse Accum Control PACNT EQU IOREGS+$27 ; Pulse Accum Counter SPCR EQU IOREGS+$28 ; SPI Control Register SPSR EQU IOREGS+$29 ; SPI Status Register SPDR EQU IOREGS+$2A ; SPI Data Register BAUD EQU IOREGS+$2B ; Baudrate Register SCCR1 EQU IOREGS+$2C ; SCI Register 1 SCCR2 EQU IOREGS+$2D ; SCI Register 2 SCSR EQU IOREGS+$2E ; SCI Status Register SCDR EQU IOREGS+$2F ; SCI Data Register ADCTL EQU IOREGS+$30 ; A/D Control Register ADR1 EQU IOREGS+$31 ; A/D Result 1 ADR2 EQU IOREGS+$32 ; A/D Result 2 ADR3 EQU IOREGS+$33 ; A/D Result 3 ADR4 EQU IOREGS+$34 ; A/D Result 4 OPTION EQU IOREGS+$39 ; Option Register COPRST EQU IOREGS+$3A ; COP Reset Register PPROG EQU IOREGS+$3B ; EEPROM Programming Register HPRIO EQU IOREGS+$3C ; Highest-Priority Register INIT EQU IOREGS+$3D ; Memory Map Initialization TEST1 EQU IOREGS+$3E ; Test Register 1 CONFIG EQU IOREGS+$3F ; System Configuration ORG $2000 SONG_PTR RMB 2 ; Music Note Pointer SONG_CNT RMB 2 ; Song Delay Count NOTE_CNT RMB 1 ; Note/Output Count OC1_STAS RMB 1 ; PA7 Status ; FREQ_CNT RMB 2 ; Timer 1/2 Cycle Count FREQ_OC1 RMB 2 FREQ_OC2 RMB 2 FREQ_OC3 RMB 2 FREQ_OC4 RMB 2 FREQ_OC5 RMB 2 ORG $A000 ; Start of code MAIN LDS #$9FFF ; Initial Stack on RAM 32KB LDD #0 ; SONG_CNT = 0 STD SONG_CNT LDAB TMSK2 ORAB #%01000000 STAB TMSK2 ; Enable RTI Interrupt LDAB #%01000000 STAB TFLG2 ; Clear RTIF Flag ; LDAB TMSK1 ORAB #%11111000 STAB TMSK1 ; Enable OC1I-OC5I LDAB #%11111000 STAB TFLG1 ; Clear OC1F-OC5F LDAB #%00000000 STAB TCTL1 ; Disconnect OC2-OC5 Pin LDAB PACTL ORAB #%10000000 STAB PACTL ; PA7 = Output CLI ; Enable Global Interrupt ; NEW_SONG LDAB #%11111000 STAB TFLG1 ; Clear OC1F-OC5F LDD #0 ; Start 1st Music Note STD SONG_PTR ; LDAB #8 STAB NOTE_CNT ; 8-Note on OC5(PA3) ; SONG_OC5 JSR GET_NOTE ; Get Note & Delay LDD FREQ_CNT STD FREQ_OC5 LDD FREQ_OC5 ; FREQ_OC5 = 0 ? CPD #0 BNE ENA_OC5 JMP DIS_OC5 ; ENA_OC5 LDD TCNT ADDD FREQ_OC5 STD TOC5 LDAB TCTL1 ORAB #%00000001 STAB TCTL1 ; Toggle OC5 Pin JMP CHK_OC5 ; DIS_OC5 CLRB ; No Active Output STAB TCTL1 ; Disconnect OC2-5 STAB OC1M ; Disconnect PA7 STAB OC1D ; PA7 = 0 ; CHK_OC5 LDD SONG_CNT ; Loop Until SONG_CNT = 0 CPD #0 BNE CHK_OC5 DEC NOTE_CNT BNE SONG_OC5 ; LDAB #8 STAB NOTE_CNT ; 8-Note on OC4(PA4) ; SONG_OC4 JSR GET_NOTE ; Get Note & Delay LDD FREQ_CNT STD FREQ_OC4 LDD FREQ_OC4 ; FREQ_OC4 = 0 ? CPD #0 BNE ENA_OC4 JMP DIS_OC4 ; ENA_OC4 LDD TCNT ADDD FREQ_OC4 STD TOC4 LDAB TCTL1 ORAB #%00000100 STAB TCTL1 ; Toggle OC4 Pin JMP CHK_OC4 ; DIS_OC4 CLRB ; No Active Output STAB TCTL1 ; Disconnect OC2-5 STAB OC1M ; Disconnect PA7 STAB OC1D ; PA7 = 0 ; CHK_OC4 LDD SONG_CNT ; Loop Until SONG_CNT = 0 CPD #0 BNE CHK_OC4 DEC NOTE_CNT BNE SONG_OC4 ; LDAB #8 STAB NOTE_CNT ; 8-Note on OC3(PA5) ; SONG_OC3 JSR GET_NOTE ; Get Note & Delay LDD FREQ_CNT STD FREQ_OC3 LDD FREQ_OC3 ; FREQ_OC3 = 0 ? CPD #0 BNE ENA_OC3 JMP DIS_OC3 ; ENA_OC3 LDD TCNT ADDD FREQ_OC3 STD TOC3 LDAB TCTL1 ORAB #%00010000 STAB TCTL1 ; Toggle OC3 Pin JMP CHK_OC3 ; DIS_OC3 CLRB ; No Active Output STAB TCTL1 ; Disconnect OC2-5 STAB OC1M ; Disconnect PA7 STAB OC1D ; PA7 = 0 ; CHK_OC3 LDD SONG_CNT ; Loop Until SONG_CNT = 0 CPD #0 BNE CHK_OC3 DEC NOTE_CNT BNE SONG_OC3 ; LDAB #8 STAB NOTE_CNT ; 8-Note on OC2(PA6) ; SONG_OC2 JSR GET_NOTE ; Get Note & Delay LDD FREQ_CNT STD FREQ_OC2 LDD FREQ_OC2 ; FREQ_OC2 = 0 ? CPD #0 BNE ENA_OC2 JMP DIS_OC2 ; ENA_OC2 LDD TCNT ADDD FREQ_OC2 STD TOC2 LDAB TCTL1 ORAB #%01000000 STAB TCTL1 ; Toggle OC2 Pin JMP CHK_OC2 ; DIS_OC2 CLRB ; No Active Output STAB TCTL1 ; Disconnect OC2-5 STAB OC1M ; Disconnect PA7 STAB OC1D ; PA7 = 0 ; CHK_OC2 LDD SONG_CNT ; Loop Until SONG_CNT = 0 CPD #0 BNE CHK_OC2 DEC NOTE_CNT BNE SONG_OC2 ; LDAB #8 STAB NOTE_CNT ; 8-Note on OC1(PA7) ; SONG_OC1 JSR GET_NOTE ; Get Note & Delay LDD FREQ_CNT STD FREQ_OC1 LDD FREQ_OC1 ; FREQ_OC1 = 0 ? CPD #0 BNE ENA_OC1 JMP DIS_OC1 ; ENA_OC1 LDD TCNT ADDD FREQ_OC1 STD TOC1 LDAB #%10000000 STAB OC1M ; OC1 Active PA7 STAB OC1_STAS ; Save Status Output STAB OC1D ; PA7 = 1 JMP CHK_OC1 ; DIS_OC1 CLRB ; No Active Output STAB TCTL1 ; Disconnect OC2-5 STAB OC1M ; Disconnect PA7 STAB OC1D ; PA7 = 0 ; CHK_OC1 LDD SONG_CNT ; Loop Until SONG_CNT = 0 CPD #0 BNE CHK_OC1 DEC NOTE_CNT BNE SONG_OC1 JMP NEW_SONG ;/*********************************/; ;/* Get Frequency & Delay of Note */; ;/* Input : SONG_PTR(Note Table) */; ;/* Output : FREQ_CNT(Note Freq.) */; ;/* : SONG_CNT(Note Delay) */; ;/* : SONG_PTR=SONG_PTR+2 */; ;/*********************************/; ; GET_NOTE LDD SONG_PTR ; Get Note Pointer ADDD #TAB_SONG PSHB PSHA PULX LDAA #2 LDAB 0,X ; B = Note MUL ADDD #TAB_NOTE PSHB PSHA PULX ; X = Note Pointer LDD 0,X STD FREQ_CNT ; Save Note Frequency LDD #1 ADDD SONG_PTR STD SONG_PTR ; SONG_PTR = SONG_PTR+1 ; ;/* Get Delay of Note (Long-Time) */; LDD SONG_PTR ; get duration ADDD #TAB_SONG PSHB PSHA PULX LDAA #2 LDAB 0,X ; B = Delay MUL ADDD #TAB_DELAY PSHB PSHA PULX ; X = Delay Pointer LDD 0,X STD SONG_CNT ; Save Note Delay LDD #1 ADDD SONG_PTR STD SONG_PTR ; SONG_PTR = SONG_PTR+1 RTS ;/*****************/; ;/* RTI Interrupt */; ;/*****************/; ; RTI_INT LDD SONG_CNT ; Get Note CPD #0 BHI DEC_NOTE ; If >= 0 Jump (*+5) JMP CLR_FLAG DEC_NOTE LDD SONG_CNT ; SONG_CNT = SONG_CNT-1 SUBD #1 STD SONG_CNT CLR_FLAG LDD #%01000000 ; Clear RTIF flag STAB TFLG2 RTI ;/******************/; ;/* TOC5 Interrupt */; ;/******************/; ; OC5_INT LDD TOC5 ; Read TOC5 ADDD FREQ_OC5 ; TOC5 = TOC5 + FREQ_OC5 STD TOC5 LDD #%00001000 ; Clear OC5F Flag STAB TFLG1 RTI ;/******************/; ;/* TOC4 Interrupt */; ;/******************/; ; OC4_INT LDD TOC4 ; Read TOC4 ADDD FREQ_OC4 ; TOC4 = TOC4 + FREQ_OC4 STD TOC4 LDD #%00010000 ; Clear OC4F Flag STAB TFLG1 RTI ;/******************/; ;/* TOC3 Interrupt */; ;/******************/; ; OC3_INT LDD TOC3 ; Read TOC3 ADDD FREQ_OC3 ; TOC3 = TOC3 + FREQ_OC3 STD TOC3 LDD #%00100000 ; Clear OC3F Flag STAB TFLG1 RTI ;/******************/; ;/* TOC2 Interrupt */; ;/******************/; ; OC2_INT LDD TOC2 ; Read TOC2 ADDD FREQ_OC2 ; TOC2 = TOC2 + FREQ_OC2 STD TOC2 LDD #%01000000 ; Clear OC2F Flag STAB TFLG1 RTI ;/******************/; ;/* TOC1 Interrupt */; ;/******************/; ; OC1_INT LDD TOC1 ; Read TOC1 ADDD FREQ_OC1 ; TOC1 = TOC1 + FREQ_OC1 STD TOC1 LDAB #%10000000 ; Clear OC1F Flag STAB TFLG1 LDAB OC1_STAS ; Toggle PA7 COMB STAB OC1_STAS ANDB #%10000000 STAB OC1D RTI ;/********************/; ;/* Table of Pointer */; ;/* For Note & Delay */; ;/* Song of All Note */; ;/********************/; ; TAB_SONG FCB 00,1,01,5,02,5,03,5 FCB 04,5,05,5,06,5,07,5 FCB 00,1,08,5,09,5,10,5 FCB 11,5,12,5,13,5,14,5 FCB 00,1,15,5,16,5,17,5 FCB 18,5,19,5,20,5,21,5 FCB 00,1,22,5,23,5,24,5 FCB 25,5,26,5,27,5,28,5 FCB 00,1,29,5,30,5,31,5 FCB 32,5,33,5,34,5,35,5 FCB 255 ; End of Music ;/**************************/; ;/* Table of Standard Note */; ;/**************************/; ; TAB_NOTE FDB 0000 ; No Sound ; FDB 3822 ; Note C (261.624 Hz) Octave4 FDB 3405 ; Note D (293.664 Hz) FDB 3034 ; Note E (329.624 Hz) FDB 2863 ; Note F (349.232 Hz) FDB 2551 ; Note G (391.992 Hz) FDB 2273 ; Note A (440.000 Hz) FDB 2025 ; Note B (493.880 Hz) ; FDB 1911 ; Note C (523.248 Hz) Octave5 FDB 1703 ; Note D (587.238 Hz) FDB 1517 ; Note E (659.248 Hz) FDB 1432 ; Note F (698.464 Hz) FDB 1276 ; Note G (783.984 Hz) FDB 1136 ; Note A (880.000 Hz) FDB 1012 ; Note B (987.760 Hz) ; FDB 956 ; Note C (1046.496 Hz) Octave6 FDB 851 ; Note D (1174.656 Hz) FDB 758 ; Note E (1318.496 Hz) FDB 716 ; Note F (1396.928 Hz) FDB 638 ; Note G (1567.968 Hz) FDB 568 ; Note A (1760.000 Hz) FDB 506 ; Note B (1975.520 Hz) ; FDB 478 ; Note C (2092.992 Hz) Octave7 FDB 426 ; Note D (2349.312 Hz) FDB 379 ; Note E (2636.992 Hz) FDB 358 ; Note F (2793.856 Hz) FDB 319 ; Note G (3135.936 Hz) FDB 284 ; Note A (3520.000 Hz) FDB 253 ; Note B (3951.040 Hz) ; FDB 239 ; Note C (4185.984 Hz) Octave8 FDB 213 ; Note D (4698.624 Hz) FDB 190 ; Note E (5273.984 Hz) FDB 179 ; Note F (5587.712 Hz) FDB 161 ; Note G (6217.872 Hz) FDB 142 ; Note A (7040.000 Hz) FDB 127 ; Note B (7902.080 Hz) ;/********************/; ;/* Note Delay Table */; ;/********************/; ; TAB_DELAY FDB 0,255,190,127,94 FDB 63,47,31,23,16 ORG $FFE0 FDB OC5_INT ; OC5 Vector FDB OC4_INT ; OC4 Vector FDB OC3_INT ; OC3 Vector FDB OC2_INT ; OC2 Vector FDB OC1_INT ; OC1 Vector ORG $FFF0 FDB RTI_INT ; RTI Vector ORG $FFFE ; Reset Vector FDB MAIN ENDส่วนสำหรับเขียนเพื่อทำงานกับมอนิเตอร์ของอีทีที จะเป็นดังนี้
;/**********************************/; ;/* Demo Program For OutputCompare */; ;/* Timer Run Interrupt Mode */; ;/* Used OCX : Generate Music Note */; ;/* Hardware : ET-CP68HC11 Ver 2.0 */; ;/* Complier : AS11NEW.EXE (V1.03) */; ;/**********************************/; ; ;/***************************/; ;/*** I/O Register Equate ***/; ;/***************************/; ; IOREGS EQU $1000 ; Start of I/O Register PORTA EQU IOREGS+$00 ; I/O Port-A PIOC EQU IOREGS+$02 ; I/O Control Register PORTC EQU IOREGS+$03 ; I/O Port-C PORTB EQU IOREGS+$04 ; I/O Port-B PORTCL EQU IOREGS+$05 ; I/O Control Register DDRC EQU IOREGS+$07 ; Data Direction Register-C PORTD EQU IOREGS+$08 ; I/O Port-D DDRD EQU IOREGS+$09 ; Data Direction Register-D PORTE EQU IOREGS+$0A ; I/O Port-E CFORC EQU IOREGS+$0B ; Force Output Compare OC1M EQU IOREGS+$0C ; OC1 Mask Bits OC1D EQU IOREGS+$0D ; OC1 Data Bits?? TCNT EQU IOREGS+$0E ; Timer Count Register TIC1 EQU IOREGS+$10 ; Input Capture #1 TIC2 EQU IOREGS+$12 ; Input Capture #2 TIC3 EQU IOREGS+$14 ; Input Capture #3 TOC1 EQU IOREGS+$16 ; Output Compare #1 TOC2 EQU IOREGS+$18 ; Output Compare #2 TOC3 EQU IOREGS+$1A ; Output Compare #3 TOC4 EQU IOREGS+$1C ; Output Compare #4 TOC5 EQU IOREGS+$1E ; Output Compare #5 TCTL1 EQU IOREGS+$20 ; Timer Control Register #1 TCTL2 EQU IOREGS+$21 ; Timer Control Register #2 TMSK1 EQU IOREGS+$22 ; Timer Mask #1 TFLG1 EQU IOREGS+$23 ; Timer Flags #1 TMSK2 EQU IOREGS+$24 ; Timer Mask #2 TFLG2 EQU IOREGS+$25 ; Timer Flags #2 PACTL EQU IOREGS+$26 ; Pulse Accum Control PACNT EQU IOREGS+$27 ; Pulse Accum Counter SPCR EQU IOREGS+$28 ; SPI Control Register SPSR EQU IOREGS+$29 ; SPI Status Register SPDR EQU IOREGS+$2A ; SPI Data Register BAUD EQU IOREGS+$2B ; Baudrate Register SCCR1 EQU IOREGS+$2C ; SCI Register 1 SCCR2 EQU IOREGS+$2D ; SCI Register 2 SCSR EQU IOREGS+$2E ; SCI Status Register SCDR EQU IOREGS+$2F ; SCI Data Register ADCTL EQU IOREGS+$30 ; A/D Control Register ADR1 EQU IOREGS+$31 ; A/D Result 1 ADR2 EQU IOREGS+$32 ; A/D Result 2 ADR3 EQU IOREGS+$33 ; A/D Result 3 ADR4 EQU IOREGS+$34 ; A/D Result 4 OPTION EQU IOREGS+$39 ; Option Register COPRST EQU IOREGS+$3A ; COP Reset Register PPROG EQU IOREGS+$3B ; EEPROM Programming Register HPRIO EQU IOREGS+$3C ; Highest-Priority Register INIT EQU IOREGS+$3D ; Memory Map Initialization TEST1 EQU IOREGS+$3E ; Test Register 1 CONFIG EQU IOREGS+$3F ; System Configuration ; ;/* Interrupt Vector For Debugger 68HC11 V2.0 */; OC5_VEC EQU $20D3 OC4_VEC EQU $20D6 OC3_VEC EQU $20D9 OC2_VEC EQU $20DC OC1_VEC EQU $20DF RTI_VEC EQU $20EB ORG $2200 ; Start of Debugger User Area MAIN LDAB #$7E ; Jump-EXT Opcode STAB OC5_VEC ; 1st Byte Debugger Vector STAB OC4_VEC STAB OC3_VEC STAB OC2_VEC STAB OC1_VEC STAB RTI_VEC LDX #OC5_INT ; Address Service Routine STX OC5_VEC+1 ; 2nd,3rd Byte Debugger Vector LDX #OC4_INT STX OC4_VEC+1 LDX #OC3_INT STX OC3_VEC+1 LDX #OC2_INT STX OC2_VEC+1 LDX #OC1_INT STX OC1_VEC+1 LDX #RTI_INT STX RTI_VEC+1 ; LDD #0 ; SONG_CNT = 0 STD SONG_CNT LDAB TMSK2 ORAB #%01000000 STAB TMSK2 ; Enable RTI Interrupt LDAB #%01000000 STAB TFLG2 ; Clear RTIF Flag ; LDAB TMSK1 ORAB #%11111000 STAB TMSK1 ; Enable OC1I-OC5I LDAB #%11111000 STAB TFLG1 ; Clear OC1F-OC5F LDAB #%00000000 STAB TCTL1 ; Disconnect OC2-OC5 Pin LDAB PACTL ORAB #%10000000 STAB PACTL ; PA7 = Output CLI ; Enable Global Interrupt ; NEW_SONG LDAB #%11111000 STAB TFLG1 ; Clear OC1F-OC5F LDD #0 ; Start 1st Music Note STD SONG_PTR ; LDAB #8 STAB NOTE_CNT ; 8-Note on OC5(PA3) ; SONG_OC5 JSR GET_NOTE ; Get Note & Delay LDD FREQ_CNT STD FREQ_OC5 LDD FREQ_OC5 ; FREQ_OC5 = 0 ? CPD #0 BNE ENA_OC5 JMP DIS_OC5 ; ENA_OC5 LDD TCNT ADDD FREQ_OC5 STD TOC5 LDAB TCTL1 ORAB #%00000001 STAB TCTL1 ; Toggle OC5 Pin JMP CHK_OC5 ; DIS_OC5 CLRB ; No Active Output STAB TCTL1 ; Disconnect OC2-5 STAB OC1M ; Disconnect PA7 STAB OC1D ; PA7 = 0 ; CHK_OC5 LDD SONG_CNT ; Loop Until SONG_CNT = 0 CPD #0 BNE CHK_OC5 DEC NOTE_CNT BNE SONG_OC5 ; LDAB #8 STAB NOTE_CNT ; 8-Note on OC4(PA4) ; SONG_OC4 JSR GET_NOTE ; Get Note & Delay LDD FREQ_CNT STD FREQ_OC4 LDD FREQ_OC4 ; FREQ_OC4 = 0 ? CPD #0 BNE ENA_OC4 JMP DIS_OC4 ; ENA_OC4 LDD TCNT ADDD FREQ_OC4 STD TOC4 LDAB TCTL1 ORAB #%00000100 STAB TCTL1 ; Toggle OC4 Pin JMP CHK_OC4 ; DIS_OC4 CLRB ; No Active Output STAB TCTL1 ; Disconnect OC2-5 STAB OC1M ; Disconnect PA7 STAB OC1D ; PA7 = 0 ; CHK_OC4 LDD SONG_CNT ; Loop Until SONG_CNT = 0 CPD #0 BNE CHK_OC4 DEC NOTE_CNT BNE SONG_OC4 ; LDAB #8 STAB NOTE_CNT ; 8-Note on OC3(PA5) ; SONG_OC3 JSR GET_NOTE ; Get Note & Delay LDD FREQ_CNT STD FREQ_OC3 LDD FREQ_OC3 ; FREQ_OC3 = 0 ? CPD #0 BNE ENA_OC3 JMP DIS_OC3 ; ENA_OC3 LDD TCNT ADDD FREQ_OC3 STD TOC3 LDAB TCTL1 ORAB #%00010000 STAB TCTL1 ; Toggle OC3 Pin JMP CHK_OC3 ; DIS_OC3 CLRB ; No Active Output STAB TCTL1 ; Disconnect OC2-5 STAB OC1M ; Disconnect PA7 STAB OC1D ; PA7 = 0 ; CHK_OC3 LDD SONG_CNT ; Loop Until SONG_CNT = 0 CPD #0 BNE CHK_OC3 DEC NOTE_CNT BNE SONG_OC3 ; LDAB #8 STAB NOTE_CNT ; 8-Note on OC2(PA6) ; SONG_OC2 JSR GET_NOTE ; Get Note & Delay LDD FREQ_CNT STD FREQ_OC2 LDD FREQ_OC2 ; FREQ_OC2 = 0 ? CPD #0 BNE ENA_OC2 JMP DIS_OC2 ; ENA_OC2 LDD TCNT ADDD FREQ_OC2 STD TOC2 LDAB TCTL1 ORAB #%01000000 STAB TCTL1 ; Toggle OC2 Pin JMP CHK_OC2 ; DIS_OC2 CLRB ; No Active Output STAB TCTL1 ; Disconnect OC2-5 STAB OC1M ; Disconnect PA7 STAB OC1D ; PA7 = 0 ; CHK_OC2 LDD SONG_CNT ; Loop Until SONG_CNT = 0 CPD #0 BNE CHK_OC2 DEC NOTE_CNT BNE SONG_OC2 ; LDAB #8 STAB NOTE_CNT ; 8-Note on OC1(PA7) ; SONG_OC1 JSR GET_NOTE ; Get Note & Delay LDD FREQ_CNT STD FREQ_OC1 LDD FREQ_OC1 ; FREQ_OC1 = 0 ? CPD #0 BNE ENA_OC1 JMP DIS_OC1 ; ENA_OC1 LDD TCNT ADDD FREQ_OC1 STD TOC1 LDAB #%10000000 STAB OC1M ; OC1 Active PA7 STAB OC1_STAS ; Save Status Output STAB OC1D ; PA7 = 1 JMP CHK_OC1 ; DIS_OC1 CLRB ; No Active Output STAB TCTL1 ; Disconnect OC2-5 STAB OC1M ; Disconnect PA7 STAB OC1D ; PA7 = 0 ; CHK_OC1 LDD SONG_CNT ; Loop Until SONG_CNT = 0 CPD #0 BNE CHK_OC1 DEC NOTE_CNT BNE SONG_OC1 JMP NEW_SONG ;/*********************************/; ;/* Get Frequency & Delay of Note */; ;/* Input : SONG_PTR(Note Table) */; ;/* Output : FREQ_CNT(Note Freq.) */; ;/* : SONG_CNT(Note Delay) */; ;/* : SONG_PTR=SONG_PTR+2 */; ;/*********************************/; ; GET_NOTE LDD SONG_PTR ; Get Note Pointer ADDD #TAB_SONG PSHB PSHA PULX LDAA #2 LDAB 0,X ; B = Note MUL ADDD #TAB_NOTE PSHB PSHA PULX ; X = Note Pointer LDD 0,X STD FREQ_CNT ; Save Note Frequency LDD #1 ADDD SONG_PTR STD SONG_PTR ; SONG_PTR = SONG_PTR+1 ; ;/* Get Delay of Note (Long-Time) */; LDD SONG_PTR ; get duration ADDD #TAB_SONG PSHB PSHA PULX LDAA #2 LDAB 0,X ; B = Delay MUL ADDD #TAB_DELAY PSHB PSHA PULX ; X = Delay Pointer LDD 0,X STD SONG_CNT ; Save Note Delay LDD #1 ADDD SONG_PTR STD SONG_PTR ; SONG_PTR = SONG_PTR+1 RTS ;/*****************/; ;/* RTI Interrupt */; ;/*****************/; ; RTI_INT LDD SONG_CNT ; Get Note CPD #0 BHI DEC_NOTE ; If >= 0 Jump (*+5) JMP CLR_FLAG DEC_NOTE LDD SONG_CNT ; SONG_CNT = SONG_CNT-1 SUBD #1 STD SONG_CNT CLR_FLAG LDD #%01000000 ; Clear RTIF flag STAB TFLG2 RTI ;/******************/; ;/* TOC5 Interrupt */; ;/******************/; ; OC5_INT LDD TOC5 ; Read TOC5 ADDD FREQ_OC5 ; TOC5 = TOC5 + FREQ_OC5 STD TOC5 LDD #%00001000 ; Clear OC5F Flag STAB TFLG1 RTI ;/******************/; ;/* TOC4 Interrupt */; ;/******************/; ; OC4_INT LDD TOC4 ; Read TOC4 ADDD FREQ_OC4 ; TOC4 = TOC4 + FREQ_OC4 STD TOC4 LDD #%00010000 ; Clear OC4F Flag STAB TFLG1 RTI ;/******************/; ;/* TOC3 Interrupt */; ;/******************/; ; OC3_INT LDD TOC3 ; Read TOC3 ADDD FREQ_OC3 ; TOC3 = TOC3 + FREQ_OC3 STD TOC3 LDD #%00100000 ; Clear OC3F Flag STAB TFLG1 RTI ;/******************/; ;/* TOC2 Interrupt */; ;/******************/; ; OC2_INT LDD TOC2 ; Read TOC2 ADDD FREQ_OC2 ; TOC2 = TOC2 + FREQ_OC2 STD TOC2 LDD #%01000000 ; Clear OC2F Flag STAB TFLG1 RTI ;/******************/; ;/* TOC1 Interrupt */; ;/******************/; ; OC1_INT LDD TOC1 ; Read TOC1 ADDD FREQ_OC1 ; TOC1 = TOC1 + FREQ_OC1 STD TOC1 LDAB #%10000000 ; Clear OC1F Flag STAB TFLG1 LDAB OC1_STAS ; Toggle PA7 COMB STAB OC1_STAS ANDB #%10000000 STAB OC1D RTI ;/********************/; ;/* Table of Pointer */; ;/* For Note & Delay */; ;/* Song of All Note */; ;/********************/; ; TAB_SONG FCB 00,1,01,5,02,5,03,5 FCB 04,5,05,5,06,5,07,5 FCB 00,1,08,5,09,5,10,5 FCB 11,5,12,5,13,5,14,5 FCB 00,1,15,5,16,5,17,5 FCB 18,5,19,5,20,5,21,5 FCB 00,1,22,5,23,5,24,5 FCB 25,5,26,5,27,5,28,5 FCB 00,1,29,5,30,5,31,5 FCB 32,5,33,5,34,5,35,5 FCB 255 ; End of Music ;/**************************/; ;/* Table of Standard Note */; ;/**************************/; ; TAB_NOTE FDB 0000 ; No Sound ; FDB 3822 ; Note C (261.624 Hz) Octave4 FDB 3405 ; Note D (293.664 Hz) FDB 3034 ; Note E (329.624 Hz) FDB 2863 ; Note F (349.232 Hz) FDB 2551 ; Note G (391.992 Hz) FDB 2273 ; Note A (440.000 Hz) FDB 2025 ; Note B (493.880 Hz) ; FDB 1911 ; Note C (523.248 Hz) Octave5 FDB 1703 ; Note D (587.238 Hz) FDB 1517 ; Note E (659.248 Hz) FDB 1432 ; Note F (698.464 Hz) FDB 1276 ; Note G (783.984 Hz) FDB 1136 ; Note A (880.000 Hz) FDB 1012 ; Note B (987.760 Hz) ; FDB 956 ; Note C (1046.496 Hz) Octave6 FDB 851 ; Note D (1174.656 Hz) FDB 758 ; Note E (1318.496 Hz) FDB 716 ; Note F (1396.928 Hz) FDB 638 ; Note G (1567.968 Hz) FDB 568 ; Note A (1760.000 Hz) FDB 506 ; Note B (1975.520 Hz) ; FDB 478 ; Note C (2092.992 Hz) Octave7 FDB 426 ; Note D (2349.312 Hz) FDB 379 ; Note E (2636.992 Hz) FDB 358 ; Note F (2793.856 Hz) FDB 319 ; Note G (3135.936 Hz) FDB 284 ; Note A (3520.000 Hz) FDB 253 ; Note B (3951.040 Hz) ; FDB 239 ; Note C (4185.984 Hz) Octave8 FDB 213 ; Note D (4698.624 Hz) FDB 190 ; Note E (5273.984 Hz) FDB 179 ; Note F (5587.712 Hz) FDB 161 ; Note G (6217.872 Hz) FDB 142 ; Note A (7040.000 Hz) FDB 127 ; Note B (7902.080 Hz) ;/********************/; ;/* Note Delay Table */; ;/********************/; ; TAB_DELAY FDB 0,255,190,127,94 FDB 63,47,31,23,16 ;/* Variable Buffer in EXT-RAM */; ; SONG_PTR RMB 2 ; Music Note Pointer SONG_CNT RMB 2 ; Song Delay Count NOTE_CNT RMB 1 ; Note/Output Count OC1_STAS RMB 1 ; PA7 Status ; FREQ_CNT RMB 2 ; Timer 1/2 Cycle Count FREQ_OC1 RMB 2 FREQ_OC2 RMB 2 FREQ_OC3 RMB 2 FREQ_OC4 RMB 2 FREQ_OC5 RMB 2 ENDสามารถ download ไฟล์ตัวอย่างของบอร์ด พร้อม assembler ได้เลยครับ