Public Constants and Modules

General discussion relating to the library modules supplied with the compiler

Moderators: David Barker, Jerry Messina

Post Reply
xor
Posts: 286
Joined: Sun Nov 05, 2006 1:15 pm
Location: NYC
Contact:

Public Constants and Modules

Post by xor » Wed Sep 26, 2007 7:54 pm

I added a new sub to the PWM module which uses a public constant array declared in the main program. I am getting errors such "Incompatible types" and "Identifier not delcared: pwmpsc" and also for pwmpr2. Anything I've missed doing?

Added Subroutine to PWM.bas:

Code: Select all

Public Sub SetToIndex(pIndex As Byte)
 Dim prv As Byte  
  prv = pwmpr2(pIndex)                             // get new PR2 value from array
  PR2 = prv                                        // load PR2
  SetDuty(0)                                       // no pwm output
  T2CON = pwmpsc(pIndex) Or 4                      // get new prescaler value from array and load
  Start
  Max_Duty = Word((prv + 1) << 2)                 // calculate max duty cycle
End Sub
Public Constant Arrays declared in main program module:

Code: Select all

Public Const pwmpr2(1) As Byte =  (249)
Public Const pwmpsc(1) As Byte =   (1)

User avatar
Steven
BETA Tester
Posts: 406
Joined: Tue Oct 03, 2006 8:32 pm
Location: Cumbria, UK

Post by Steven » Wed Sep 26, 2007 8:11 pm

Since you include the PWM module before the const array declare, I'm guessing that the module does not yet know about the array. Dave added a prototypes structure to the compiler in the last update, and although I haven't used it yet, I think that it's for doing forward declarations. It might help? Or I might be completely wrong...! Might be worth a look.

Regards,

Steve

xor
Posts: 286
Joined: Sun Nov 05, 2006 1:15 pm
Location: NYC
Contact:

Post by xor » Wed Sep 26, 2007 8:14 pm

Thanks Steve. I tried that to no avail.

Code: Select all

Public Const pwmpr2(2) As Byte =  (249, 248)
Public Const pwmpsc(2) As Byte =   (1, 1)

Include "pwm.bas"

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Wed Sep 26, 2007 8:32 pm

Swordfish implements scoping rather like Pascal as opposed to C. There are compelling reasons why you would want to do this, but that's probably a discussion for another time. Anyway, your problem is this:

Your main program can see all public declarations from PWM. However, PWM cannot see anything declared in your main program. Your declarations

Code: Select all

Public Const pwmpr2(1) As Byte =  (249)
Public Const pwmpsc(1) As Byte =   (1)
Have to be declared in (a) the PWM module itself or (b) in another module, which is included in PWM (and your main program, if required)

Swordfish scoping and visibility are important topics to understand - if you need to discuss further or require more detailed explanation, please let me know.

xor
Posts: 286
Joined: Sun Nov 05, 2006 1:15 pm
Location: NYC
Contact:

Post by xor » Wed Sep 26, 2007 8:41 pm

David,

I figured that this was the issue and I can surely work with it. Does this mean that there is no reason for declaring anything public inside the main program?

Would it be possible to utilize an include of the main module (main program) inside the PWM.bas module to access its consts/vars? ***I re-read your comments and think this part is answered in the affirmative.***

User avatar
Steven
BETA Tester
Posts: 406
Joined: Tue Oct 03, 2006 8:32 pm
Location: Cumbria, UK

Post by Steven » Wed Sep 26, 2007 8:51 pm

I think your module includes have to come first - I wasn't suggesting swapping them around. I've had a look at the prototypes structure, but I think it's only for forward declaration of subs and functions. How about passing the const arrays to the sub as parameters (by ref?), so avoiding the issue of forward declaration? It would probably be better for a module anyway?

Steve

Edit: oops, a little too late; I hadn't thought of scoping! The parameter option might still help though and avoid having to include an extra module.

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Wed Sep 26, 2007 9:03 pm

> Would it be possible to utilize an include of the
> main module (main program) inside the PWM.bas module

No, you cannot include a program in a module. I assume you arrays would have more than one element each - what values would they possibly have? Would they change from program to program and if so, in what way? I'm just trying to get a feel for what you are planning in order to come up with something that is workable...

xor
Posts: 286
Joined: Sun Nov 05, 2006 1:15 pm
Location: NYC
Contact:

Post by xor » Wed Sep 26, 2007 9:08 pm

I have created a VB program that calculates all possible frequencies for the PWM module and will create a constant array based on the user's click selection of 1 or many different frequencies and ideal resolution from the list. The array will copy to the clipboard to be pasted wherever. The programmer can simply access different exact frequencies/resolutions by indexing the custom made array.

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Wed Sep 26, 2007 9:12 pm

Sounds interesting - could you post or email a sample array(s)

xor
Posts: 286
Joined: Sun Nov 05, 2006 1:15 pm
Location: NYC
Contact:

Post by xor » Wed Sep 26, 2007 9:32 pm

Sure. Let me get some more done on the program and I will send it to you.

Doj
Posts: 362
Joined: Wed Apr 11, 2007 10:18 pm
Location: East Sussex

Post by Doj » Thu Sep 27, 2007 11:27 am

xor,
I have found sometimes two modules find it impossible to see the declared variables in each others so I have a "main" Const and DIM module that is declared in both modules which then allows them both to see the required values.

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Thu Sep 27, 2007 11:28 am

I had a thought this morning - if you are automatically generating a lookup table, then it might be an idea to consider the following format

Code: Select all

Const PWMTable(2) As Byte =  (249, 1)
where you have PR2 and prescale pairs. You could then use something like the following

Module Code

Code: Select all

// read ROM helper...
Inline Function ReadROM() As TABLAT
   ASM
   TBLRD*+      
   End ASM
End Function

// set lookup table...
Dim LookupAddr As Word
Public Sub SetLookup(ByRefConst pLookup() As Byte)
   LookupAddr = @pLookup
End Sub

// set to index...
Public Sub SetToIndex(pIndex As Byte)
  TABLEPTR = LookupAddr
  PR2 = ReadROM    
  SetDuty(0)  
  T2CON = ReadROM Or 4   
  Start
  Max_Duty = (PR2 + 1) << 2 
End Sub
Now you can have the lookup table in your main program, like this

Program Code

Code: Select all

Include "pwm.bas"

Const PWMTable(2) As Byte =  (249, 1)

PWM.SetLookup(PWMTable)
PWM.SetToIndex(0)
Basically, you initialise with a call to 'SetLookup()' at the beginning of your program, then you can call 'SetToIndex()' as many times as you want. You could easily modify it to support two tables (as your original code) but the single table is far more efficient in terms of reading from ROM.

xor
Posts: 286
Joined: Sun Nov 05, 2006 1:15 pm
Location: NYC
Contact:

Post by xor » Sun Sep 30, 2007 2:07 am

The PWM Table Writer is here: The result SF code should be copied/pasted directly into the (new name) SetFreqByTable() function added to the PWM module.

I also tweaked up the SetFreq() function and added support for 2 PWM outputs, standard for most PIC18. Here is the revised module:

Code: Select all

{
*****************************************************************************
*  Name    : PWM.BAS                                                        *
*  Author  : David John Barker & Warren Schroeder                           *
*  Notice  : Copyright (c) 2007 Mecanique                                   *
*          : All Rights Reserved                                            *
*  Date    : 23/08/2007                                                     *
*  Version : 1.0                                                            *
*  Notes   : 29/09/2007 - Added support for 2 PWM outputs                   *                    
*                       - Added FreqSetByTable() function                   *
*                       - PWM Table Writer Utility available at             *
*                          http://circuit-ed.com/uplds/pwm_writer.exe       *
*****************************************************************************
}                                                                                                                 
Module PWM
Dim
   FMaxDuty As Word,
   FTMR2ON As T2CON.2
#if _device in (18F1220, 18F1320)
   Dim FPWM1Pin As PORTB.3    // RB3 connected to CCP1 module
#else
   Dim FPWM1Pin As PORTC.2    // RC2 connected to CCP1 module
   Dim FPWM2Pin As PORTC.1    // RC1 connected to CCP2 module
#endif
{
****************************************************************************
* Name    : Start1                                                         *
* Purpose : Start PWM Channel 1                                            *
****************************************************************************
}  
Public Sub Start1()
    CCP1CON = $0C
    Output(FPWM1Pin) 
    FTMR2ON = 1   
End Sub
{
****************************************************************************
* Name    : Start2                                                         *
* Purpose : Start PWM Channel 2                                            *
****************************************************************************
}  
Public Sub Start2()
    CCP2CON = $0C
    Output(FPWM2Pin) 
    FTMR2ON = 1   
End Sub
{
****************************************************************************
* Name    : Stop1                                                          *
* Purpose : Stop PWM Channel 1                                             *
****************************************************************************
}  
Public Sub Stop1()
   Input(FPWM1Pin)
   CCP1CON = $00
End Sub
{
****************************************************************************
* Name    : Stop2                                                          *
* Purpose : Stop PWM Channel 2                                             *
****************************************************************************
}  
Public Sub Stop2()
   Input(FPWM2Pin)
   CCP2CON = $00
End Sub
{
****************************************************************************
* Name    : SetDuty1                                                       *
* Purpose : The CCPR1L contains the eight MSbs And the CCP1CON<5:4>        *
*         : contains the two LSbs. This 10-Bit value is represented by     *
*         : CCPR1L:CCP1CON<5:4>.                                           *
****************************************************************************
} 	
Public Sub SetDuty1(pDuty As Word)
   CCP1CON.5 = pDuty.1
   CCP1CON.4 = pDuty.0	
   CCPR1L = pDuty >> 2
End Sub
{
****************************************************************************
* Name    : SetDuty2                                                       *
* Purpose : The CCPR2L contains the eight MSbs And the CCP2CON<5:4>        *
*         : contains the two LSbs. This 10-Bit value is represented by     *
*         : CCPR2L:CCP2CON<5:4>.                                           *
****************************************************************************
} 	
Public Sub SetDuty2(pDuty As Word)
   CCP2CON.5 = pDuty.1
   CCP2CON.4 = pDuty.0	
   CCPR2L = pDuty >> 2
End Sub
{
****************************************************************************
* Name    : SetDuty1Percent                                                *
* Purpose : Set the duty as a percentage for channel 1                     *
****************************************************************************
} 	
Public Sub SetDuty1Percent(pPercent As Byte)
   SetDuty1(FMaxDuty * pPercent / 100)
End Sub
{
****************************************************************************
* Name    : SetDuty2Percent                                                *
* Purpose : Set the duty as a percentage for channel 2                     *
****************************************************************************
} 	
Public Sub SetDuty2Percent(pPercent As Byte)
   SetDuty2(FMaxDuty * pPercent / 100)
End Sub
{
****************************************************************************
* Name    : MaxDuty                                                        *
* Purpose :                                                                *
****************************************************************************
}   
Public Inline Function MaxDuty() As FMaxDuty
End Function
{
****************************************************************************
* Name    : SetFreq                                                        *
* Purpose :                                                                *
* Notes   : Initializes Freq settings                                      * 
*         : Resets Duty Cycle To 0                                         *
*         : Requires PWM.Start afterward if PWM is not running             *               
****************************************************************************
} 
Public Function SetFreq(pFrequency As LongWord) As Boolean
   Const Fosc As LongWord = _clock * 1000000
   Dim Prescale As Byte
   Dim PR2Value, PRConst As Word

   // loop through all the valid prescalers...
   PRConst = Fosc / pFrequency / 4
   Prescale = 1
   Result = false
   Repeat
      PR2Value = PRConst / Prescale - 1        // calculate a PR2 value
      If PR2Value < 256 Then                   // if it is a valid value, then... 
         FMaxDuty = (PR2Value + 1) * 4         // determine maximum duty... 
	     PR2 = PR2Value                        // initialise PR2                 
         Select Prescale                       // configure T2CON prescale
            Case 1  : Prescale = %00000000     // prescale 1
	        Case 4  : Prescale = %00000001     // prescale 4
	        Case 16 : Prescale = %00000011     // prescale 16
         End Select
         SetDuty1(0)                           // output = 0V
         SetDuty2(0)                           //
         T2CON = (T2CON And 252) Or Prescale   // load prescaler value
         Result = true                         // function return true (success)         
         Exit                                  // exit the sub
      EndIf   
      Prescale = Prescale * 4
   Until Prescale > 16
End Function
{
****************************************************************************
* Name    : SetFreqByTable                                                 *
* Purpose : Change PWM frequency settings by indexing table                *
* Notes   : Initializes Freq settings                                      * 
*         : Resets Duty Cycle To 0                                         *
*         : Requires PWM.Start afterward if PWM is not running             *               
****************************************************************************
}
Public Sub SetFreqByTable(pIndex As Byte)
 Const pwmtbl(4) As Byte = (255,1,127,3)
  // (Fosc=48) 11719; 5859; 
 Dim prv As Byte

   pindex = pindex * 2                          // table offset value
   prv = pwmtbl(pindex)                         // get new PR2 value from array for frequency value
   FMaxDuty = (prv + 1) * 4                     // maximum duty cycle resolution based on PR2 value  
   PR2 = prv                                    // load PR2
   SetDuty1(0)                                  // output = 0V
   SetDuty2(0)                                  //
   T2CON = (T2CON And 252) Or pwmtbl(pindex+1)  // load prescaler value from array
End Sub

// initialise the module
FMaxDuty = 0

xor
Posts: 286
Joined: Sun Nov 05, 2006 1:15 pm
Location: NYC
Contact:

Post by xor » Sun Sep 30, 2007 9:35 pm

Here is a screenshot of the PWM Table Writer Utility for SF:
  • Image

Post Reply