.file "main.S" #include #define PC r0 #define SP r1 #define SR r2 ;; --- register usage -------------------------------- ;; r4: synchronization between main loop and isr ;; bit0 signals byte done from isr ;; r5: data byte to be handled by isr ;; r6: bit-counter, only used within isr ;; r7: screen data start/next pointer ;; r8: screen data end pointer ;; r9: next screen data byte, prepared in mainloop #define SIGNAL_INIT_VALUE 0x00 #define SIGNAL_BYTE_DONE 0x01 #define SIGNAL_ISR_ENABLE 0x02 #define SIGNAL_REGISTER r4 #define DATA_BYTE_REGISTER r5 #define NEXT_DATA_BYTE_REGISTER r9 #define DATA_NEXT_ADDRESS_REGISTER r7 #define DATA_LAST_ADDRESS_REGISTER r8 #define BIT_COUNTER_REGISTER r6 #define BIT_COUNTER_INIT_VALUE 0x01 ;; --------------------------------------------------- .section ".rodata","a" screendata: .byte 0b00000001 .byte 0b00000011 .byte 0b00000111 .byte 0b00001111 screendataend: .byte 0xff red: colors1: .byte 0b01001111 colors2: .byte 0b01000111 colors3: .byte 0b01000011 .byte 0 blue: .byte 0b11001111 .byte 0b11000111 .byte 0b11000011 .byte 0 green: .byte 0b10001111 .byte 0b10000111 .byte 0b10000011 .byte 0 ;; .text is the name of the section, it is a hint for the linker to ;; allocate the section ;; ax: a means allocatable by linker, x means executable ;; @progbits is a hint for the linker to allocate this section into ;; program memory (flash) .section ".text","ax",@progbits _start: ;; disable watchdog mov.w #WDTPW|WDTHOLD, &WDTCTL ;; configure clock system to the highest frequency mov.b #DCO0|DCO1|DCO2, &DCOCTL mov.b #XT2OFF|RSEL0|RSEL1|RSEL2|RSEL3, &BCSCTL1 mov.b #0, &BCSCTL2 mov.b #0, &BCSCTL3 ;; initialize stack pointer with value from linker mov.w #__stack, SP init: ;; configuration of GPIO Ports mov.b #BIT0|BIT1|BIT2, &P1DIR mov.b #BIT1|BIT4, &P2DIR mov.b #BIT1|BIT4, &P2SEL ;; timer configuration ;; configure and stop timer ;; cycle time is 56.25ns mov.w #ID_0|MC_0|TACLR|TASSEL_2, &TA1CTL ;; 2.0us mov.w #45, &TA1CCR0 ;; a bit less mov.w #10, &TA1CCR1 mov.w #22, &TA1CCR2 ;; configure output mode for TA0.1 mov.w #CCIE, &TA1CCTL0 mov.w #OUTMOD_7, &TA1CCTL1 mov.w #OUTMOD_7, &TA1CCTL2 ;; initialize bit-counter for isr mov.b #BIT_COUNTER_INIT_VALUE, BIT_COUNTER_REGISTER ;; initialize isr-sync register mov.b #SIGNAL_INIT_VALUE, SIGNAL_REGISTER ;; screen data start/next into DATA_NEXT_ADDRESS_REGISTER mov.w #screendata, DATA_NEXT_ADDRESS_REGISTER ;; screen data end into DATA_LAST_ADDRESS_REGISTER mov.w #screendataend, DATA_LAST_ADDRESS_REGISTER ;; load first screen data value into DATA_BYTE_REGISTER mov.b @DATA_NEXT_ADDRESS_REGISTER, DATA_BYTE_REGISTER inc.w DATA_NEXT_ADDRESS_REGISTER ;; start timer in up mode bis.w #MC0, &TA1CTL ;; enable interrupts eint mainloop: ;; prepare next byte to handle by isr ;; first, check whether we are already at the end of screen data cmp.w DATA_NEXT_ADDRESS_REGISTER, DATA_LAST_ADDRESS_REGISTER jnz mainloop_prepare_next_byte ;; in that case rollover to the start again mov.w #screendata, DATA_NEXT_ADDRESS_REGISTER mainloop_prepare_next_byte: ;; load the byte from the screen data next pointer mov.b @DATA_NEXT_ADDRESS_REGISTER, NEXT_DATA_BYTE_REGISTER ;; and increase the pointer inc.w DATA_NEXT_ADDRESS_REGISTER mainloop_wait_for_isr: ;; check bit0 in sync register, wait for the signal from ;; the isr bit #SIGNAL_BYTE_DONE, SIGNAL_REGISTER jz mainloop_wait_for_isr ;; load data mov.b NEXT_DATA_BYTE_REGISTER, DATA_BYTE_REGISTER ;; clear the signal bic #SIGNAL_BYTE_DONE, SIGNAL_REGISTER ;; mark the cycle bis #BIT2, &P1OUT bic #BIT2, &P1OUT ;; continue jmp mainloop ; --- timer isr --- ;; r6: exclusively used by isr as bit-counter timer1_a0_isr: ;; func begin marker bis #BIT0, &P1OUT ;; check isr idle bit bit #SIGNAL_ISR_ENABLE, SIGNAL_REGISTER jnz timer1_a0_isr_exit ;; shift msb of data register r5 into carry flag and set or reset P1.1 accordingly rla.b DATA_BYTE_REGISTER jnc timer1_a0_isr_false_bit bis #BIT1, &P1OUT jmp timer1_a0_isr_end timer1_a0_isr_false_bit: bic #BIT1, &P1OUT ;; shift bit-counter, after eight shifts signal byte done and reset bit-counter timer1_a0_isr_end: rla.b BIT_COUNTER_REGISTER jnc timer1_a0_isr_exit ;; reset bit-counter mov.b #BIT_COUNTER_INIT_VALUE, BIT_COUNTER_REGISTER ;; signal byte done bis #SIGNAL_BYTE_DONE, SIGNAL_REGISTER timer1_a0_isr_exit: ;; func end marker bic #BIT0, &P1OUT reti ;; .resetvec comes from linker .section ".resetvec","ax",@progbits .word _start .end