From Swordfish Wiki

SwordfishUser: Autokey

This module demonstrates the use of a very simple to use but powerful module called ISRTimer. What I did was copy the code from the Keypad module and added a bit of my own. The result as a very simple system to automatically scan the keyboard every 20hz and then provide key latching. Key latching is a term I use to say you can set a key as been seen and you will not be notified until that key is released and pressed again. A typical example being in a menu system where you would normally have to put a big delay in to prevent the menu going through every option before you can blink.

With the key latch in place and the fact you have a 20hz tick you can add an auto repeat function in as all the module has to do is flag the key again as being a fresh key press.

At the bottom is the module and above are 2 examples of it being used.

In this first example we just have a simple autorepeat

    Include "usart.bas"
    Include "AutoKey.bas"
    Include "convert.bas"


    Dim temp As Byte
    Dim counter As Byte
    Dim counter2 As Byte

    SetBaudrate(br19200)
    ' program start...

    counter = 5
    counter2 = 10
    AutoRepeatPeriod(counter2)

    While 1 = 1
        If AutoKey.IsNewKey = true Then           // Has there been a new key pressed?
            temp = AutoKey.Value()                // Yes so get that Key 
            AutoKey.KeyLatched()                  // Seen the key so latch it as seen until is Pressed 
                                                  // another key or it auto Repeats
            USART.Write(DecToStr(temp))           // Convert the no to asscii and write the value out   
        EndIf
        DelayMS(100)
    Wend

In this example we show how altering the auto-repeat period we can decrease the delay between auto-repeats

    Include "usart.bas"
    Include "AutoKey.bas"
    Include "convert.bas"


    Dim temp As Byte
    Dim counter As Byte
    Dim counter2 As Byte

    SetBaudrate(br19200)
    ' program start...

    counter = 5
    counter2 = 10
    AutoRepeatPeriod(counter2)

    While 1 = 1
        If AutoKey.IsNewKey = true Then           // Has there been a new key pressed?
            temp = AutoKey.Value()                // Yes so get that Key 
            AutoKey.KeyLatched()                  // Seen the key so latch 
            USART.Write(temp + 48)
            Toggle (PORTD.0) 
            If counter > 0 Then                // Now count the number of times a 
                Dec (counter)                  // new key is seen so we can
            Else
                If counter2 > 0 Then
                    Dec (counter2)
                    AutoRepeatPeriod(counter2) // Reduce the auto repeat period
                    USART.Write("S")           // Just a note to let me know I have 
                EndIf                          // reduced the Auto Repeat period
                counter = 5
            EndIf    
        EndIf
        DelayMS(100)
    Wend

Finally the module don't forget to save it in the "UserLibrary" folder for safe keeping!

     Module AutoKey

    Include "ISRTimer.bas"

// validate data port...
    #option KEYPAD_PORT = PORTB
    #if IsOption(KEYPAD_PORT) 
       #if Not IsValidPort(KEYPAD_PORT)
          #error KEYPAD_PORT, "Invalid option. Keypad must be connected to a valid port name."
       #endif
       #option _KEYPAD_PORT_TRIS = GetTRIS(KEYPAD_PORT)   
    #endif 

// bring PORT and TRIS options into the module
    Dim 
       FKeyPort As KEYPAD_PORT, 
       FKeyPortTris As _KEYPAD_PORT_TRIS

// private variables and aliases...
    #if KEYPAD_PORT in (PORTB)
    Dim 
       FPullupsDisabled As INTCON2.Booleans(7), // weak pullups
       FInterruptFlag As INTCON.Booleans(0),    // PORTB interrupt flag
       FInterruptEnable As INTCON.Booleans(3)   // PORTB interrupt enable
    #endif
{
****************************************************************************
* Name    : EnablePullups (PRIVATE)                                        *
* Purpose : Enables MCU weak pullups                                       *
****************************************************************************
}
    Inline Sub EnablePullups()
    #if KEYPAD_PORT in (PORTB)
       FPullupsDisabled = false
    #endif    
    End Sub
{
****************************************************************************
* Name    : Value                                                          *
* Purpose : Reads and returns the key pressed on a keypad matrix           *
****************************************************************************
}
    Function KeyValue() As Byte
       Const NumberOfRows = 4      
       Dim RowIndex As Byte            

       EnablePullups                    // enable weak pullups
       FKeyPortTris  = $F0              // Make the columns bits inputs       
       FKeyPort = 0                     // Send row lines low
       Result = 0
       If FKeyPort < $F0 Then            
          RowIndex = NumberOfRows       
          FKeyPort = %11111110 
          Repeat
             Inc(Result)

             // column 1...
             If FKeyPort.4 = 0 Then           
                Break
             EndIf
             Inc(Result)

             // column 2...
             If FKeyPort.5 = 0 Then 
                Break
             EndIf
             Inc(Result)

             // column 3...
             If FKeyPort.6 = 0 Then  
                Break            
             EndIf                       
             Inc(Result)

             // column 4...
             If FKeyPort.7 = 0 Then  
               Break            
             EndIf                       

             // rotate mask...
             FKeyPort = FKeyPort << 1
             FKeyPort.0 = 1 

             Dec(RowIndex)
          Until RowIndex = 0 
       EndIf  
    End Function




    Public Dim CurrentKey As Byte
    Public Dim IsNewKey As Boolean 
    Public Dim AutoRepeateActive As Boolean
    Public Dim AutoRepeatTmrValue As Byte
    Public Dim AutoRepeatTmr As Byte
    Public Dim DebounceTmr As Byte 
    Public Dim DebounceTimeValue As Byte  
    Public Dim Lastkey As Byte   


    // OnTimer event...
    Event OnKeyPadRead()           
    CurrentKey = KeyValue

    If CurrentKey <> 0  Then
        If CurrentKey = Lastkey Then
            If AutoRepeateActive = true Then
                If AutoRepeatTmr > 0 Then
                    Dec (AutoRepeatTmr)
                Else
                    IsNewKey = true 
                    AutoRepeatTmr = AutoRepeatTmrValue
                EndIf  
             EndIf    
        Else
            IsNewKey = true 
            Lastkey = CurrentKey 
        EndIf
    Else
        If DebounceTmr > 0 Then
            Dec (DebounceTmr)
        Else
            DebounceTmr = DebounceTimeValue
            Lastkey = 0
            AutoRepeatTmr = AutoRepeatTmrValue
        EndIf
    EndIf

    End Event 

{    
****************************************************************************
* Name    : Value                                                          *
* Purpose : Returns the current key being Pressed                          *
****************************************************************************
}    
    Public Inline Function Value() As Byte
        result = CurrentKey
    End Function
{    
****************************************************************************
* Name    : DebounceTime                                                   *
* Purpose : Sets the number of times it sees the key at 0 before           *
*           it accepts it as 0 to debounce the key                         *
****************************************************************************
}
    Public Sub DebounceTime(ByVal Pvalue As Byte)
        DebounceTimeValue = Pvalue
        DebounceTmr = Pvalue    
    End Sub
{    
****************************************************************************
* Name    : AutoRepeatPeriod                                               *
* Purpose : Sets the number of times it sees the same key in sucssesion    *
*          before it notifies by resetting the new IsNewKey flag           *
****************************************************************************
}    
    Public Sub AutoRepeatPeriod(ByRef Pvalue As Byte)
        AutoRepeatTmrValue = Pvalue
        AutoRepeatTmr = Pvalue    
    End Sub
{    
****************************************************************************
* Name    : KeyLatched                                                     *
* Purpose : Clears the IsNewKey flag so you will only be notifed when the  *
*           key changes  (or auto repeates)                                *
****************************************************************************
}    
    Public Inline Sub KeyLatched()
       IsNewKey = false
    End Sub 

{    
****************************************************************************
* Name    : EnableAutoRepeate                                              *
* Purpose : Enables the autorepeat function                                *
****************************************************************************
}     
    Public Inline Sub EnableAutoRepeate ()
        AutoRepeateActive = true
    End Sub
{    
****************************************************************************
* Name    : DisableAutoRepeat                                              *
* Purpose : Disables the autorepeat function                               *
****************************************************************************
}    
    Public Inline Sub DisableAutoRepeat ()
        AutoRepeateActive = False
    End Sub     

    AutoRepeatTmrValue = 10
    IsNewKey = True
    AutoRepeateActive = true
    Lastkey = 0
    KeyLatched()

    Timer.Initialize
    Timer.Items(0).Interval =50      // Scanned at 20hz
    Timer.Items(0).OnTimer = @OnKeyPadRead // timer event handler
    Timer.Items(0).Enabled = true
    Timer.Start

    End
Retrieved from https://www.sfcompiler.co.uk/wiki/pmwiki.php?n=SwordfishUser.Autokey
Page last modified on December 04, 2006, at 01:38 PM