Version:0.9 StartHTML:0000000105 EndHTML:0000037801 StartFragment:0000001117 EndFragment:0000037785
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' AVR Chronograph using VFD, 20MHz clock '
' Timer 0 overflow increments variable "speed" '
' Overflow should occur every 20MHz / 50 = 400 kHz '
' 400kHz^-1 = 2.5 µs '
' Timer starts on INT0 interrupt and stops with INT1 '
' Speed is then calculated and sent to VFD '
' slowest projectile speed measurable is 0.92m/s before '
' overflow of count. '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
program vfd_chronograph
dim digit, grid as byte
dim number, tens, ones as byte
dim speed, temp, thou, hund, count as word
dim precalc as longword
'INT0 interrupt rutine (start timer)
sub procedure INT0_Interrupt org 0x01
SREG_I_bit = 0 ' disable Interrupts
TCNT0 = 0 ' reset timer0
TCCR0B = %00001001 ' select no prescaling, clear TMR0 on compare match
TIMSK.0 = 1 ' enable interrupt on TMR0 compare match A
SREG_I_bit = 1 ' enable Interrupts
end sub
'INT1 interrupt rutine (stop timer and determine speed)
sub procedure INT1_Interrupt org 0x02
SREG_I_bit = 0 ' disable Interrupts
TIMSK.0 = 0 ' disable interrupt on TMR0 compare match A
TCCR0B = %00001000 ' stop timer 0, clear TMR0 on compare match
TCNT0 = 0 ' reset timer0
' Determine projectile speed
precalc = 6000000 div count ' since distance and time interval are set
' at 150mm and 2.5µs, they can be precalculated into 6M. 6M because display
' has dot already, so speed is actually given in mm/s
speed = precalc
SREG_I_bit = 1 ' enable Interrupts
end sub
' Timer0 overflow interrupt rutine (add 2.5µs to speed)
sub procedure Timer_Interrupt0 org 0x0D
Inc(count)
end sub
main:
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''Initializations'''''''''''''''''''''''''''''''''''''''''''''''
TCCR0B = %00001000 ' stop timer 0, clear TMR0 on compare match '
OCR0A = 50 ' set overflow at 50, giving 400kHz clocking '
MCUCR = %00001111 ' set interrupt on rising edge for INT 0 and 1 '
GIMSK.7 = 1 ' enable INT interrupts
GIMSK.6 = 1
DDRB = %01111111 ' portb output, except PB7 '
DDRD = %1110011 ' only pins 6 and 7 (INT0 and 1) as input on portD '
count = 0 ' initialize variables '
speed = 0 '
digit = 0 '
grid = 0xFF '
SREG_I_bit = 1 ' Interrupt enable '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''Main Program'''''''''''''''''''''''''''''''''''''''''''''''''
while true ' create digits here, fun fact: takes 1243 clock cycles
' that's 0.00006215s or 62.15µs
thou = speed div 1000 ' thousands digit
thou = thou * 1000
temp = speed - thou ' hundreds digit
hund = temp div 100
hund = hund * 100
temp = thou + hund ' tens digit
temp = speed - temp
tens = temp div 10
tens = tens * 10
temp = thou + hund ' ones digit
temp = temp + tens
temp = speed - temp
ones = temp
thou = thou div 1000 ' thousands digit
hund = hund div 100 ' hundreds digit
tens = tens div 10 ' tens digit
if thou = 0 then
thou = 10 ' invalid digit, VFD displays nothing
end if
digit = 0 ' MSB = 0, LSB = 4
do ' display digits
select case digit
case 0
grid = %1111110
number = thou
case 1
grid = %1111101
number = hund
case 2
grid = %1101111
number = 2 ' number two activates correct dot
case 3
grid = %1011111
number = tens
case 4
grid = %0111111
number = ones
end select
portB = 0
delay_us(10) ' time for display to blank
portD = grid
select case number ' Chooses proper portB output for digit display
case 0
portb = 192
case 1
portb = 249
case 2
portb = 164
case 3
portb = 176
case 4
portb = 153
case 5
portb = 146
case 6
portb = 130
case 7
portb = 248
case 8
portb = 0
case 9
portb = 152
case else
portb = 127 ' displays nothing if number doesn't exsist
end select
Inc(digit) ' digit control so grids are activiated accordingly
delay_us(200) ' time for digit to be perceived by eye
loop until digit = 5
wend
end.