'-------------------------------------------------------------------------------
Option Explicit

' This module is used for causing a BasicX processor to go into power
' down mode, during which time current drops to low levels. The processor
' can be made to wake up by applying a logic low to the INT1 pin for
' at least 16 ms.
'
' INT1 pin number:
'
'    BX-01 => 13
'    BX-24 => 11
'    BX-35 => 17

'>>Private Const INT1pin As Byte = 13  ' BX-01
Private Const INT1pin As Byte = 11  ' BX-24
'>>Private Const INT1pin As Byte = 17  ' BX-35

Private Const StackSize As Integer = 19
Private WakeupStack(1 To StackSize) As Byte

Private InterruptIsPending As Boolean
Private WakeupTaskIsActive As Boolean
'-------------------------------------------------------------------------------
Public Sub PowerDownMode()

    ' Configure INT1 as input-pullup.
    Call PutPin(INT1pin, bxInputPullup)

    ' Also configure INT0 as input-pullup in order to prevent it from
    ' causing an unwanted interrupt.
    '
    ' On the BX-01, INT0 is pin 12 (which is also Com2 Receive Data).
    '
    ' On the BX-24, INT0 is (internal) pin 11 on the 8535 chip, and is not
    ' connected to an external pin.
    '
    ' On the BX-35, INT0 is pin 16.

    Register.DDRD  = Register.DDRD And bx1111_1011
    Register.PORTD = Register.PORTD Or bx0000_0100

    InterruptIsPending = True
    WakeupTaskIsActive = False

    CallTask "WakeupTask", WakeupStack

    Do Until (WakeupTaskIsActive)
        Call Sleep(0)
    Loop

    ' Modify according to processor.
    '>>Call PowerDownBX01
    Call PowerDownBX24
    '>>Call PowerDownBX35

End Sub
'-------------------------------------------------------------------------------
Private Sub WakeupTask()

    WakeupTaskIsActive = True

    ' This blocks the task until the INT1 pin is held low for at
    ' least 16 ms.
    Call WaitForInterrupt(bxPinLow)

    InterruptIsPending = False

End Sub
'-------------------------------------------------------------------------------
Private Sub PowerDownBX35()

    Call PowerDownBX24

End Sub
'-------------------------------------------------------------------------------
Private Sub PowerDownBX24()

    ' Clear SM0 (bit 4).
    Register.MCUCR = Register.MCUCR And bx1110_1111

    ' Set SE (Sleep Enable, bit 6). Also set SM1 (bit 5) for
    ' power down mode.
    Register.MCUCR = Register.MCUCR Or  bx0110_0000

    ' Skip CPUsleep if an interrupt has already occurred.
    If (InterruptIsPending) Then
        Call CPUsleep
    End If

    ' Clear SE and SM1.
    Register.MCUCR = Register.MCUCR And bx1001_1111

End Sub
'-------------------------------------------------------------------------------
Private Sub PowerDownBX01()

    ' Set SE (Sleep Enable, bit 5). Also set SM (bit 4) for
    ' power down mode.
    Register.MCUCR = Register.MCUCR Or  bx0011_0000

    ' Skip CPUsleep if an interrupt has already occurred.
    If (InterruptIsPending) Then
        Call CPUsleep
    End If

    ' Clear SE and SM.
    Register.MCUCR = Register.MCUCR And bx1100_1111

End Sub
'-------------------------------------------------------------------------------
