MPLABICDCode

SwordfishUser.MPLABICDCode History

Hide minor edits - Show changes to output

June 17, 2008, at 09:20 AM by David Barker -
Changed lines 1-3 from:
!!!Program Code
The
main program code should be under "Source File" in MPLAB.
to:
The main program code should be under "Source File" in MPLAB. Your main Swordfish program file '''should always reside''' in the same folder as you MPLAB project file. That is, the program in "Source Files" must be in the same folder as the MPLAB *.mcp and *.mcw files.
Changed lines 59-60 from:
#endif
to:
June 17, 2008, at 09:18 AM by David Barker -
Added lines 1-232:
!!!Program Code
The main program code should be under "Source File" in MPLAB.

=code [=
' select device and clock...
Device = 18F1320
Clock = 8

' enable ICD - always set before including the Junebug module - if
' you are not using the ICD, you must disable or remove this option
' in order for your program to work correctly...
#option ICD = true   

' include the Junebug module - this module will manage LEDs and
' button presses for you. It will also correctly configure for internal
' oscillator, based on the 'clock' value above (4 or 8MHz only)
Include "junebug.bas"

' local variables...
Dim Index As Byte
Dim Delay As Word
Dim DoCount As Boolean

' program start...
Index = 0
DoCount = false
Delay = 100
While true
  LED = Index

  ' press button 1 to start and stop counting...
  If IsPressed(Btn1) Then
      DoCount = Not DoCount

  ' if button 2 is pressed, slow down the count speed...
  ElseIf IsPressed(Btn2) Then
      Inc(Delay, 10)
      If Delay > 500 Then
        Delay = 500
      EndIf

  ' if button 3 is pressed, speed up the count speed...
  ElseIf IsPressed(Btn3) Then
      Dec(Delay, 10)
      If Delay < 10 Then
        Delay = 10
      EndIf
  EndIf
 
  ' if counting is enabled, increment the counter and
  ' delayms(Delay) - Delay will vary depending on how
  ' much you have decreased or increased using Btn2 or Btn3
  ' respectively...
  If DoCount Then
      Inc(Index)
      DelayMS(Delay)
  EndIf
Wend
=]
#endif

!!! Module Code
Here is the module code, which should be under "Other Files"

=code [=
Module Junebug

// default configuration fuses...
Config
  OSC = INTIO2,
  WDT = OFF,
  LVP = OFF

// if you want to use ICD, then set '#option ICD = true' in your main program
// before you include this module...
#if IsOption(ICD) And ICD
#option ISR_SHADOW = false
#variable _maxram = _maxram - $C    // constrain RAM
#variable _maxrom = _maxrom - $1C0  // constrain ROM
Config DEBUG = ON                  // DEBUG fuse ON
#endif

// private module constants...
Const
  TIMER_REFRESH          = 500,                            // 500 = 2 ms, 250 = 1ms
  TIMER_RELOAD As Word  = 65536 - _clock * TIMER_REFRESH, // calculate reload constant
  TIMER_DEBOUNCE As Byte = 2500 / TIMER_REFRESH            // button debounce (10ms)

// private module variables...
Dim
  TMR1 As TMR1L.AsWord,  // timer 1 as a word
  TMR1IF As PIR1.0,      // timer 1 interrupt flag
  TMR1IE As PIE1.0,      // timer 1 interrupt enable
  smState As Byte,        // LED state machine variable
  LastButton As Byte,    // holds the state of the last PORTB button press
  Debounce As Byte        // debounce counter variable

// public module constants...
Public Const
  Btn1 = 1,
  Btn2 = 2,
  Btn3 = 4

// public module variables...
Public Dim               
  LED As Byte,            // LED, bits 0..5
  Button As Byte          // button press, bits 0..2
{
****************************************************************************
* Name    : ISR (PRIVATE)                                                  *
* Notes  : High priority interrupt handler for Timer 1 events. The ISR is *
*        : fired every 1 or 2ms (depending on TIMER_REFRESH, see above)  *
*        : LED HANDLING                                                  *
*        : As the LEDs on the Junebug are 'charlieplexed', you can only  *
*        : normally have one LED on at a time. However, by time slicing  *
*        : very quickly between each LED state, you can give the illusion *
*        : that all LEDs are on at the same time. Just set LED.0..5 in    *
*        : main program to switch on                                      *
*        : BUTTON HANDLING                                                *
*        : PORTB is scanned and if a button is pressed, the ISR will      *
*        : manage debouncing (10ms). Using an ISR to scan for a button    *
*        : ensure that no button press events are ever missed, even if    *
*        : your main program is performing another task. Use either      *
*        : Button.0..2 in your main program to test for a button press.  *
*        : alternatively, make a call to IsPressed() - see below          *
****************************************************************************
}
Public Interrupt ISR()
  Dim PortState As Byte
 
  // clear timer 1 interrupt flag and reload timer counter...
  TMR1 = TMR1 + TIMER_RELOAD
  TMR1IF = 0

  // disable all LEDS, then check each LED bit in turn - if set to
  // one, the LED is switched on
  TRISA = TRISA Or %11000001
  If (smState And LED) <> 0 Then
      Select smState
        Case 1
            High(PORTA.0)
            Low (PORTA.6)
        Case 2   
            Low (PORTA.0)
            High(PORTA.6)     
        Case 4   
            High(PORTA.6)
            Low (PORTA.7)     
        Case 8   
            Low (PORTA.6)
            High(PORTA.7)     
        Case 16     
            Low (PORTA.0)
            High(PORTA.7)     
        Case 32     
            High(PORTA.0)
            Low (PORTA.7)     
      End Select
  EndIf

  // next LED state...
  smState = smState << 1
  If smState.6 = 1 Then
      smState = 1
  EndIf 
 
  // read PORTB and mask non-button pins...
  PortState = PORTB And %00100101
 
  // check for button debounce...
  If Debounce > 0 Then
      Dec(Debounce)
     
      // if debounce has expired and the button press state remains the same,
      // we need to set the correct bits for our public 'button' variable
      If (Debounce = 0) And (PortState = LastButton) Then
        If PortState.0 = 0 Then
            Button.0 = 1
        EndIf
        If PortState.2 = 0 Then
            Button.1 = 1
        EndIf
        If PortState.5 = 0 Then
            Button.2 = 1
        EndIf
      EndIf
 
  // no debounce, see if a button has been pressed... 
  ElseIf PortState <> LastButton Then
      Debounce = TIMER_DEBOUNCE
      LastButton = PortState
  EndIf
End Interrupt
{
****************************************************************************
* Name    : IsPressed (PUBLIC)                                            *
* Notes  : Returns true if a button has been pressed. You should pass    *
*        : the pre-defined constants Btn1, Btn2 or Btn3 to this routine.  *
*        : The 'Button' bit is automatically cleared whan a call is made  *
*        : this routine. If you use the 'Button' variable directly in    *
*        : your program, you will need to clear its state flag manually  *                                                  *
****************************************************************************
}
Public Function IsPressed(pButton As Byte) As Boolean
  Disable(ISR)
  result = (Button And pButton) > 0
  Button = Button And Not pButton
  Enable(ISR)
End Function

// the first piece of code we must always execute is to select
// either internal 4 or 8Mhz clock - this depends on the 'clock' value
// set in the main program...
#if _clock = 4
OSCCON = $62       
#elseif _clock = 8
OSCCON = $72
#endif

// initialise the module...
smState = 1        // initialise LED state machine
LED = 0            // all LEDs are off
Button = 0          // no buttons pressed
INTCON2.7 = 0      // enable weak pullups on PORTB
Debounce = 0        // clear debounce
ADCON1 = %11110101  // all digital, except RA1 and RA3
TMR1 = TIMER_RELOAD // initialise timer 1
TMR1IF = 0          // clear timer interrupt flag
TMR1IE = 1          // enable timer 1 interrupts
T1CON = $01        // prescale 1:1, switch timer on
Enable(ISR)        // enable interrupt handler
=]