Version:0.9 StartHTML:0000000105 EndHTML:0000037801 StartFragment:0000001117 EndFragment:0000037785 mikroIDE
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' 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.