'ATtiny13 6 LEDs an 3 Ports
$regfile = "attiny13.dat"
$crystal = 1200000
$hwstack = 8
$swstack = 4
$framesize = 4
Config Portb = Input
Portb = 0
Do
Ddrb = 00001100
Portb = 00001000
Waitms 500
Ddrb = 00001100
Portb = 00000100
Waitms 500
Ddrb = 00011000
Portb = 00010000
Waitms 500
Ddrb = 00011000
Portb = 00001000
Waitms 500
Ddrb = 00010100
Portb = 00000100
Waitms 500
Ddrb = 00010100
Portb = 00010000
Waitms 500
Loop
End
'***************************************************************************
'
'ATTiny13 12 Charlieplexed Leds on PB 0 1 2 3
'
'
' input on ADC channel 2
'
'***************************************************************************
' This program is free software; you can redistribute it and/or
' modify it under the terms of the GNU General Public License.
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY;
'
'***************************************************************************
'
' Pinout ATtiny13/ATtiny13V 8-PDIP/SOIC
'
' (PCINT5/RESET/ADC0/dW) PB5 VCC
' (PCINT3/CLKI/ADC3) PB3 PB2 (SCK/ADC1/T0/PCINT2)
' (PCINT4/ADC2) PB4 PB1 (MISO/AIN1/OC0B/INT0/PCINT1)
' GND PB0 (MOSI/AIN0/OC0A/PCINT0)
'
'***************************************************************************
' PB0 output Led
' PB1 output
' PB2 output
' PB3 output
' PB4 input ADC channel 2
'***************************************************************************
$regfile = "attiny13.dat"
$crystal = 1200000
$hwstack = 8
$swstack = 8
$framesize = 4
Const C_value = 187 - 1 ' Compare Match IRQ 10 ms
Declare Sub Mydelay
Dim Voltage As Word , Avgv As Word
Dim Icnt0 As Byte
Dim N As Byte , Xp As Byte , Xd As Byte
'Dim Pp As Byte , Dd As Byte
Portb = &B00000000
Ddrb = &B00000000
Acsr.acd = 1 ' switch off analog comparator
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Didr0.adc2d = 1
Start Adc
Config Timer0 = Timer , Prescale = 64
Ocr0a = C_value ' value for 1.2 MHz
Tccr0a = &B00000010 ' ctc
Timsk0.ocie0a = 1
On Oc0a Tim0_compa
Start Timer0
For N = 0 To 11 'test leds
Xd = Lookup(n , Led12)
Xp = Xd
Shift Xd , Right , 4 ' upper is DDR
Xd = Xd And &H0F
Xp = Xp And &H0F ' lower is Port
Portb = Xp
Ddrb = Xd
Call Mydelay
Next N
Enable Interrupts
Timer0 = 0
Do ' main loop
Loop
'***************************************************************************
'Tim0_compa Interrupt 10 ms
'***************************************************************************
Tim0_compa: '
'Incr Icnt0
Voltage = Getadc(2)
Avgv = Getadc(2)
Voltage = Avgv + Voltage
N = Voltage / 170
If N = 12 Then
N = 11
End If
Xd = Lookup(n , Led12)
Xp = Xd
Shift Xd , Right , 4 ' upper is DDR
Xd = Xd And &H0F
Xp = Xp And &H0F ' lower is Port
Portb = Xp
Ddrb = Xd
'Voltage = Getadc(2)
'Avgv = Avgv + Voltage
'Shift Voltage , Right , 2 '8 bit
Return
End
Mydelay: 'delay
$asm
PUSH R27
Ldi R27 , 200 'Load R27
Mdec:
Dec R27
BRNE Mdec
POP R27
$end Asm
Return
Led12: ' Led0..11 Cplex ' 12 = 0 upper 4 bit DDRB lower 4 bit PORTB
Data &B00110001 , &B11001000 , &B11000100 , &B10101000 , &B10100010 , &B01100100 , &B01100010 , &B01010100 , &B01010001 , &B10011000 , &B10010001 , &B00110010 , 0 , 0
Assembler-Version:
;***************************************************************************
; ATtiny13 Charlieplex 12 Leds on PB 0 1 2 3, use threshold and Led table
;
; input on ADC2, PB4, 8 bit
; simple Voltmeter, 0,..,5 V, single Led is on
; bsed on ATtiny15 GS 2009
; The timing is adapted for 1.2 MHz
;
;***************************************************************************
; This program is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License.
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY;
;
;***************************************************************************
; Pinout ATtiny13/ATtiny13V 8-PDIP/SOIC
;
; (PCINT5/RESET/ADC0/dW) PB5 VCC
; (PCINT3/CLKI/ADC3) PB3 PB2 (SCK/ADC1/T0/PCINT2)
; (PCINT4/ADC2) PB4 PB1 (MISO/AIN1/OC0B/INT0/PCINT1)
; GND PB0 (MOSI/AIN0/OC0A/PCINT0)
;***************************************************************************
; PB4 input ADC2
; PB3 output Leds
; PB2 output
; PB1 output
; PB0 output
;***************************************************************************
.DEVICE ATtiny13 ;for gavrasm
.equ avgcnt = 16
.equ AD_resolution = 256 ; A/D converter resolution
; r0 used
.def S = r4
.def temp = r16
.def count = r17
.def lcnt = r18
.def next_step = r19
.def av_l = r20 ; Average Low Byte (ADC Measurement)
.def av_h = r21 ; Average High Byte (ADC Measurement)
.def LedPD = R22 ; Led port and DDR
.def Ledcnt = R23 ; Led 0,..,11
.def ZL = r30
.def ZH = r31
.cseg
.org 0
rjmp reset ; 0x0000 Reset-vector
reti ; 0x0001 External Interrupt 0
reti ; 0x0002 PCIrq0
rjmp TIM0_OVF ; 0x0003 Timer/Counter0 Overflow
reti
;********************************************************************
;* "TIM0_OVF" - Timer/counter overflow interrupt handler
;*
;* The overflow interrupt fires every 1.7ms
;*
;********************************************************************
TIM0_OVF: in S,sreg ; Updated every 1.7 ms, calibrate OSCCAL
inc count
inc next_step
out sreg,S
reti
;***************************************************************************
reset:
; writing calibration byte to OSCCAL Register.
;ldi temp,0x7F ; test
;out OSCCAL,temp ; for the clock
nop
nop
; Port B
ldi temp,0 ; set
out PORTB, temp ; 1 = pull-up , 0 = float
ldi temp,0 ; 1 = output , 0 = input
out DDRB, temp ; to data direction register
;***************************************************************************
; AD-Converter setup:
; If ADLAR is set, the result is left-adjusted.
ldi temp, 0b00100010 ; Ch 2 input=PB4, REFS0,1 =00 Vcc is RefVoltage
out ADMUX, temp
; ADC init single conversion prescaler 8:
ldi temp, 0b11010011 ;
out ADCSRA, temp
;***************************************************************************
; timer setup:
ldi temp,0b00000010 ; Timer/Counter 0 clocked at CK/8
out TCCR0B,temp ; 1,2 Mhz
;Bit 1 – TOIE0: Timer/Counter0 Overflow Interrupt Enable
ldi temp,0b00000010 ; set Bit 1
out TIMSK0,temp ; in the Timer Interupt Mask Register
out TIFR0,temp ; in the Timer Interupt Flag Register
ldi temp,0 ; Timer/Counter 0 clear
out TCNT0,temp ;
clr av_l
clr av_h ; Clear Average Registers
clr next_step
sei ; Enable gobal iterrupt
;***************************************************************************
clr Ledcnt
ldi ZH,high(2*Led12) ; setup Z pointer hi
testleds:
ldi ZL,low(2*Led12) ; Leds upper 4 bit DDRB lower 4 bit PORTB
add ZL, Ledcnt ; table offset
lpm
tst r0 ; 0 is end of table
breq ma1
rcall Ledset ; set PORTB and DDRB
inc Ledcnt
clr next_step
testwait: cpi next_step, 250 ; wait time
brlo testwait
rjmp testleds
ma1: clr next_step
main: cpi next_step, 8 ; reaction time
brlo main
clr next_step
rcall convert_average ; Measure Volt 0..255
mc0:
ldi ZH, high(2*Thresh) ; setup Threshold
ldi ZL, low(2*Thresh) ; setup Z pointer lo
ser Ledcnt ; to -1
mc1:
lpm
tst r0
breq mc2
inc ZL
inc Ledcnt ; 0..11
cp av_l, r0 ; av higher than threshold
brsh mc1 ; else led on
mc2:
ldi ZH,high(2*Led12) ; setup Z pointer hi to Leds
ldi ZL,low(2*Led12) ; Leds upper 4 bit DDRB lower 4 bit PORTB
add ZL, Ledcnt ; table offset
lpm
rcall Ledset ; set PORTB and DDRB
rjmp main
;***************************************************************************
Ledset:
mov LedPD, r0 ; subroutine to set Leds, input r0
andi LedPD, 0x0F ; lower 4 bit PORTB
out PORTB, LedPD ; first Port
mov LedPD, r0
swap LedPD ; swap
andi LedPD, 0x0F ; upper 4 bit DDRB
out DDRB, LedPD ; to data direction register
ret
;*************************[ ADC Handler ]*********************************
; This function measures the ADC channel, and returns the
; converted value in [av_l] 8 bit resolution
convert_average:
ldi temp,0b00100010
out ADMUX, temp ; Set ADC Channel PB4
clr av_l
clr av_h ; Clear Average Registers
ldi lcnt,avgcnt ; Set loop counter
convert_start:
ldi temp,0b11010011 ;
out ADCSRA,temp ; Start A/D Conversions
convert_wait:
sbis ADCSRA, ADIF
rjmp convert_wait ; Wait for Conversion to finish
in temp, ADCH
add av_l, temp
ldi temp, 0
adc av_h, temp ; Add measured value to average
dec lcnt
brne convert_start ; Repeat lcnt times
ldi lcnt,avgcnt/4 ; Set shift counter
convert_avg:
lsr av_h
ror av_l ; av_h:av_l = av_h:av_l/2
dec lcnt
brne convert_avg ; Repeat (avg_loop_cnt) times
;cbi ADCSRA,ADEN
ret ; return to measure
;***************************************************************************
; force table to begin at 256 byte boundary
.org 0x100
; Charlieplex Leds on PB 0 1 2 3
; in 1 byte: upper 4 bit DDRB lower 4 bit PORTB
Led12: ;led0..11 Cplex
.db 0b00110001, 0b00110010,
.db 0b10010001, 0b10011000,
.db 0b01010001, 0b01010100,
.db 0b01100010, 0b01100100,
.db 0b10100010, 0b10101000,
.db 0b11000100, 0b11001000,
.db 0,0
; linear voltage threshold for Leds
Thresh:
.db 21, 42, 63, 85, 106, 127, 148, 170, 191, 210, 233, 255, 0, 0
Led6:
.db 0b10110001, 0b10110010,
.db 0b11100010, 0b11100100,
.db 0b11010100, 0b11010001,
.db 0,0