Upload files to "/"
This commit is contained in:
commit
008f12d166
114
README.md
Normal file
114
README.md
Normal file
@ -0,0 +1,114 @@
|
||||
# AtTiny26L-8pi_counter
|
||||
|
||||
Hand held device with display to count button presses. It uses buttons to detect user input one +1 and one for -1.
|
||||
Made with of the shelf components.
|
||||
|
||||
For me this is a exploration in programming ASM assembly as I had never done this before.
|
||||
Also the designing was interesting.
|
||||
|
||||
## Components
|
||||
|
||||
### The ATTiny microcontroller
|
||||
As I had a `ATTiny26L` 8-bit microcontroller laying around I decided to use that. As it already has an onboard clock which is plenty
|
||||
fast enough for this simple project it saved me from connection a XTAL.
|
||||
|
||||
```
|
||||
Ttiny26
|
||||
_____________________________________
|
||||
1 / |20
|
||||
o--|PB0 /OC1A SDA DI MOSI PA0 ADC0|--o
|
||||
2| |19
|
||||
o--|PB1 OC1A DO MISO PA1 ADC1|--o
|
||||
3| |18
|
||||
o--|PB2 /OC1B SCL SCK PA2 ADC2|--o
|
||||
4| |17
|
||||
o--|PB3 OC1B PA3 AREF|--o
|
||||
5| |16
|
||||
o--|VCC GND|--o
|
||||
6| |15
|
||||
o--|GND AVCC|--o
|
||||
7| |14
|
||||
o--|PB4 XTAL1 ADC7 PA4 ADC3|--o
|
||||
8| |13
|
||||
o--|PB5 XTAL2 ADC8 PA5 ADC4|--o
|
||||
9| |12
|
||||
o--|PB6 T0 INT0 ADC9 PA6 ADC5 AIN0|--o
|
||||
10| |11
|
||||
o--|PB7 RESET ADC10 PA7 ADC6 AIN1|--o
|
||||
|______________________________________|
|
||||
```
|
||||
|
||||
### The shift register
|
||||
As the ATTiny doesn't have enough outputs do drive a 7-segment display we need a shift register. I used a `74HCT595N` as again this what I had on hand.
|
||||
|
||||
```
|
||||
74HCT595N
|
||||
_____________________________________
|
||||
1 / |16
|
||||
o--|Q1 VCC|--o
|
||||
2| |15
|
||||
o--|Q2 Q0|--o
|
||||
3| |14
|
||||
o--|Q3 DS|--o
|
||||
4| |13
|
||||
o--|Q4 ~OE|--o
|
||||
5| |12
|
||||
o--|Q5 STCP|--o
|
||||
6| |11
|
||||
o--|Q6 SHCP|--o
|
||||
7| |10
|
||||
o--|Q7 ~MR|--o
|
||||
8| |9
|
||||
o--|GND Q7S|--o
|
||||
|______________________________________|
|
||||
```
|
||||
|
||||
### Something to read the number
|
||||
A 7-segment display sporting 4 digits is used for outputting the number to the user. I used a `CL5642BH-30` as you guessed it already, was the one I had laying around.
|
||||
|
||||
```
|
||||
CL5642BH-30
|
||||
|
||||
DIG1 A F DIG2 DIG3 B
|
||||
o12 o11 o10 o9 o8 o7
|
||||
| | | | | |
|
||||
----|------|-------|-------|-------|-------|----
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
----|------|-------|-------|-------|-------|----
|
||||
| | | | | |
|
||||
o1 o2 o3 o4 o5 o6
|
||||
E D : C G DIG4
|
||||
|
||||
|
||||
--a--
|
||||
f b
|
||||
--g--
|
||||
e c
|
||||
--d--
|
||||
|
||||
1 = no path to ground
|
||||
0 = path to ground
|
||||
|
||||
| b | a | f | e | d | c | g | ; |
|
||||
MSB | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | LSB
|
||||
1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 |
|
||||
2 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 |
|
||||
3 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 |
|
||||
4 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 1 |
|
||||
5 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
|
||||
6 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
|
||||
7 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 1 |
|
||||
8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
|
||||
9 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
|
||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
|
||||
```
|
||||
|
||||
### Other components
|
||||
Something to mount it all on, for this perfboard was used.
|
||||
As I use a 9v battery a 5 volt regulator was used.
|
||||
2 buttons to read the user input.
|
||||
A 3d printed case.
|
||||
Supporting electronics like condensators and current resisters as pull-up/down and current limiting.
|
||||
629
counter.asm
Normal file
629
counter.asm
Normal file
@ -0,0 +1,629 @@
|
||||
; A digital 4x7 digit display witch keeps track of button presses
|
||||
;
|
||||
; 2020 R. Branten
|
||||
; Written for use with the AtTiny26L-8pi
|
||||
;
|
||||
; Clock set to 1Mhz internal clock
|
||||
|
||||
.NOLIST
|
||||
.include "tn26def.inc"
|
||||
.LIST
|
||||
|
||||
;===============================================================================
|
||||
; REGISTERS
|
||||
;
|
||||
; Register | Name | Function
|
||||
;-----------|-------------------------------------------------------
|
||||
; R1 | arithmicRegisterA | Calculations
|
||||
; R2 | arithmicRegisterB | Calculations
|
||||
; R3 | arithmicRegisterC | Calculations
|
||||
; R4 | arithmicRegisterD | Calculations
|
||||
; R16 | registerA | General purpose
|
||||
; R17 | registerB | General purpose
|
||||
; R18 | buttonPushRegister | Button push detection
|
||||
; R19 | delayRegisterB | Delaying program execution
|
||||
; R20 | digit1 | Storing ones of 7-segment
|
||||
; R21 | digit2 | Storing tens of 7-segment
|
||||
; R22 | digit3 | Storing hundreds of 7-segment
|
||||
; R23 | digit4 | Storing thousands of 7-segment
|
||||
; R24 | counterLow | LSB of counter
|
||||
; R25 | counterHigh | MSB of counter
|
||||
; R10 | incrementButtonStatus | Button debounce state for increment
|
||||
; R11 | decrementButtonStatus | Button debounce state for decrement
|
||||
;
|
||||
.DEF registerA = R16
|
||||
.DEF registerB = R17
|
||||
.DEF arithmicRegisterA = R1
|
||||
.DEF arithmicRegisterB = R2
|
||||
.DEF arithmicRegisterC = R3
|
||||
.DEF arithmicRegisterD = R4
|
||||
.DEF buttonPushRegister = R18
|
||||
.DEF counterHigh = R25
|
||||
.DEF counterLow = R24
|
||||
.DEF delayRegisterA = R18
|
||||
.DEF delayRegisterB = R19
|
||||
.DEF incrementButtonStatus = R10
|
||||
.DEF decrementButtonStatus = R11
|
||||
|
||||
; Digit numbering
|
||||
; +-----+ +-----+ +-----+ +-----+
|
||||
; | | | | | | | |
|
||||
; | 4 | | 3 | | 2 | | 1 |
|
||||
; | R23 | | R22 | | R21 | | R22 |
|
||||
; +-----+ +-----+ +-----+ +-----+
|
||||
;
|
||||
.DEF digit1 = R20
|
||||
.DEF digit2 = R21
|
||||
.DEF digit3 = R22
|
||||
.DEF digit4 = R23
|
||||
|
||||
;===============================================================================
|
||||
; PINS
|
||||
;
|
||||
; Port | Name | Function | Direction | Init
|
||||
;-------|---------------|-------------------------------|-----------|------
|
||||
; PA0 | display4 | Ground fourth segment | OUTPUT | LOW
|
||||
; PA1 | display2 | Ground third segment | OUTPUT | LOW
|
||||
; PA2 | display3 | Ground second segment | OUTPUT | LOW
|
||||
; PA3 | display1 | Ground first segment | OUTPUT | LOW
|
||||
; PB0 | incrementPin | Trigger ISR | INPUT | LOW
|
||||
; PB1 | decrementPin | Trigger ISR | INPUT | LOW
|
||||
; PB4 | latchPin | Latching of shift register | OUTPUT | LOW
|
||||
; PB5 | clockPin | Clock of shift register | OUTPUT | LOW
|
||||
; PB6 | dataPin | Data to shift register | OUTPUT | LOW
|
||||
;
|
||||
; Inputs
|
||||
.EQU incrementPin = PB0 ; PCINT0
|
||||
.EQU decrementPin = PB1 ; PCINT0
|
||||
|
||||
; Outputs
|
||||
.EQU latchPin = PB4 ; pin 07 of the Attiny to pin number 12 of the 74HC595
|
||||
.EQU clockPin = PB5 ; pin 08 of the Attiny to pin number 11 of the 74HC595
|
||||
.EQU dataPin = PB6 ; pin 09 of the Attiny to pin number 14 of the 74HC595
|
||||
.EQU display4 = PA0
|
||||
.EQU display2 = PA1
|
||||
.EQU display3 = PA2
|
||||
.EQU display1 = PA3
|
||||
|
||||
;===============================================================================
|
||||
; CONSTANTS
|
||||
; Segment numbers
|
||||
; +--[1]--+
|
||||
; | |
|
||||
;[2] [3]
|
||||
; | |
|
||||
; +--[4]--+
|
||||
; | |
|
||||
;[5] [6]
|
||||
; | |
|
||||
; +--[7]--+ [8]
|
||||
;
|
||||
|
||||
.EQU displayDigit0 = 0b00000011
|
||||
.EQU displayDigit1 = 0b01111011
|
||||
.EQU displayDigit2 = 0b00100101
|
||||
.EQU displayDigit3 = 0b00110001
|
||||
.EQU displayDigit4 = 0b01011001
|
||||
.EQU displayDigit5 = 0b10010001
|
||||
.EQU displayDigit6 = 0b10000001
|
||||
.EQU displayDigit7 = 0b00111011
|
||||
.EQU displayDigit8 = 0b00000001
|
||||
.EQU displayDigit9 = 0b00010001
|
||||
|
||||
; Button debounce states
|
||||
.EQU BUTTON_IDLE = 0
|
||||
.EQU BUTTON_DEBOUNCE = 1
|
||||
.EQU BUTTON_PRESSED = 2
|
||||
|
||||
;===============================================================================
|
||||
; VECTORS
|
||||
;
|
||||
.CSEG
|
||||
.ORG $0000
|
||||
RJMP RESET ; Hardware Pin and Watchdog Reset
|
||||
RETI ; External Interrupt Request 0
|
||||
RJMP PIN_CHANGE ; Pin Change Interrupt
|
||||
RETI ; Timer/Counter1 Compare Match 1A
|
||||
RETI ; Timer/Counter1 Compare Match 1B
|
||||
RETI ; Timer/Counter1 Overflow
|
||||
RJMP TIM0_OVF ; Timer/Counter0 Overflow
|
||||
RETI ; USI Start
|
||||
RETI ; USI Overflow
|
||||
RETI ; EEPROM Ready
|
||||
RETI ; Analog Comparator
|
||||
RETI ; ADC Conversion Complete
|
||||
|
||||
;===============================================================================
|
||||
; SETUP
|
||||
;
|
||||
RESET:
|
||||
CLI ; Disable interrupts
|
||||
|
||||
LDI registerA, RAMEND
|
||||
OUT SP, registerA ; Set stack pointer, 8 bits on the attiny26
|
||||
|
||||
; Port A, direction
|
||||
LDI registerA, (1<<display4) | (1<<display3) | (1<<display2) | (1<<display1)
|
||||
OUT DDRA, registerA
|
||||
|
||||
; Port A, init status
|
||||
CBI PORTA, display1
|
||||
CBI PORTA, display2
|
||||
CBI PORTA, display3
|
||||
CBI PORTA, display1
|
||||
|
||||
; Port B, direction
|
||||
LDI registerA, (1<<latchPin) | (1<<clockPin) | (1<<dataPin)
|
||||
OUT DDRB, registerA
|
||||
|
||||
; Port B, init status
|
||||
CBI PORTB, latchPin
|
||||
CBI PORTB, clockPin
|
||||
CBI PORTB, dataPin
|
||||
|
||||
; Interrupt PCINT1 enable
|
||||
LDI registerA, (1<<PCIE0)
|
||||
OUT GIMSK, registerA
|
||||
|
||||
; Set counter to zero
|
||||
LDI counterLow, 0
|
||||
LDI counterHigh, 0
|
||||
|
||||
; Initialize button states
|
||||
LDI registerA, BUTTON_IDLE
|
||||
MOV incrementButtonStatus, registerA
|
||||
MOV decrementButtonStatus, registerA
|
||||
|
||||
SEI ; Enable interrupts
|
||||
RJMP main
|
||||
|
||||
|
||||
;===============================================================================
|
||||
; MAIN PROGRAM LOOP
|
||||
;
|
||||
main:
|
||||
RCALL checkButtonRelease ; Check for button releases
|
||||
RCALL setDigits
|
||||
RCALL outputCounter
|
||||
RJMP main
|
||||
|
||||
;===============================================================================
|
||||
; REGULAR SUBROUTINES
|
||||
;
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
; INCREMENT COUNTER
|
||||
;
|
||||
incrementCounter:
|
||||
LDI registerA, HIGH(9999)
|
||||
CP counterHigh, registerA
|
||||
BRLO doIncrement
|
||||
LDI registerA, LOW(9999) ; Above 9984, check lower half
|
||||
CP counterLow, registerA
|
||||
BRSH maximumReached
|
||||
|
||||
doIncrement:
|
||||
ADIW counterHigh:counterLow, 1
|
||||
BRCS maximumReached
|
||||
RET
|
||||
maximumReached:
|
||||
LDI counterLow, LOW(9999) ; Above 65535, fill low bytes
|
||||
LDI counterHigh, HIGH(9999) ; Above 65535, fill high bytes
|
||||
RET
|
||||
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
; DECREMENT COUNTER
|
||||
;
|
||||
decrementCounter:
|
||||
LDI registerA, 0
|
||||
CP registerA, counterHigh
|
||||
BRSH doDecrement
|
||||
CP registerA, counterLow
|
||||
BREQ minimumReached
|
||||
|
||||
doDecrement:
|
||||
SBIW counterHigh:counterLow, 1
|
||||
BRCS minimumReached
|
||||
RET
|
||||
minimumReached:
|
||||
CLR counterLow
|
||||
CLR counterHigh
|
||||
RET
|
||||
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
; GETTING DIGITS FROM COUNTER
|
||||
;
|
||||
setDigits:
|
||||
; Push original counter to stack
|
||||
PUSH counterHigh
|
||||
PUSH counterLow
|
||||
RCALL setThousands
|
||||
RCALL setHundreds
|
||||
RCALL setTens
|
||||
RCALL setOnes
|
||||
; Pop original counter from stack
|
||||
POP counterLow
|
||||
POP counterHigh
|
||||
RET
|
||||
|
||||
setThousands:
|
||||
; Should be above 00000011 11101000 (1000)
|
||||
LDI digit4, 0 ; Default digit 4 to zero
|
||||
LDI registerA, 0b00000011
|
||||
CP counterHigh, registerA
|
||||
BRSH thousandStart ; More than 1000, start counting
|
||||
RET
|
||||
thousandStart:
|
||||
INC digit4
|
||||
SUBI counterLow, LOW(1000) ; Subtract two low bytes: AL=AL-LOW(420)
|
||||
SBCI counterHigh, HIGH(1000) ; Subtract high bytes and include Carry Flag
|
||||
CP counterHigh, registerA
|
||||
BRSH thousandStart ; More than 100, substract some more
|
||||
RET
|
||||
|
||||
setHundreds:
|
||||
; Should be above 00000000 01100100 (100)
|
||||
LDI digit3, 0 ; Default digit 3 to zero
|
||||
LDI registerA, 0b00000001
|
||||
LDI registerB, 0b01100100
|
||||
CP counterHigh, registerA
|
||||
BRSH hundredStart ; More than 100, start counting
|
||||
CP counterLow, registerB
|
||||
BRSH hundredStart ; More than 100, start counting
|
||||
RET
|
||||
hundredStart:
|
||||
INC digit3
|
||||
SBIW counterHigh:counterLow, 50
|
||||
SBIW counterHigh:counterLow, 50
|
||||
LDI registerA, 0b00000001
|
||||
CP counterHigh, registerA
|
||||
BRSH hundredStart ; More than 100, substract some more
|
||||
CP counterLow, registerB
|
||||
BRSH hundredStart ; More than 100, substract some more
|
||||
RET
|
||||
|
||||
setTens:
|
||||
; Should be above 00000000 00001010 (10)
|
||||
LDI digit2, 0 ; Default digit 4 to zero
|
||||
LDI registerA, 0b00001010
|
||||
CP counterLow, registerA
|
||||
BRSH tenStart ; More than 10, start counting
|
||||
RET
|
||||
tenStart:
|
||||
INC digit2
|
||||
SBCI counterLow, 10
|
||||
CP counterLow, registerA
|
||||
BRSH tenStart ; More than 10, substract some more
|
||||
RET
|
||||
|
||||
setOnes:
|
||||
; Should be above 00000000 00000001 (1)
|
||||
LDI digit1, 0
|
||||
LDI registerA, 0b00000001
|
||||
CP counterLow, registerA
|
||||
BRSH oneStart
|
||||
RET
|
||||
oneStart:
|
||||
INC digit1
|
||||
DEC counterLow
|
||||
CP counterLow, registerA
|
||||
BRSH oneStart ; More then 1, substract some more
|
||||
RET
|
||||
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
; DRIVING SEGMENT DISPLAY
|
||||
;
|
||||
outputCounter:
|
||||
CLI ; Disable interrupts
|
||||
; drive digit 1 [X][ ][ ][ ]
|
||||
MOV registerA, digit4
|
||||
RCALL getShiftValue ; Get value to be shifted out
|
||||
MOV arithmicRegisterA, registerB
|
||||
LDI registerB, (1<<display1)
|
||||
RCALL driveDisplay
|
||||
|
||||
; drive digit 2 [ ][X][ ][ ]
|
||||
MOV registerA, digit3
|
||||
RCALL getShiftValue ; Get value to be shifted out
|
||||
MOV arithmicRegisterA, registerB
|
||||
LDI registerB, (1<<display2)
|
||||
RCALL driveDisplay
|
||||
|
||||
; drive digit 3 [ ][ ][X][ ]
|
||||
MOV registerA, digit2
|
||||
RCALL getShiftValue ; Get value to be shifted out
|
||||
MOV arithmicRegisterA, registerB
|
||||
LDI registerB, (1<<display3)
|
||||
RCALL driveDisplay
|
||||
|
||||
; drive digit 4 [ ][ ][ ][X]
|
||||
MOV registerA, digit1
|
||||
RCALL getShiftValue ; Get value to be shifted out
|
||||
MOV arithmicRegisterA, registerB
|
||||
LDI registerB, (1<<display4)
|
||||
RCALL driveDisplay
|
||||
|
||||
SEI ; Enable interrupts
|
||||
|
||||
RET
|
||||
|
||||
driveDisplay:
|
||||
; Shift in bits
|
||||
RCALL shiftStart
|
||||
; Set correct display pin high, see registerB (display(n))
|
||||
OUT PORTA, registerB
|
||||
NOP ; Wait
|
||||
NOP ; Wait
|
||||
RCALL delay
|
||||
; Stop driving display pin
|
||||
EOR registerB, registerB
|
||||
OUT PORTA, registerB
|
||||
RET
|
||||
|
||||
shiftStart:
|
||||
; Repeat shift 8 times
|
||||
LDI registerA, 8
|
||||
MOV arithmicRegisterB, registerA
|
||||
LDI registerA, 0
|
||||
shiftIn:
|
||||
; Logic shift left to get value to be shifted in SREG 'C' flag
|
||||
LSL arithmicRegisterA
|
||||
BRCS shiftHigh
|
||||
CBI PORTB, dataPin
|
||||
RJMP doShift
|
||||
shiftHigh:
|
||||
SBI PORTB, dataPin
|
||||
doShift:
|
||||
; Cycle clock
|
||||
SBI PORTB, clockPin
|
||||
NOP
|
||||
NOP
|
||||
CBI PORTB, clockPin
|
||||
; End if all shifted out
|
||||
DEC arithmicRegisterB
|
||||
CP arithmicRegisterB, registerA
|
||||
BRNE shiftIn
|
||||
; Toggle latch
|
||||
SBI PORTB, latchPin
|
||||
NOP
|
||||
NOP
|
||||
CBI PORTB, latchPin
|
||||
RET
|
||||
|
||||
getShiftValue:
|
||||
; Set data to be shifted out
|
||||
; The digit should be loaded in registerA
|
||||
LDI registerB, 0
|
||||
CP registerA, registerB
|
||||
BRNE shiftValue_1
|
||||
LDI registerB, displayDigit0 ; Set shift bits to 0
|
||||
RET
|
||||
shiftValue_1:
|
||||
INC registerB
|
||||
CP registerA, registerB
|
||||
BRNE shiftValue_2
|
||||
LDI registerB, displayDigit1 ; Set shift bits to 1
|
||||
RET
|
||||
shiftValue_2:
|
||||
INC registerB
|
||||
CP registerA, registerB
|
||||
BRNE shiftValue_3
|
||||
LDI registerB, displayDigit2 ; Set shift bits to 2
|
||||
RET
|
||||
shiftValue_3:
|
||||
INC registerB
|
||||
CP registerA, registerB
|
||||
BRNE shiftValue_4
|
||||
LDI registerB, displayDigit3 ; Set shift bits to 3
|
||||
RET
|
||||
shiftValue_4:
|
||||
INC registerB
|
||||
CP registerA, registerB
|
||||
BRNE shiftValue_5
|
||||
LDI registerB, displayDigit4 ; Set shift bits to 4
|
||||
RET
|
||||
shiftValue_5:
|
||||
INC registerB
|
||||
CP registerA, registerB
|
||||
BRNE shiftValue_6
|
||||
LDI registerB, displayDigit5 ; Set shift bits to 5
|
||||
RET
|
||||
shiftValue_6:
|
||||
INC registerB
|
||||
CP registerA, registerB
|
||||
BRNE shiftValue_7
|
||||
LDI registerB, displayDigit6 ; Set shift bits to 6
|
||||
RET
|
||||
shiftValue_7:
|
||||
INC registerB
|
||||
CP registerA, registerB
|
||||
BRNE shiftValue_8
|
||||
LDI registerB, displayDigit7 ; Set shift bits to 7
|
||||
RET
|
||||
shiftValue_8:
|
||||
INC registerB
|
||||
CP registerA, registerB
|
||||
BRNE shiftValue_9
|
||||
LDI registerB, displayDigit8 ; Set shift bits to 8
|
||||
RET
|
||||
shiftValue_9:
|
||||
LDI registerB, displayDigit9 ; Set shift bits to 9
|
||||
RET
|
||||
|
||||
delay:
|
||||
LDI delayRegisterA, 255
|
||||
LDI delayRegisterB, 0
|
||||
delayStart:
|
||||
DEC delayRegisterA
|
||||
CP delayRegisterA, delayRegisterB
|
||||
BRNE delayStart
|
||||
RET
|
||||
|
||||
setTimer:
|
||||
; Use the 8-bit timer0
|
||||
; We want to wait about 1.6ms for faster button response
|
||||
; Using prescaler of 64 gives about 1.6ms which is much faster
|
||||
LDI registerA, 0b00000011 ; CS01=1, CS00=1 for prescaler /64
|
||||
OUT TCCR0, registerA ; Set prescaler to /64
|
||||
LDI registerA, (1<<TOV0) ; Load timer overflow flag
|
||||
OUT TIFR, registerA ; Reset by writing a 1
|
||||
LDI registerA, (1<<TOIE0) ; Load overflow interrupt flag for timer 0
|
||||
OUT TIMSK, registerA ; Enable overflow interrupt flag for timer 0
|
||||
RET
|
||||
|
||||
;===============================================================================
|
||||
; ISR SUBROUTINES
|
||||
;
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
; CHECK BUTTON RELEASE
|
||||
; This routine should be called periodically to detect button releases
|
||||
;
|
||||
checkButtonRelease:
|
||||
; Check increment button release
|
||||
LDI registerA, BUTTON_PRESSED
|
||||
CP incrementButtonStatus, registerA
|
||||
BRNE checkDecrementRelease ; Not pressed, check decrement
|
||||
|
||||
IN registerA, PINB ; Read pin states
|
||||
LDI registerB, (1<<incrementPin)
|
||||
AND registerA, registerB ; Check if increment button is still pressed
|
||||
CP registerA, registerB
|
||||
BRNE incrementReleased ; Button released
|
||||
|
||||
RJMP checkDecrementRelease ; Still pressed, check decrement
|
||||
|
||||
incrementReleased:
|
||||
LDI registerA, BUTTON_IDLE
|
||||
MOV incrementButtonStatus, registerA ; Reset to idle state
|
||||
|
||||
checkDecrementRelease:
|
||||
LDI registerA, BUTTON_PRESSED
|
||||
CP decrementButtonStatus, registerA
|
||||
BRNE releaseExit ; Not pressed, exit
|
||||
|
||||
IN registerA, PINB ; Read pin states
|
||||
LDI registerB, (1<<decrementPin)
|
||||
AND registerA, registerB ; Check if decrement button is still pressed
|
||||
CP registerA, registerB
|
||||
BRNE decrementReleased ; Button released
|
||||
|
||||
RJMP releaseExit ; Still pressed, exit
|
||||
|
||||
decrementReleased:
|
||||
LDI registerA, BUTTON_IDLE
|
||||
MOV decrementButtonStatus, registerA ; Reset to idle state
|
||||
|
||||
releaseExit:
|
||||
RET
|
||||
|
||||
;
|
||||
PIN_CHANGE:
|
||||
CLI ; Disable interrupt
|
||||
; Push registers on stack
|
||||
PUSH registerA
|
||||
PUSH registerB
|
||||
|
||||
; Check which button caused the interrupt
|
||||
IN registerA, PINB ; Read current pin states
|
||||
LDI registerB, (1<<incrementPin)
|
||||
AND registerA, registerB ; Check increment button
|
||||
CP registerA, registerB
|
||||
BRNE checkDecrementPin ; Not increment, check decrement
|
||||
|
||||
; Increment button was pressed
|
||||
LDI registerA, BUTTON_IDLE
|
||||
CP incrementButtonStatus, registerA ; Check if button was idle
|
||||
BRNE pinChangeExit ; Already processing, ignore
|
||||
|
||||
LDI registerA, BUTTON_DEBOUNCE
|
||||
MOV incrementButtonStatus, registerA ; Set to debounce state
|
||||
RCALL setTimer ; Start debounce timer
|
||||
RJMP pinChangeExit
|
||||
|
||||
checkDecrementPin:
|
||||
IN registerA, PINB ; Read current pin states again
|
||||
LDI registerB, (1<<decrementPin)
|
||||
AND registerA, registerB ; Check decrement button
|
||||
CP registerA, registerB
|
||||
BRNE pinChangeExit ; Neither button, exit
|
||||
|
||||
; Decrement button was pressed
|
||||
LDI registerA, BUTTON_IDLE
|
||||
CP decrementButtonStatus, registerA ; Check if button was idle
|
||||
BRNE pinChangeExit ; Already processing, ignore
|
||||
|
||||
LDI registerA, BUTTON_DEBOUNCE
|
||||
MOV decrementButtonStatus, registerA ; Set to debounce state
|
||||
RCALL setTimer ; Start debounce timer
|
||||
|
||||
pinChangeExit:
|
||||
; Pop registers from stack
|
||||
POP registerB
|
||||
POP registerA
|
||||
SEI ; Enable interrupt
|
||||
RETI
|
||||
|
||||
TIM0_OVF:
|
||||
CLI ; Disable interrupt
|
||||
; Push registers on stack
|
||||
PUSH registerA
|
||||
PUSH registerB
|
||||
|
||||
; Clear stop the timer by setting Clock select to 0
|
||||
LDI registerA, 0x000000
|
||||
OUT TCCR0, registerA
|
||||
|
||||
; Check current pin states after debounce period
|
||||
IN registerA, PINB ; Read current pin states
|
||||
|
||||
; Check increment button
|
||||
LDI registerB, BUTTON_DEBOUNCE
|
||||
CP incrementButtonStatus, registerB
|
||||
BRNE checkDecrementTimer ; Not in debounce state, check decrement
|
||||
|
||||
LDI registerB, (1<<incrementPin)
|
||||
AND registerA, registerB ; Check if increment button is still pressed
|
||||
CP registerA, registerB
|
||||
BRNE incrementNotPressed ; Button not pressed, reset state
|
||||
|
||||
; Button is still pressed after debounce, process it
|
||||
LDI registerA, BUTTON_PRESSED
|
||||
MOV incrementButtonStatus, registerA
|
||||
RCALL incrementCounter
|
||||
RJMP timerExit
|
||||
|
||||
incrementNotPressed:
|
||||
LDI registerA, BUTTON_IDLE
|
||||
MOV incrementButtonStatus, registerA ; Reset to idle state
|
||||
|
||||
checkDecrementTimer:
|
||||
LDI registerB, BUTTON_DEBOUNCE
|
||||
CP decrementButtonStatus, registerB
|
||||
BRNE timerExit ; Not in debounce state, exit
|
||||
|
||||
IN registerA, PINB ; Read current pin states again
|
||||
LDI registerB, (1<<decrementPin)
|
||||
AND registerA, registerB ; Check if decrement button is still pressed
|
||||
CP registerA, registerB
|
||||
BRNE decrementNotPressed ; Button not pressed, reset state
|
||||
|
||||
; Button is still pressed after debounce, process it
|
||||
LDI registerA, BUTTON_PRESSED
|
||||
MOV decrementButtonStatus, registerA
|
||||
RCALL decrementCounter
|
||||
RJMP timerExit
|
||||
|
||||
decrementNotPressed:
|
||||
LDI registerA, BUTTON_IDLE
|
||||
MOV decrementButtonStatus, registerA ; Reset to idle state
|
||||
|
||||
timerExit:
|
||||
; Pop registers from stack
|
||||
POP registerB
|
||||
POP registerA
|
||||
SEI ; Enable interrupt
|
||||
RETI
|
||||
42
counter.hex
Normal file
42
counter.hex
Normal file
@ -0,0 +1,42 @@
|
||||
:020000020000FC
|
||||
:100000000BC01895FAC018951895189514C1189535
|
||||
:100010001895189518951895F8940FED0DBF0FE0E9
|
||||
:100020000ABBDB98D998DA98DB9800E707BBC4983D
|
||||
:10003000C598C69800E10BBF80E090E000E0A02EDC
|
||||
:10004000B02E789400C0C2D019D051D0FCCF07E2B6
|
||||
:10005000901718F00FE0801718F4019608F0089533
|
||||
:100060008FE097E2089500E0091710F4081719F0DF
|
||||
:10007000019708F008958827992708959F938F93F3
|
||||
:1000800006D010D020D029D08F919F91089570E094
|
||||
:1000900003E0901708F408957395885E93409017D5
|
||||
:1000A000D8F7089560E001E014E6901718F481177E
|
||||
:1000B00008F408956395C297C29701E09017D0F7AE
|
||||
:1000C0008117C0F7089550E00AE0801708F40895FA
|
||||
:1000D00053958A408017E0F7089540E001E08017CB
|
||||
:1000E00008F4089543958A958017E0F70895F894E9
|
||||
:1000F000072F30D0112E18E011D0062F2BD0112E43
|
||||
:1001000012E00CD0052F26D0112E14E007D0042FBA
|
||||
:1001100021D0112E11E002D07894089507D01BBB96
|
||||
:100120000000000046D011271BBB089508E0202ED8
|
||||
:1001300000E0110C10F0C69801C0C69AC59A0000E4
|
||||
:100140000000C5982A942016A1F7C49A0000000068
|
||||
:10015000C498089510E0011711F413E00895139561
|
||||
:10016000011711F41BE708951395011711F415E217
|
||||
:1001700008951395011711F411E3089513950117CC
|
||||
:1001800011F419E508951395011711F411E9089573
|
||||
:100190001395011711F411E808951395011711F43F
|
||||
:1001A0001BE308951395011711F411E0089511E16F
|
||||
:1001B00008952FEF30E02A952317E9F7089503E01B
|
||||
:1001C00003BF02E008BF02E009BF089502E0A016E5
|
||||
:1001D00041F406B311E00123011709F402C000E065
|
||||
:1001E000A02E02E0B01641F406B312E0012301177D
|
||||
:1001F00009F402C000E0B02E0895F8940F931F9305
|
||||
:1002000006B311E00123011739F400E0A01679F4D8
|
||||
:1002100001E0A02ED4DF0BC006B312E001230117CA
|
||||
:1002200031F400E0B01619F401E0B02EC8DF1F91E0
|
||||
:100230000F9178941895F8940F931F9300E003BFE3
|
||||
:1002400006B311E0A11651F411E00123011721F4C6
|
||||
:1002500002E0A02EFCDE10C000E0A02E11E0B116DE
|
||||
:1002600059F406B312E00123011721F402E0B02E85
|
||||
:10027000FADE02C000E0B02E1F910F91789418951D
|
||||
:00000001FF
|
||||
1
createhex.txt
Normal file
1
createhex.txt
Normal file
@ -0,0 +1 @@
|
||||
avra counter.asm
|
||||
1
uploadhex.txt
Normal file
1
uploadhex.txt
Normal file
@ -0,0 +1 @@
|
||||
sudo avrdude -c usbasp -F -p t26 -U flash:w:counter.hex:i
|
||||
Loading…
Reference in New Issue
Block a user