The simple solution is to have your reset
read the signature byte into a variable so you can branch on that later.
Initial code could look like:
rjmp reset
rjmp vec_1
rjmp vec_2
rjmp vec_3
...
vec_1:
; odd vectors are always attiny87
; this is INT0
; attiny167 never gets here so no branching
...
vec_2:
; if we are attiny87 this is INT1
; if we are attiny167 this is INT0
; so do a conditional branch to the proper place
...
vec_3:
; again odd vector so this is PCINT0 on an attiny87
...
If you don't like the repeated branching you can put together a clever dispatcher working with RCALL
and the return addresses. This may be overkill but was fun so here it is:
#include <avr/io.h>
; set up a variable to store the signature byte
; arbitrary address
.equ signature_byte_1, 0x100
rjmp reset
.rept 39
rcall dispatch
.endr
dispatch:
; save Y
push r28
push r29
; get SP into Y
in r28, _SFR_IO_ADDR(SPL)
in r29, _SFR_IO_ADDR(SPH)
; put ZH on stack
std Y + 3, r31
; get return address into ZH
ldd r31, Y + 4
; put ZL on stack
std Y + 4, r30
; save SREG
in r30, _SFR_IO_ADDR(SREG)
push r30
; assume this has been set up during reset
; 0x93 for attiny87
; 0x94 for attiny167
lds r30, signature_byte_1
; return address is
; attiny87: 2, 3, 4, ...
; attiny167: 3, 5, 7, ...
; we want for indexing: 0, 2, 4 ...
dec r31
; multiply attiny87 by 2
sbrc r30, 0
lsl r31
; now both are 2, 4, 6, ...
; fix pointer, assume it's in first 256 bytes
mov r30, r31
ldi r31, 0
ldi r28, lo8(vectors-2)
add r30, r28
; both LPM and ICALL use Z :(
lpm r28, Z+
lpm r29, Z
mov r30, r28
mov r31, r29
icall
; restore SREG
pop r30
out _SFR_IO_ADDR(SREG), r30
; restore Y
pop r29
pop r28
; restore Z
pop r31
pop r30
; done
reti
; here is the real vector table
vectors:
.word pm(int0_handler)
.word pm(int1_handler)
.word pm(pcint0_handler)
.word pm(pcint1_handler)
; ...
reset:
ldi r16, lo8(RAMEND)
ldi r17, hi8(RAMEND)
out _SFR_IO_ADDR(SPL), r16
out _SFR_IO_ADDR(SPH), r17
; read signature byte into variable
; left as exercise for reader :)
; TEST CODE
; verify these are not changed
ldi r28, 28
ldi r29, 29
ldi r30, 30
ldi r31, 31
; simulate attiny87
ldi r16, 0x93
sts signature_byte_1, r16
; invoke PCINT0
rcall 3*2
; invoke INT1
rcall 2*2
; simulate attiny167
ldi r16, 0x94
sts signature_byte_1, r16
; invoke PCINT0
rcall 6*2
; invoke INT1
rcall 4*2
end:
rjmp end
int0_handler:
ret
int1_handler:
ret
pcint0_handler:
ret
pcint1_handler:
ret