News:

;) This forum is the property of Proton software developers

Main Menu

Mirror Bit angle modulation

Started by Pepe, Sep 04, 2023, 11:41 PM

Previous topic - Next topic

Pepe

Simulation in Proteus Mirror Bit angle modulation in 8 independent outputs

Pepe

source mibam

John Lawton

Hi Pepe,
thanks for posting this. I haven't tried the code yet but I assume it is based on Darrel Taylor's original PicBasicPro code. Does it fade smoothly or are there a transition point(s) where flicker occurs?

John

Pepe

I have not made the hardware, nor the mibam.pbp library, I made my own program deducing the theory of operation, I hope it is correct. If you can try it and let me know.

top204

An excellent mechanism Pepe and many thanks for it.

I have altered the code listing so it is easier to understand and alter the timings and also easier to alter the pins used for the MIBAM outputs, but it is still your code mechanism, and I must admit, I do not fully understand its mechanism 100% yet, but your code seems to operate excellently. Also, because the modified code listing is using meta-macros for Timer0 and other SFRs, it is very much easier to adapt for other devices that have a different requirement for their SFRs or different names for them or their bits.

The pins that will be used for the MIBAM channels can be changed by the $defines at the top of the program's listing, and if they are not $defined, they will not be used:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Mirror Bit Angle Modulation mechanism, created by Pepe on the forum
'
' Modified by Les Johnson for the Positron8 compiler.
'
    Device = 18F26K22                                   ' Tell the compiler what device to compile for
    Declare Xtal = 64                                   ' Tell the compiler what frequency the device will be operating at (in MHz)
    On_Hardware_Interrupt GoTo ISR_Handler              ' Point to the Interrupt Handler
'
' Set the pins to use for the MIBAM outputs
'
$define MIBAM_Pin0 PORTB.0                              ' Set the pin to use for MIBAM channel 0
$define MIBAM_Pin1 PORTB.1                              ' Set the pin to use for MIBAM channel 1
$define MIBAM_Pin2 PORTB.2                              ' Set the pin to use for MIBAM channel 2
$define MIBAM_Pin3 PORTB.3                              ' Set the pin to use for MIBAM channel 3
$define MIBAM_Pin4 PORTB.4                              ' Set the pin to use for MIBAM channel 4
$define MIBAM_Pin5 PORTB.5                              ' Set the pin to use for MIBAM channel 5
$define MIBAM_Pin6 PORTB.6                              ' Set the pin to use for MIBAM channel 6
$define MIBAM_Pin7 PORTB.7                              ' Set the pin to use for MIBAM channel 7

    Dim MIBAM_wTimer0 As TMR0L.Word                     ' Combine TMR0L and TMR0H into a 16-bit SFR

'------------------------------------------------------------------------------
$define IntGlobal_Enable()  INTCONbits_GIE = 1          ' Enable global interrupts
$define IntGlobal_Disable() INTCONbits_GIE = 0          ' Disable global interrupts
$define IntPeriph_Enable()  INTCONbits_GIEL = 1         ' Enable peripheral interrupts
$define IntPeriph_Disable() INTCONbits_GIEL = 0         ' Disable peripheral interrupts

'------------------------------------------------------------------------------
' Timer0 Meta-Macros for a PIC18F26K22 device
'
$define Timer0_Flag()       INTCONbits_T0IF             ' Timer0 Flag
$define Timer0_FlagClear()  Timer0_Flag() = 0           ' Clear the Timer0 interrupt flag
$define Timer0_IntEnable()  INTCONbits_TMR0IE = 1       ' Enable a Timer0 interrupt
$define Timer0_IntDisable() INTCONbits_TMR0IE = 0       ' Disable a Timer0 interrupt
$define Timer0_Start()      T0CONbits_TMR0ON = 1        ' Start Timer0
$define Timer0_Stop()       T0CONbits_TMR0ON = 0        ' Stop Timer0
'
' Alter the bits for a required Timer0 Prescaler on a PIC18F26K22 Device
'
$define Timer0_Prescaler(pPrescaler)'
    $if pPrescaler = 2              '
        T0CONbits_T0PS0 = 0         '
        T0CONbits_T0PS1 = 0         '
        T0CONbits_T0PS2 = 0         '
    $elseif pPrescaler = 4          '
        T0CONbits_T0PS0 = 1         '
        T0CONbits_T0PS1 = 0         '
        T0CONbits_T0PS2 = 0         '
    $elseif pPrescaler = 8          '
        T0CONbits_T0PS0 = 0         '
        T0CONbits_T0PS1 = 1         '
        T0CONbits_T0PS2 = 0         '
    $elseif pPrescaler = 16         '
        T0CONbits_T0PS0 = 1         '
        T0CONbits_T0PS1 = 1         '
        T0CONbits_T0PS2 = 0         '
    $elseif pPrescaler = 32         '
        T0CONbits_T0PS0 = 0         '
        T0CONbits_T0PS1 = 0         '
        T0CONbits_T0PS2 = 1         '
    $elseif pPrescaler = 64         '
        T0CONbits_T0PS0 = 1         '
        T0CONbits_T0PS1 = 0         '
        T0CONbits_T0PS2 = 1         '
    $elseif pPrescaler = 128        '
        T0CONbits_T0PS0 = 0         '
        T0CONbits_T0PS1 = 1         '
        T0CONbits_T0PS2 = 1         '
    $elseif pPrescaler = 256        '
        T0CONbits_T0PS0 = 1         '
        T0CONbits_T0PS1 = 1         '
        T0CONbits_T0PS2 = 1         '
    $else                           '
        $error "Unknown Timer0 prescaler value. Supported values for this device are 2 or 4 or 8 or 16 or 32 or 64 or 128 or 256" '
    $endif

'----------------------------------------------------------------------------------------
' Calculate the value to place into the TMR0L\H registers in order to achieve a certain overflow interrupt rate (in us)
'
$define Timer0_cPrescaler 2                                                     ' The prescaler used for the timer (must be the same prescaler as used for the timer's setup)
$define Timer0_cMicroSeconds 100                                                ' Interrupt rate (in uS)
$define Timer0_cTweakValue 0                                                    ' Holds a tweak value for the timer calculation

$define Timer0_cValue $eval ((65536 + Timer0_cTweakValue) - ((Timer0_cMicroSeconds / Timer0_cPrescaler) * (_xtal / 4)))

$if Timer0_cValue > 65535
    $error "Timer0_cValue is too large for the interrupt duration"
$elseif Timer0_cValue <= 0
    $error "Timer0_cValue is too small for the interrupt duration"
$endif

'----------------------------------------------------------------------------------------
$define PLL_Enable() OSCTUNEbits_PLLEN = 1                                      ' PLL enable
$define PLL_ReadyFlag() OSCCON2bits_PLLRDY                                      ' PLL run status

$ifndef True
    $define True 1
$endif
$ifndef False
    $define False 0
$endif

'----------------------------------------------------------------------------------------
' Create variables and constants for the program
'
    Dim MIBAM_bDutyCycle0 As Byte                                               ' Holds the 8-bit duty cycle value for the MIBAM channel 0 pin
    Dim MIBAM_bDutyCycle1 As Byte                                               ' Holds the 8-bit duty cycle value for the MIBAM channel 1 pin
    Dim MIBAM_bDutyCycle2 As Byte                                               ' Holds the 8-bit duty cycle value for the MIBAM channel 2 pin
    Dim MIBAM_bDutyCycle3 As Byte                                               ' Holds the 8-bit duty cycle value for the MIBAM channel 3 pin
    Dim MIBAM_bDutyCycle4 As Byte                                               ' Holds the 8-bit duty cycle value for the MIBAM channel 4 pin
    Dim MIBAM_bDutyCycle5 As Byte                                               ' Holds the 8-bit duty cycle value for the MIBAM channel 5 pin
    Dim MIBAM_bDutyCycle6 As Byte                                               ' Holds the 8-bit duty cycle value for the MIBAM channel 6 pin
    Dim MIBAM_bDutyCycle7 As Byte                                               ' Holds the 8-bit duty cycle value for the MIBAM channel 7 pin

    Dim MIBAM_bState      As Byte Access
    Dim MIBAM_bBitPos     As Byte Access                                        ' Start from the 1st bit (0) of MIBAM_bBitTable table
    Dim MIBAM_bTemp       As Byte Access
    Dim MIBAM_wMsCounter  As Word Access
    Dim MIBAM_tReady      As Bit
    Dim MIBAM_tDelFlag    As Bit
    Dim MIBAM_bBitTable   As Flash8 = 1, 2, 4, 8, 16, 32, 64, 128               ' Create the BAM table in flash memory

    Symbol cMIBAM_Bits = SizeOf(MIBAM_bBitTable)                                ' This is the number of bits that are used in MIBAM_bBitTable: 8 bits for 256 PWM levels
    Symbol cMIBAM_DelayTime = 255
    Symbol cMIBAM_DelayTimeX2 = (cMIBAM_DelayTime * 2)

'----------------------------------------------------------------------------------------
' The main program starts here
' Cycle the duty cycles of all 8 MIBAM pins
'
Main:
    Setup()                                                                     ' Setup the program

    MIBAM_bDutyCycle0 = 1
    MIBAM_bDutyCycle1 = 2
    MIBAM_bDutyCycle2 = 4
    MIBAM_bDutyCycle3 = 8
    MIBAM_bDutyCycle4 = 16
    MIBAM_bDutyCycle5 = 32
    MIBAM_bDutyCycle6 = 64
    MIBAM_bDutyCycle7 = 128

    Do                                                                          ' Create a loop
        If MIBAM_tReady = True Then                                             ' Is it OK to alter the duty cycles?
            MIBAM_tReady = False                                                ' Yes. So reset the flag
            Inc MIBAM_bDutyCycle0                                               ' Increase the Duty Cycle for MIBAM_Pin0
            Inc MIBAM_bDutyCycle1                                               ' Increase the Duty Cycle for MIBAM_Pin1
            Inc MIBAM_bDutyCycle2                                               ' Increase the Duty Cycle for MIBAM_Pin2
            Inc MIBAM_bDutyCycle3                                               ' Increase the Duty Cycle for MIBAM_Pin3
            Inc MIBAM_bDutyCycle4                                               ' Increase the Duty Cycle for MIBAM_Pin4
            Inc MIBAM_bDutyCycle5                                               ' Increase the Duty Cycle for MIBAM_Pin5
            Inc MIBAM_bDutyCycle6                                               ' Increase the Duty Cycle for MIBAM_Pin6
            Inc MIBAM_bDutyCycle7                                               ' Increase the Duty Cycle for MIBAM_Pin7

            If MIBAM_bDutyCycle0 = 255 Then MIBAM_bDutyCycle0 = 0
            If MIBAM_bDutyCycle1 = 255 Then MIBAM_bDutyCycle1 = 0
            If MIBAM_bDutyCycle2 = 255 Then MIBAM_bDutyCycle2 = 0
            If MIBAM_bDutyCycle3 = 255 Then MIBAM_bDutyCycle3 = 0
            If MIBAM_bDutyCycle4 = 255 Then MIBAM_bDutyCycle4 = 0
            If MIBAM_bDutyCycle5 = 255 Then MIBAM_bDutyCycle5 = 0
            If MIBAM_bDutyCycle6 = 255 Then MIBAM_bDutyCycle6 = 0
            If MIBAM_bDutyCycle7 = 255 Then MIBAM_bDutyCycle7 = 0
        EndIf
        DelayMS 1000                                                            ' Create a large delay so the duty cycles can be seen altering on an oscilloscope
    Loop                                                                        ' Do it forever

'----------------------------------------------------------------------------------------
' Setup the program
' Input     : None
' Output    : None
' Notes     : None
'
Proc Setup()
    Osc_Int64MHz()                                                              ' Setup the device to operate at 64MHz with its internal oscillator
'
' Set all the MIBAM pins used to output low mode
'
$ifdef MIBAM_Pin0                                                               ' Has MIBAM_Pin0 been $defined?
    PinLow MIBAM_Pin0                                                           ' Yes. So set it as an output low
$endif
$ifdef MIBAM_Pin1                                                               ' Has MIBAM_Pin1 been $defined?
    PinLow MIBAM_Pin1                                                           ' Yes. So set it as an output low
$endif
$ifdef MIBAM_Pin2                                                               ' Has MIBAM_Pin2 been $defined?
    PinLow MIBAM_Pin2                                                           ' Yes. So set it as an output low
$endif
$ifdef MIBAM_Pin3                                                               ' Has MIBAM_Pin3 been $defined?
    PinLow MIBAM_Pin3                                                           ' Yes. So set it as an output low
$endif
$ifdef MIBAM_Pin4                                                               ' Has MIBAM_Pin4 been $defined?
    PinLow MIBAM_Pin4                                                           ' Yes. So set it as an output low
$endif
$ifdef MIBAM_Pin5                                                               ' Has MIBAM_Pin5 been $defined?
    PinLow MIBAM_Pin5                                                           ' Yes. So set it as an output low
$endif
$ifdef MIBAM_Pin6                                                               ' Has MIBAM_Pin6 been $defined?
    PinLow MIBAM_Pin6                                                           ' Yes. So set it as an output low
$endif
$ifdef MIBAM_Pin7                                                               ' Has MIBAM_Pin7 been $defined?
    PinLow MIBAM_Pin7                                                           ' Yes. So set it as an output low
$endif

    MIBAM_bDutyCycle0 = 0
    MIBAM_bDutyCycle1 = 0
    MIBAM_bDutyCycle2 = 0
    MIBAM_bDutyCycle3 = 0
    MIBAM_bDutyCycle4 = 0
    MIBAM_bDutyCycle5 = 0
    MIBAM_bDutyCycle6 = 0
    MIBAM_bDutyCycle7 = 0

    MIBAM_tReady = False
    MIBAM_tDelFlag = False
    MIBAM_bState = 0
    MIBAM_bBitPos = 0                                                           ' Start from the 1st bit (0) of MIBAM_bBitTable table
    MIBAM_wMsCounter = cMIBAM_DelayTime

    Timer0_Setup()                                                              ' Setup Timer0
    IntPeriph_Enable()                                                          ' Enable peripheral interrupts
    IntGlobal_Enable()                                                          ' Enable global interrupts
EndProc

'----------------------------------------------------------------------------------------
' Setup Timer0
' Input     : None
' Output    : None
' Notes     : Sets Timer0 up for an overflow interrupt
'
Proc Timer0_Setup()
    T0CON = 0
    Timer0_Prescaler(Timer0_cPrescaler)                                         ' Set the prescaler value for Timer0
    MIBAM_wTimer0 = Timer0_cValue                                               ' Load the value for a specific overflow time
    Timer0_FlagClear()                                                          ' Clear the Timer0 interrupt flag
    Timer0_IntEnable()                                                          ' Enable a Timer0 interrupt
    Timer0_Start()                                                              ' Start Timer0
EndProc

'----------------------------------------------------------------------------------------
' Set the 18F26K22 device to use its internal oscillator at 64MHz
' Input     : None
' Output    : None
' Notes     : None
'
Proc Osc_Int64MHz()
    OSCCON = 0b01111100                                                         ' Setup for the internal 16MHz oscillator
    PLL_Enable()                                                                ' Enable 4xPLL
    Repeat: Until PLL_ReadyFlag() = 1                                           ' Wait for the PLL to become stable
EndProc

'----------------------------------------------------------------------------------------
' Interrupt Handler
' Input     : None
' Output    :
' Notes     : Handles a Timer0 overflow interrupt
'
ISR_Handler:
    Context Save                                                                ' Save any compiler system variables and SFRs used within the interrupt handler

    If Timer0_Flag() = True Then
        If MIBAM_bState = 0 Then                                                ' When MIBAM_bState = 0, set the duty cycle state bits
            $ifdef MIBAM_Pin0                                                   ' Has MIBAM_Pin0 been $defined?
                MIBAM_bTemp = MIBAM_bDutyCycle0 >> MIBAM_bBitPos                ' \
                MIBAM_Pin0 = MIBAM_bTemp.0                                      ' / Yes. So set its bit pattern
            $endif
            $ifdef MIBAM_Pin1                                                   ' Has MIBAM_Pin1 been $defined?
                MIBAM_bTemp = MIBAM_bDutyCycle1 >> MIBAM_bBitPos                ' \
                MIBAM_Pin1 = MIBAM_bTemp.0                                      ' / Yes. So set its bit pattern
            $endif
            $ifdef MIBAM_Pin2                                                   ' Has MIBAM_Pin2 been $defined?
                MIBAM_bTemp = MIBAM_bDutyCycle2 >> MIBAM_bBitPos                ' \
                MIBAM_Pin2 = MIBAM_bTemp.0                                      ' / Yes. So set its bit pattern
            $endif
            $ifdef MIBAM_Pin3                                                   ' Has MIBAM_Pin3 been $defined?
                MIBAM_bTemp = MIBAM_bDutyCycle3 >> MIBAM_bBitPos                ' \
                MIBAM_Pin3 = MIBAM_bTemp.0                                      ' / Yes. So set its bit pattern
            $endif
            $ifdef MIBAM_Pin4                                                   ' Has MIBAM_Pin4 been $defined?
                MIBAM_bTemp = MIBAM_bDutyCycle4 >> MIBAM_bBitPos                ' \
                MIBAM_Pin4 = MIBAM_bTemp.0                                      ' / Yes. So set its bit pattern
            $endif
            $ifdef MIBAM_Pin5                                                   ' Has MIBAM_Pin5 been $defined?
                MIBAM_bTemp = MIBAM_bDutyCycle5 >> MIBAM_bBitPos                ' \
                MIBAM_Pin5 = MIBAM_bTemp.0                                      ' / Yes. So set its bit pattern
            $endif
            $ifdef MIBAM_Pin6                                                   ' Has MIBAM_Pin6 been $defined?
                MIBAM_bTemp = MIBAM_bDutyCycle6 >> MIBAM_bBitPos                ' \
                MIBAM_Pin6 = MIBAM_bTemp.0                                      ' / Yes. So set its bit pattern
            $endif
            $ifdef MIBAM_Pin7                                                   ' Has MIBAM_Pin7 been $defined?
                MIBAM_bTemp = MIBAM_bDutyCycle7 >> MIBAM_bBitPos                ' \
                MIBAM_Pin7 = MIBAM_bTemp.0                                      ' / Yes. So set its bit pattern
            $endif

            MIBAM_bState = Cread8 MIBAM_bBitTable[MIBAM_bBitPos]                ' Read the state from the flash memory table
            If MIBAM_tDelFlag = False Then
                Inc MIBAM_bBitPos
            Else
                Dec MIBAM_bBitPos
            EndIf
            MIBAM_bBitPos = MIBAM_bBitPos // cMIBAM_Bits
        EndIf
        Dec MIBAM_bState                                                        ' Countdown the time that the LED will remain in the same state
        Dec MIBAM_wMsCounter

        If MIBAM_wMsCounter = 0 Then
            MIBAM_tDelFlag = False                                              ' Total delay = cMIBAM_DelayTime / ((Fosc / 4) / Prescaler) / 256 msec
            MIBAM_tReady = True                                                 ' This flag is set when cMIBAM_DelayTime msec have elapsed
            MIBAM_wMsCounter = cMIBAM_DelayTimeX2
            MIBAM_bBitPos = 0

        ElseIf MIBAM_wMsCounter = cMIBAM_DelayTime Then
            MIBAM_tDelFlag = True
            MIBAM_bBitPos = cMIBAM_Bits - 1
        EndIf
        MIBAM_wTimer0 = Timer0_cValue                                           ' Re-load TMR0L\H with the value to give a specified overflow time
        Timer0_FlagClear()                                                      ' Clear the Timer0 interrupt flag
    EndIf
    Context Restore                                                             ' Restore any compiler system variables and SFRs used within the interrupt handler, and exit the interrupt

'----------------------------------------------------------------------------------------
' Setup the 18F26K22 device's fuse configs to use its internal oscillator
'
Config_Start
    FOSC = INTIO67                          ' Internal oscillator block
    PLLCFG = Off                            ' Oscillator used directly
    PRICLKEN = On                           ' Primary clock enabled
    FCMEN = Off                             ' Fail-Safe Clock Monitor disabled
    IESO = Off                              ' Oscillator Switchover mode disabled
    PWRTEN = On                             ' Power up timer enabled
    BOREN = Off                             ' Brown-out Reset disabled in hardware and software
    BORV = 190                              ' VBOR set to 1.90 V nominal
    WDTEN = Off                             ' Disable the watchdog timer
    WDTPS = 256                             ' Watchdog window is 1:256
    CCP2MX = PORTC1                         ' CCP2 input/output is multiplexed with RC1
    PBADEN = Off                            ' PORTB<5:0> pins are configured as digital I/O on Reset
    CCP3MX = PORTB5                         ' P3A/CCP3 input/output is multiplexed with RB5
    HFOFST = Off                            ' HFINTOSC output and ready status are not delayed by the oscillator stable status
    T3CMX = PORTB5                          ' T3CKI is on RB5
    P2BMX = PORTB5                          ' P2B is on RB5
    MCLRE = INTMCLR                         ' RE3 input pin enabled.  MCLR disabled
    STVREN = Off                            ' Stack full/underflow will not cause Reset
    LVP = Off                               ' Single-Supply ICSP disabled
    XINST = Off                             ' Instruction set extension and Indexed Addressing mode disabled
    Debug = Off                             ' Disabled
    Cp0 = On                                ' Block 0 (000800-003FFF) code-protected
    CP1 = On                                ' Block 1 (004000-007FFF) code-protected
    CP2 = On                                ' Block 2 (008000-00BFFF) code-protected
    CP3 = On                                ' Block 3 (00C000-00FFFF) code-protected
    CPB = On                                ' Boot block (000000-0007FF) code-protected
    CPD = Off                               ' Data EEPROM not code-protected
    WRT0 = On                               ' Block 0 (000800-003FFF) write-protected
    WRT1 = On                               ' Block 1 (004000-007FFF) write-protected
    WRT2 = On                               ' Block 2 (008000-00BFFF) write-protected
    WRT3 = On                               ' Block 3 (00C000-00FFFF) write-protected
    WRTC = On                               ' Configuration registers (300000-3000FF) write-protected
    WRTB = On                               ' Boot Block (000000-0007FF) write-protected
    WRTD = Off                              ' Data EEPROM not write-protected
    EBTR0 = Off                             ' Block 0 (000800-003FFF) not protected from table reads executed in other blocks
    EBTR1 = Off                             ' Block 1 (004000-007FFF) not protected from table reads executed in other blocks
    EBTR2 = Off                             ' Block 2 (008000-00BFFF) not protected from table reads executed in other blocks
    EBTR3 = Off                             ' Block 3 (00C000-00FFFF) not protected from table reads executed in other blocks
    EBTRB = Off                             ' Boot Block (000000-0007FF) not protected from table reads executed in other blocks
Config_End


Pepe

I am very happy Les that you have taken my program and modified it so that the community can use it. I saw that you removed the & 1 in the interrupt routine, I had placed it because transients appeared in the proteus simulation although I know that it was unnecessary to place it .

top204

#7
The problem with Darrel's code is that it is mostly written in assembler with a lot of macros that make it even more complex to understand, so it is not written in BASIC much. He was a good programmer and I wish he had moved over to Proton all of those years ago, but instead, he actually dis-respected it a few times for no real reason.

Then he was employed, third party, by melabs when most of the original programmers left and most of his code is pseudo assembler/BASIC because of the many lackings of the melabs Pro compiler. This makes his code very difficult to understand and very, very difficult to change for another device, even a device of the same family.


top204

#8
Thanks Pepe.

QuoteI saw that you removed the & 1 in the interrupt routine, I had placed it because transients appeared in the proteus simulation although I know that it was unnecessary to place it

I have made that section of code a lot more optimised and using the compiler's bit handling mechanisms, which makes it even more optimised. I split the expression with the "& 1" so that the compiler does not need to mask bit-0 using boolean methods in the longer expression that requires a temporary 16-bit expression stack element, and instead operates on bit-0 directly. It also allows different Port pins to be used and not just a single Port, so it could be extended or decreased in the Port pins used for the MIBAM waveforms.

When a Port's pin or SFR bit is the assignment, the compiler does not alter it directly whenever possible, so there is no transient. For example the code:

MIBAM_Pin0 = MIBAM_bTemp.0

Produces the assembler code:

F1_000275 equ $ ; in [MIBAM_MK2.BAS] PORTB.0  = MIBAM_bTemp.0
    btfsc MIBAM_bTemp,0,0
    bsf PORTB,0,0
    btfss MIBAM_bTemp,0,0
    bcf PORTB,0,0

See how the PORTB,0 is not altered until it is known what state it will finally be in?

If the code is always operated on an 18F device, the MIBAM_bTemp variable could be aliased to the PRODL SFR and the code would be a bit more optimised because it would require 1 byte less of RAM. :-) You will also have noticed that the variables that are used within the interrupt handler are made as Access types, so they do not need any RAM bank manipulation on an 18F device, and Bit types are always held in Access RAM on 18F devices with the compiler anyway, or in low RAM on 14-bit core device types, so they are automatically more efficient to use.

The Access directives could also be added to the duty cycle variables if extreme efficiency is required on an 18F device, but remember, there is only a certain amount of Access RAM on a device, and the compiler will fill it as much as it can then add the rest of the Access variables to RAM bank 0 (RAM bank 5 with newer 18F devices) so it is still very efficient but not as efficient as an Access type.

Also... If you look at the assembler code listing, you will see that the compiler does not use any library calls for the MIBAM code at all, making it extremely efficient to operate. The only library code call it uses is for the Delay 1000 command in the demo section.

Pepe

#9
For pic 16f628a