-- Title: timer0 isr interval
-- Author: Joep Suijs, Copyright (C) 2008 Joep Suijs
-- Adapted-by:
-- Compiler: >=2.4g
-- 
-- This file is part of jallib (http://jallib.googlecode.com)
-- Released under the ZLIB license (http://www.opensource.org/licenses/zlib-license.html)
--
-- Description: Fixed interval isr with support for non-blocking delays.
--
-- Modified the file (removed SLOTS) and added a function (my_count) for
-- counting pulses. Author, Vasile Guta Ciucur

var word internal_isr_counter

var word isr_countdown
var byte timer0_load

function isr_counter'get() return word is
   var word temp
   
   INTCON_T0IE = off
   temp = internal_isr_counter
   INTCON_T0IE = on
   
   return temp
end function


procedure set_delay(word in ticks) is
   
   
   INTCON_T0IE = off
   isr_countdown = ticks
   INTCON_T0IE = on
   
end procedure 


function check_delay return bit is
   
  
   if (isr_countdown == 0) then 
      if (isr_countdown == 0) then 
         -- note: double checking is done to cope with the isr
         -- decrementing from 0x100 to 0x0ff without disabling the isr.
         return true    -- delay passed
      end if
   end if
   
   return false -- still waiting
   
end function     

procedure timer0_isr_init() is  
   
   const dword timer0_div = (target_clock / 4 / timer0_isr_rate ) - 1
   
   if (timer0_div > ((256 * 256) - 1)) then
      pragma error  -- requested ISR rate is too low  
      
   elsif (timer0_div > ((128 * 256) - 1)) then
      OPTION_REG_PS = 7 ; prescaler 256
      timer0_load = 255 - timer0_div / 256
      
   elsif (timer0_div > ((64 * 256) - 1)) then
      OPTION_REG_PS = 6 ; prescaler 128
      timer0_load = 255 - timer0_div / 128
      
   elsif (timer0_div > ((32 * 256) - 1)) then
      OPTION_REG_PS = 5 ; prescaler 64
      timer0_load = 255 - byte(timer0_div / 64)
      
   elsif (timer0_div > ((16 * 256) - 1)) then
      OPTION_REG_PS = 4 ; prescaler 32
      timer0_load = 255 - byte(timer0_div / 32)
      
   elsif (timer0_div > ((8 * 256) - 1)) then
      OPTION_REG_PS = 3 ; prescaler 16
      timer0_load = 255 - byte(timer0_div / 16)
      
   elsif (timer0_div > ((4 * 256) - 1)) then
      OPTION_REG_PS = 2 ; prescaler 8
      timer0_load = 255 - byte(timer0_div / 8)
      
   elsif (timer0_div > ((2 * 256) - 1)) then
      OPTION_REG_PS = 1 ; prescaler 4
      timer0_load = 255 - byte(timer0_div / 4)
      
   else
      OPTION_REG_PS = 0 ; prescaler 2
      timer0_load = 255 - timer0_div / 2
   end if
   
   OPTION_REG_T0CS = 0  ; internal clock
   OPTION_REG_PSA  = 0  ; assign prescaler to timer0
   
   INTCON_T0IF = off
   INTCON_T0IE = on
   INTCON_GIE  = on    ; enable global interrupts
   INTCON_PEIE = on
   
   var byte i
   isr_countdown = 0
   
   
end procedure

procedure ISR() is
   pragma interrupt
   
   if INTCON_T0IF == true then
      tmr0 = timer0_load
      
      -- counters
      internal_isr_counter = internal_isr_counter + 1      
      
      var byte index      

         if (isr_countdown != 0) then
            isr_countdown = isr_countdown - 1
         end if
 
      
      INTCON_T0IF = off
      
   end if
   
end procedure     

-- let's try to simulate count basic command from PICAXE08M  
-- counting on positive edge from a given pin
procedure my_count(volatile bit in DIP_pin, word in ticks, word in out datavar) is
  var bit  step = 0
  var bit  step_t = 0
  set_delay(ticks)
  while !(check_delay())  loop 
   step = DIP_pin
   if step_t != step then
     step_t = step
     if step then
       datavar = datavar + 1
     end if  
   end if 
  end loop  
end procedure