MIBAM is a replacement for Pulse Width Modulation to allow for driving many more LEDs Using TIMER Interrupts. The heart of the feature is an Interrupt Routine that is compiled using MPASM.
I have all the original sample source (attached) and I am trying to implement MIBAM using GCB but I am having issues with getting the interrupt routine to work. Is there any examples or tutorials about using Assembly code with GCB? I have looked at the information about interrupts but I can always use more knowledge as I find interrupt handling confusing.
Since I am a bit weak in the area of interrupt handling and also new to GCB it is possible I am going at this all wrong and maybe should just code this all in GCB and let the GCB Compiler do all the heavy lifting.
I am more than willing to do all the work figuring this out but would like some feedback from those that are more knowledgeable with GCB as to how best to get this working.
Why do this at all? There are PICs that support many more PWMs than PICs did in 2009.
How many PWMs are required?
The port. This port is relatively simple. Do not use ASM.
GCBASIC will create optimised ASM for you and it will be portable across the different chip architectures.
I have reviewed the PHP and it the ISR is essentially a CASE-SELECT supporting the 8 PWM channels. There is code that will not port as it specific to specific chips but GCBASIC will handle all the context stuff anyway.
How far have you got in GCBASIC?
We can help!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I got your ' PCA9685 routines for the GCBASIC compiler
' Copyright (C) 2018 Evan R. Venn
16 channel but i2c but today and think I used it for 2 stepper motor drives
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
There is an assumption of 8 LEDs/ports with no checking that the eight are defined in the user program. Which means the interrupt handles 8 even if they are not defined.
The calcs for the Interrupt latency are hard coded. This will have to made a real calculation for the chip.
The code has limited documentation. I think I know what the ISR is doing.
The user program is relatively simple. This is a 15 minote port. I can post that... but, the library will be based on what you have.
Evan
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Another one that I need explaining, andwf BAM_Buffers#v(FDutyVar), W - the use of BAM_Buffers#v(FDutyVar).
My analysis. CylonMask AND BAM_Buffers(BuffPointer) Then so something
// movf _CylonMask, W
// andwf BAM_Buffers#v(FDutyVar), W
// btfss STATUS,Z ; copy Inverted Z to the Pin
// bsf LATport,Pin
// btfsc STATUS,Z
// bcf LATport,Pin
New code coulde be ...
if ( CylonMask AND BAM_Buffers( BuffPointer) ) =1 then
Port_Pin = 1
else
Port_Pin = 0
end if
MOVE?BB FDutyVar, BAM_Buffers#v(FDutyVar)
What is this MOVE?BB. Same addressing code but as this will be explain above this question is in relation to to MOVE?BB
The interrupt is easy. It is the rest of the code... :-)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This is optimised by the compiler and generates the same ASM.
However, this is meaningless in the context that the rest of the library does not work. :-(
I am certain the values of BAM_PeriodX are totally incorect.
Note: There is no need for ISR context management as this is managed by GCBASIC. Lots of other code in the original ISR address issues in the orginal compiler and again these are not needed.
;----[Interrupt handler for BAM-BAM]----------------------------------------
Thank you for all your comments and especially @evanvennn. I fully understand this was written at a time when PICs had a lot fewer PWM modules available but I have a lot of those older PICs in my stockpile that I would like to use. I like using GCBasic and lot better than anything else so I have been slowing moving all my project over to GCBasic and this particular module was one I just could not seem to work out. However you have really answered my basic question as it looks like I should not port this over but just recreate this in GCBasic as the compiler will do what the MPASM compiler did for the original code and that is create an optimized ISR.
Thank you all again for your very helpful feedback.
David
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I get the rational now. Thanks for the explanation.
The ISR is replica of the original and it is just wrong. The ISR prevents the 7th bit from being set. So, this means the resolution is 7-bit not 8-bit.
I am working through the ISR at the moment changing it to 8-bit. Then, the rest should work.
The huge advantage we have with GCBASIC is we can easily add serial debug that 'back in the day ' adding debug was a major task. The demo code has a scope for debug. I added serial debug to the ISR to check the bit rotation and the errors at both ends of the direction change is very obvious.
I will post an update soon.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Yes. I can see the signals. The issue is that no 7th bit pulse, and, bit 0 is pused twice when rotation is left and once when rotation is right. That cannot be correct .
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm probably missing something... I don't see where that happens. What 7th bit do you mean?
As I see it, the actual output is done by PinList (which resolves to the BAM_LIST macro), and that has all eight bits of PORTD defined
CylonMask gets bit-shifted 7->0->7->0..., and there are eight bit tests for the loading of the TMR.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The correct way to ensure all conditions are met is to use something similar to the code below.
This works correctly permitting the IRS to handle the uses cases:
Init value of BAM_CylonMask = 128 with Left or Right direction selected
Init value of BAM_CylonMask = 1 with Left or Right direction selected
Init value of BAM_CylonMask = 2,4,8,16,32,64 with Left or Right direction selected
The later part of the ISR would now handle BAM_CylonMask.7 ( BIT 7) and there is no repeat of the BAM_CylonMask.0 (BIT 0) when the direction changes.
This major difference is the BAM_IninitalPass check which enables the initial value to be handle correctly, and, the other of things.
The demo program is not operating the same... so, I know I have not done something correct. I wish there was more documentation explaining the 'concept of operation' as this would help. I will keep trying to resolve.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello,
I am looking for some guidance in implementing Mirror Image Bit Angle Modulation (MIBAM) in Great Cow Basic.
MIBAM was created by Darrel Taylor using PICBASIC in 2009. I have included a link to his work here:
http://www.picbasic.co.uk/forum/showthread.php?t=7393
MIBAM is a replacement for Pulse Width Modulation to allow for driving many more LEDs Using TIMER Interrupts. The heart of the feature is an Interrupt Routine that is compiled using MPASM.
I have all the original sample source (attached) and I am trying to implement MIBAM using GCB but I am having issues with getting the interrupt routine to work. Is there any examples or tutorials about using Assembly code with GCB? I have looked at the information about interrupts but I can always use more knowledge as I find interrupt handling confusing.
Since I am a bit weak in the area of interrupt handling and also new to GCB it is possible I am going at this all wrong and maybe should just code this all in GCB and let the GCB Compiler do all the heavy lifting.
I am more than willing to do all the work figuring this out but would like some feedback from those that are more knowledgeable with GCB as to how best to get this working.
Thank you very much for you time
David
Many, many questions.
Why do this at all? There are PICs that support many more PWMs than PICs did in 2009.
How many PWMs are required?
The port. This port is relatively simple. Do not use ASM.
GCBASIC will create optimised ASM for you and it will be portable across the different chip architectures.
I have reviewed the PHP and it the ISR is essentially a CASE-SELECT supporting the 8 PWM channels. There is code that will not port as it specific to specific chips but GCBASIC will handle all the context stuff anyway.
How far have you got in GCBASIC?
We can help!
I got your ' PCA9685 routines for the GCBASIC compiler
' Copyright (C) 2018 Evan R. Venn
16 channel but i2c but today and think I used it for 2 stepper motor drives
Good point Stan. PCA9685 could be a solution.
@David
Looking at the code more.
There is an assumption of 8 LEDs/ports with no checking that the eight are defined in the user program. Which means the interrupt handles 8 even if they are not defined.
The calcs for the Interrupt latency are hard coded. This will have to made a real calculation for the chip.
The code has limited documentation. I think I know what the ISR is doing.
The user program is relatively simple. This is a 15 minote port. I can post that... but, the library will be based on what you have.
Evan
@David.
variable BuffAddr#v(FDutyVar) = _BAM_Buffers + BAMpinCount
Another one that I need explaining,
andwf BAM_Buffers#v(FDutyVar), W
- the use of BAM_Buffers#v(FDutyVar).My analysis. CylonMask AND BAM_Buffers(BuffPointer) Then so something
// movf _CylonMask, W
// andwf BAM_Buffers#v(FDutyVar), W
// btfss STATUS,Z ; copy Inverted Z to the Pin
// bsf LATport,Pin
// btfsc STATUS,Z
// bcf LATport,Pin
New code coulde be ...
if ( CylonMask AND BAM_Buffers( BuffPointer) ) =1 then
Port_Pin = 1
else
Port_Pin = 0
end if
MOVE?BB FDutyVar, BAM_Buffers#v(FDutyVar)
What is this
MOVE?BB
. Same addressing code but as this will be explain above this question is in relation to toMOVE?BB
The interrupt is easy. It is the rest of the code... :-)
MOVE?BB is an asm macro to do a byte-to-byte move,, ie MOVFF if the byte locations require it..
Thanks Jerry,
So
MOVE?BB FDutyVar, BuffAddr#v(FDutyVar)
means assign the value ofFDutyVar
toBuffAddr#v(FDutyVar)
. I just need to know whatBuffAddr#v()
means.The interrupt handler
This is optimised by the compiler and generates the same ASM.
However, this is meaningless in the context that the rest of the library does not work. :-(
I am certain the values of BAM_PeriodX are totally incorect.
Note: There is no need for ISR context management as this is managed by GCBASIC. Lots of other code in the original ISR address issues in the orginal compiler and again these are not needed.
;----[Interrupt handler for BAM-BAM]----------------------------------------
Generates
Last edit: Anobium 2023-07-09
I found the explanation!!
It is MPASM macro expansion. Hence, this code would have only compiled using MPASM.
#v(expr)
Returns the integer value of expr. Typically, used to create unique variable names with common prefixes or suffixes.
It is some smart way of doing something.
Thank you for all your comments and especially @evanvennn. I fully understand this was written at a time when PICs had a lot fewer PWM modules available but I have a lot of those older PICs in my stockpile that I would like to use. I like using GCBasic and lot better than anything else so I have been slowing moving all my project over to GCBasic and this particular module was one I just could not seem to work out. However you have really answered my basic question as it looks like I should not port this over but just recreate this in GCBasic as the compiler will do what the MPASM compiler did for the original code and that is create an optimized ISR.
Thank you all again for your very helpful feedback.
David
I get the rational now. Thanks for the explanation.
The ISR is replica of the original and it is just wrong. The ISR prevents the 7th bit from being set. So, this means the resolution is 7-bit not 8-bit.
I am working through the ISR at the moment changing it to 8-bit. Then, the rest should work.
The huge advantage we have with GCBASIC is we can easily add serial debug that 'back in the day ' adding debug was a major task. The demo code has a scope for debug. I added serial debug to the ISR to check the bit rotation and the errors at both ends of the direction change is very obvious.
I will post an update soon.
I haven't really looked at the code, but MIBAM is different than normal PWM code would be... it generates a different waveform..
@Jerry
Yes. I can see the signals. The issue is that no 7th bit pulse, and, bit 0 is pused twice when rotation is left and once when rotation is right. That cannot be correct .
I'm probably missing something... I don't see where that happens. What 7th bit do you mean?
As I see it, the actual output is done by PinList (which resolves to the BAM_LIST macro), and that has all eight bits of PORTD defined
CylonMask gets bit-shifted 7->0->7->0..., and there are eight bit tests for the loading of the TMR.
Bits get shifted. agree.
Size the .7 bit does not get handled by the remainder of the ISR. .7=1, shift to .6=1 therefore .7 is not handled.
And, bit .1 is processed three times.
It may work but it does not seem right to me.
The correct way to ensure all conditions are met is to use something similar to the code below.
This works correctly permitting the IRS to handle the uses cases:
Init value of BAM_CylonMask = 128 with Left or Right direction selected
Init value of BAM_CylonMask = 1 with Left or Right direction selected
Init value of BAM_CylonMask = 2,4,8,16,32,64 with Left or Right direction selected
The later part of the ISR would now handle BAM_CylonMask.7 ( BIT 7) and there is no repeat of the BAM_CylonMask.0 (BIT 0) when the direction changes.
This major difference is the BAM_IninitalPass check which enables the initial value to be handle correctly, and, the other of things.
I have completed a 'port' of MIBAM.
The demo program is not operating the same... so, I know I have not done something correct. I wish there was more documentation explaining the 'concept of operation' as this would help. I will keep trying to resolve.
There is a good explanation of BAM here....
https://christian-marty.ch/ElectricThings/BitAngleModulation.html