Attribute VB_Name = "IRcodes"
'-------------------------------------------------------------------------------
Option Explicit

' IRcodes Program
'
' This program decodes IR data with the following format --  a data word
' consists of 16 IR pulses. Data is encoded in the 15 spaces between each
' pulse, at 1 bit per space. The 15-bit data is decoded, stored as a 16-bit
' integer, and sent to the serial port.
'
' A Sharp GP1U52X IR sensor is connected to the BasicX input capture pin.
' The sensor produces a logic-high (5 V) when it is quiescent, and
' logic-low (0 V) when an IR carrier is received.
'
' The assumed IR data format is as follows -- North American Protocol B is
' used, with a variable-spacing bit modulation scheme. The carrier pulses
' are 500 us long. Spaces between pulses are 500 us for logic 0, and 1500 us
' for logic 1. The word transmission rate is about 16 Hz.
'
' Input capture pin number:
'
'    BX-01 => 31
'    BX-24 => 12
'    BX-35 => 20

Private Const MaxPulses As Integer = 32
Private PulseTrain(1 To MaxPulses) As New UnsignedInteger
Private Const OverflowValue As Long = 65535
'-------------------------------------------------------------------------------
Public Sub Main()

    Dim I As Integer
    Dim Digit As Byte
    Dim Success As Boolean
    Dim Value As Integer
    Dim BitValue As Byte

    Do
        Debug.Print
        Debug.Print "Ready"
        Debug.Print

        ' Record IR pulses on the input capture pin.
        Call InputCapture(PulseTrain, MaxPulses, 0)

        Call ErrorCheck(Success)
        If (Not Success) Then
            Debug.Print "*** ERROR ***"
            GoTo Continue
        End If

        Value = 0

        ' Decode the spaces between each pulse, and send to the serial port.
        ' Spaces are stored in even-numbered array elements.
        I = 2
        Digit = 1
        Do
            Call DecodeSpace(PulseTrain(I), BitValue, Success)

            If (Success) Then

                ' Right shift.
                Value = Value * 2

                ' Add LSBit.
                Value = Value + CInt(BitValue)
            Else
                Debug.Print "*** ERROR ***"
                GoTo Continue
            End If

            I = I + 2
            Digit = Digit + 1

        Loop While I <= (MaxPulses - 1)

        Debug.Print "Key: "; CStr(Value)

        Call Delay(1.0)

Continue:

    Loop

End Sub
'-------------------------------------------------------------------------------
Private Sub ErrorCheck( _
    ByRef Success As Boolean)

' Check to make sure the last space is longer than 8.89 ms (the InputCapture
' time limit), and that each pulse is within tolerances.

    ' Each carrier pulse must be within this range.
    Const MaxValue As Single = 700.0E-6
    Const MinValue As Single = 300.0E-6 

    Const UnitConversion As Single = 135.63368E-9 ' => 1.0 / 7372800.0

    Dim PulseWidth As Single
    Dim I As Integer

    ' The last space must be greater than 8.89 ms, which means it must have
    ' overflowed.
    If (PulseTrain(MaxPulses) <> CuInt(OverflowValue)) Then
        GoTo Failure
    End If           

    ' Look at the IR carrier pulses, which are odd-numbered array elements.
    I = 1
    Do
        ' Convert to seconds.
        PulseWidth = CSng(PulseTrain(I)) * UnitConversion

        If (PulseWidth < MinValue) Or (PulseWidth > MaxValue) Then
            GoTo Failure
        End If

        I = I + 2
    Loop While I <= (MaxPulses - 1)

    Success = True
    Exit Sub

Failure:

    Success = False

End Sub
'-------------------------------------------------------------------------------
Private Sub DecodeSpace( _
    ByVal Space As UnsignedInteger, _
    ByRef BitValue As Byte, _
    ByRef Success As Boolean)

' Translates the specified space to a binary digit. If the space width is
' within tolerances, the Success flag is set to true. Otherwise Success
' is false.

    ' Each space must be within this range.
    Const MaxValue As Single = 1700.0E-6
    Const MinValue As Single =  300.0E-6 

    ' This is the crossover point between binary 0 and 1.
    Const TripPoint As Single = 1000.0E-6

    Const UnitConversion As Single = 135.63368E-9 ' => 1.0 / 7372800.0

    Dim SpaceWidth As Single

    ' Convert to seconds.
    SpaceWidth = CSng(Space) * UnitConversion

    ' Check time constraints.
    If (SpaceWidth < MinValue) Or (SpaceWidth > MaxValue) Then
        Success = False
        Exit Sub
    Else
        Success = True
    End If

    If (SpaceWidth > TripPoint) Then
        BitValue = 1
    Else
        BitValue = 0
    End If

End Sub
'-------------------------------------------------------------------------------
