; ; ANY-LICENSE V1.0 ; ---------------- ; ; You can use these files under any license approved by the ; Open Source Initiative, preferrably one of the popular licenses, ; as long as the license you choose is compatible to the ; dependencies of these files. ; ; See http://www.opensource.org/licenses/ for a list of ; approved licenses. ; ; Author: Martin Furter ; Project: Tins AVR Lib ; Repository: http://repos.borg.ch/projects/tins_avr_lib/trunk ; Copyright: 2007,2009,2013,2014,2015 ; ; ; ANY-LICENSE V1.0 ; ---------------- ; ; You can use these files under any license approved by the ; Open Source Initiative, preferrably one of the popular licenses, ; as long as the license you choose is compatible to the ; dependencies of these files. ; ; See http://www.opensource.org/licenses/ for a list of ; approved licenses. ; ; Author: Martin Furter ; Project: Tins AVR Lib ; Repository: http://repos.borg.ch/projects/tins_avr_lib/trunk ; Copyright: 2007,2009,2013,2014,2015 ; ; ; ANY-LICENSE V1.0 ; ---------------- ; ; You can use these files under any license approved by the ; Open Source Initiative, preferrably one of the popular licenses, ; as long as the license you choose is compatible to the ; dependencies of these files. ; ; See http://www.opensource.org/licenses/ for a list of ; approved licenses. ; ; Author: Martin Furter ; Project: ; Modified: 2015 ; ; ; Timer 1 overflow interrupt routine for updating OCR registers. ; ; AVR model: atmega 48/88/168 ; ; Global variables: ; /* Values for the OCR registers. */ ; extern volatile unsigned char next_value_ocr0a; ; extern volatile unsigned char next_value_ocr0b; ; extern volatile unsigned char next_value_ocr1a; ; extern volatile unsigned char next_value_ocr1b; ; extern volatile unsigned char next_value_ocr2a; ; extern volatile unsigned char next_value_ocr2b; ; /* A counter which is decreased in the interrupt routine. */ ; extern volatile unsigned char next_value_counter; ; /* Set bits to enable button. */ ; extern volatile unsigned char button_mask; ; /* Set bits to make button low active. */ ; extern volatile unsigned char button_low_active; ; /* Debounced value of the buttons. */ ; extern volatile unsigned char button_value; ; /* Bits set when a button is pressed (edge). */ ; extern volatile unsigned char button_pressed; ; /* Bits set when a button is released (edge). */ ; extern volatile unsigned char button_released; ; /* Last 4 states of the buttons as read from the I/O pins. */ ; extern volatile unsigned char button_states[4]; ; #include ; timer 1 overflow interrupt (TIMER1_OVF_vect) .global __vector_13 .type __vector_13, @function __vector_13: ; interrupt execution cycles: 4 + 0..3 = upto 7 ; save registers push r16 ; cycles: 1 push r17 ; cycles: 1 push r18 ; cycles: 1 push r19 ; cycles: 1 in r16, _SFR_IO_ADDR(SREG) ; cycles: 1 push r16 ; cycles: 1 ; load counter and compare to one lds r18, next_value_counter ; cycles: 2 cpi r18, 1 ; cycles: 1 brne .CNTRDEC ; cycles: 1/2 ; zero register for high bytes clr r17 ; cycles: 1 ; copy OCR values lds r16, next_value_ocr0a ; cycles: 2 out _SFR_IO_ADDR(OCR0A), r16 ; cycles: 1 lds r16, next_value_ocr0b ; cycles: 2 out _SFR_IO_ADDR(OCR0B), r16 ; cycles: 1 lds r16, next_value_ocr1a ; cycles: 2 sts _SFR_MEM_ADDR(OCR1AH), r17 ; cycles: 2 sts _SFR_MEM_ADDR(OCR1AL), r16 ; cycles: 2 lds r16, next_value_ocr1b ; cycles: 2 sts _SFR_MEM_ADDR(OCR1BH), r17 ; cycles: 2 sts _SFR_MEM_ADDR(OCR1BL), r16 ; cycles: 2 lds r16, next_value_ocr2a ; cycles: 2 sts _SFR_MEM_ADDR(OCR2A), r16 ; cycles: 2 lds r16, next_value_ocr2b ; cycles: 2 sts _SFR_MEM_ADDR(OCR2B), r16 ; cycles: 2 ; total: 12*2 + 2*1 = 26 ; total cycles until here must be less than 64 because the overflow ; interrupt is executed at TOP and OCR's are updated at BOTTOM ; total cycles: 7 + 10 + 26 = 43 ; compare again to set the flags cpi r18, 1 .CNTRDEC: ; already zero? if yes do not decrease brlo .CNTRSTORE dec r18 .CNTRSTORE: sts next_value_counter, r18 ; check buttons on port C (0-5) and D (4,7) ; init 'and' and 'or' registers, use mask for and's lds r16, button_mask clr r17 ; sum up states and shift them lds r18, button_states+3 and r16, r18 or r17, r18 lds r18, button_states+2 sts button_states+3, r18 and r16, r18 or r17, r18 lds r18, button_states+1 sts button_states+2, r18 and r16, r18 or r17, r18 lds r18, button_states+0 sts button_states+1, r18 and r16, r18 or r17, r18 ; read ports, sum up, optinally invert, store in states ; ++++++ how to make this configurable? ; read port D: get PD4 and PD7 in r18, _SFR_IO_ADDR(PIND) ; move bit 4 to bit 6 andi r18, 0x90 mov r19, r18 lsl r19 lsl r19 or r18, r19 andi r19, 0xC0 ; read PORT C: add PD0-5 to the bits from port D in r19, _SFR_IO_ADDR(PINC) andi r19, 0x3F or r18, r19 ; invert low active inputs lds r19, button_low_active eor r18, r19 ; apply mask lds r19, button_mask and r18, r19 ; store it sts button_states+0, r18 and r16, r18 or r17, r18 ; set/clear bits of button value lds r18, button_value mov r19, r18 or r18, r16 and r18, r17 sts button_value, r18 ; new value is in r18, old is in r19 ; put difference (xor) into r17 mov r17, r18 eor r17, r19 ; bits set in new value and difference -> pressed and r18, r17 sts button_pressed, r18 ; bits set in old value and difference -> released and r19, r17 sts button_released, r19 ; restore registers pop r16 out _SFR_IO_ADDR(SREG), r16 pop r19 pop r18 pop r17 pop r16 ; done reti ; void init_timer_overflow( uint8_t mask, uint8_t low_active ) ; r24 paramter 1: bits set in mask enable buttons ; r22 paramter 2: bits set in low_active invert buttons ; .global init_timer_overflow .type init_timer_overflow, @function init_timer_overflow: ; save registers push r16 ; initialize the following registers to zero sts button_mask, r24 sts button_low_active, r22 clr r16 sts button_value, r16 sts button_pressed, r16 sts button_released, r16 sts next_value_counter, r16 ; initialize the following registers to 0xFF dec r16 sts button_states, r16 sts next_value_ocr0a, r16 sts next_value_ocr0b, r16 sts next_value_ocr1a, r16 sts next_value_ocr1b, r16 sts next_value_ocr2a, r16 sts next_value_ocr2b, r16 ; restore registers pop r16 ret ; variables .comm next_value_ocr0a,1,1 .comm next_value_ocr0b,1,1 .comm next_value_ocr1a,1,1 .comm next_value_ocr1b,1,1 .comm next_value_ocr2a,1,1 .comm next_value_ocr2b,1,1 .comm next_value_counter,1,1 .comm button_states,4,1 .comm button_mask,1,1 .comm button_low_active,1,1 .comm button_value,1,1 .comm button_pressed,1,1 .comm button_released,1,1