General discussion relating to the library modules supplied with the compiler
Moderators: David Barker, Jerry Messina
-
xor
- Posts: 286
- Joined: Sun Nov 05, 2006 1:15 pm
- Location: NYC
-
Contact:
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)
-
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"
-
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.***
-
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.
-
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.
-
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.
-
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: