I have an interrupt routine playing back audio from memory to DAC. 18F27Q84.
I simultaneously need to sample an analog input with the ADC. I could start it off, do the DAC-stuff and there would be enough delay for the ADC to complete its work without the need for a stand still with AD_Delay.
The question is can I do something like this in GCbasic:
StartADC - do some other stuff - GetADC
or to do this I will have to fiddle with chip registers manually?
Not that I absolutely need it now, but it would be elegant and effective maybe opening future possibilities.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
All possible. I would rationalise the ADC read ( using the existing sub routine ) but put the code inline to do what you want. Fiddling with registers ( lol ) is what the existing sub does anyway. You are moving from sequencial to inline.
All doable.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Yes, I understand that the existing sub is poking around with the registers. My question should have been: can I do it using GCbasic commands? (set it off, leave the chip to do its A/D magic and get the output later).
Looking at a-d.h I figured it would be too hard for me to distill what I need. My guess is that it would be easier to try to figure out what register settings are needed, throw them in (I guess that is what you call inline code) and see if I can get it to show any sign of life.
I will have at a-d.h again and see if I can copy it, maybe just stop it at the right moment, before it interrupts the convertion in order to read the value. But. There is a lot of code ot grasp. If I settle on just one chip maybe it is easier to set the registers manually (playing them until it responds back).
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The configuration ( not poking about! ) in shown in your ASM. This is the best place to look. This is configured for your chip and therefore works. It is not a case of copying the a-d.h , this is a case of use the ASM produced and copying the required GCBASIC instructions to your program. There will only be a few GCBASIC instructions required.
This approach can be repeated across all 1500 microcontrollers. So, look in the ASM at the GCBASIC source added as part of the compilation for a specific microcontroller.
👍
1
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I examined the asm for a long time, but I could not make out what to extract, so I took a look in the 18FxxQ84 manual to see if it would help. There was an ADC example which I managed to adopt and succeeded in getting working. So after seemingly wasting a lot of valuable time fiddling around, it turned out it was not wasted after all!
I now have a AD-conversion routine that can be started off to do its thing while my code is running.
Happy day! :)
#CHIP18F27Q84,64#OPTIONExplicitDIRPORTA.1OUTDIRPORTA.3INDimADCresultasByte//ANALOG TO DIGITAL CONVERSION on 18FxxQ84//Instead of waiting or pausing for polling, code can be running while conversion gets finished.//Extracted from the 18FxxQ84 manual (example page 916)ADCON1=0;ADCON2=0;Legacymode,nofiltering,ADRES->ADPREVADCON3=0;nomathfunctionsADREF=0;Vref=Vdd&VssADPCH=3;selectRA3/AN3ADACQ=0;softwarecontrolledacquisitiontimeADCAP=0;defaultS&HcapacitanceADRPT=0;norepeatmeasurementsADACT=0;auto-conversiondisabledADCON0=B'10010000'//bit 2 high for 12bit (right justified), low = read 8-bit from ADRESH (left justified, zero-filled)//TRISA3 = 1 //PortA.3 = input (Tri-state control register)//ANSELA3=1 //PortA.3 analog inputDoADCON0.0=1//--START-- conversion by setting flag. -Ready when this flag goes low (page 936)wait20us//--WAIT-- can be REPLACED BY CODE or looking for ADCON0.0 flag going lowADCresult=ADRESH//--READ-- 8bit through ADRESH, for 12bit (ADCON0.2=1) result at: ADRESL, ADRESHIfADCresult>128thenPORTA.1=1elsePORTA.1=0//-OUTPUT (changes state at 1/2 VCC on PORTA.3)Loop
👍
1
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
With Bit 4=1 of ADCON0 as in the above example the built-in Analog-to-Digital Converter RC Oscillator (ADCRC) is used, giving a tad of 1-2us and total conversion time 10-20us for 8-bit.
Using FOSC as source instead (+ prescaler /22) conversion is faster and is as fast as possible without violating the specification limits. Code change:
ADCON0=B'10000000' // Bit 4=0 FOSC. Needs prescaler.
ADCLK = 0x15 //= prescaler /22, = tad 0.67us and measuring about 7us (8-bit) and 9us (12bit)
For 8-bit a wait of 10us (instead of 20us with ADCRC) now seems safe. One probably should check the ADCON0.0 flag going low to be perfectly safe, but I found it working without.
While it is working it seems that I should have added some value to ADACQ (ADC Acquisition Time Control Register. ADACQL) = 3 (minium 3-10 is recommended, FOSC cycles). Higher ADACQ value = not as demanding on source being low impedance. With a value of 3 it still should be within 10us total, with a value of 10 the total time should be within 15us(?). The reason for this seemingly working with ADACQ=0 is likely due to only using a single channel/input.
Last edit: Roger Jönsson 2 hours ago
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Looking at the asm doing: - MYresult = ReadAD(AN3). -When starting the AD converter conversation it says:
;SET ADON ON
bsf ADCON0,ADON,BANKED
I guess what it does is setting the conversion flag: ADCON0.0=1 (ADCON0.0 being called "GO" in the manual).
Reading the asm, how would I know what bit ADON is?
Just to help me understand how the asm is working. I searched for ADON in the asm file but did not find an explainiation.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I think I misunderstood how GCbasic ReadAD works.
AD_Delay controls is the acquisition delay (during this time the value is sampled, a capacitor is charged up)?
After that the voltage sampled gets measured internally, while ReadAD waits for the flag to signal ready before moving along? So the total time consumed is AD_Delay + for the logic to find the value and clear the flag.
asm snippet:
;Enable AD Operations
;SET ADON ON
bsf ADCON0,ADON,BANKED
;Acquisition Delay
;Wait AD_Delay //<- sampling starts and continues for 10us?
movlw 2
movwf SysWaitTemp10US,ACCESS
banksel 0
rcall Delay_10US
;Read A/D @1
;SET GO_NOT_DONE ON
banksel ADCON0
bsf ADCON0,GO_NOT_DONE,BANKED //<- flag is set, measuring of what is sampled starts?
;nop
nop
;Wait While GO_NOT_DONE ON //wait until flag signals done?
SysWaitLoop1
btfsc ADCON0,GO_NOT_DONE,BANKED
bra SysWaitLoop1
;Switch off A/D
;SET ADCON0.ADON OFF
bcf ADCON0,ADON,BANKED
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have an interrupt routine playing back audio from memory to DAC. 18F27Q84.
I simultaneously need to sample an analog input with the ADC. I could start it off, do the DAC-stuff and there would be enough delay for the ADC to complete its work without the need for a stand still with AD_Delay.
The question is can I do something like this in GCbasic:
StartADC - do some other stuff - GetADC
or to do this I will have to fiddle with chip registers manually?
Not that I absolutely need it now, but it would be elegant and effective maybe opening future possibilities.
All possible. I would rationalise the ADC read ( using the existing sub routine ) but put the code inline to do what you want. Fiddling with registers ( lol ) is what the existing sub does anyway. You are moving from sequencial to inline.
All doable.
Yes, I understand that the existing sub is poking around with the registers. My question should have been: can I do it using GCbasic commands? (set it off, leave the chip to do its A/D magic and get the output later).
Looking at a-d.h I figured it would be too hard for me to distill what I need. My guess is that it would be easier to try to figure out what register settings are needed, throw them in (I guess that is what you call inline code) and see if I can get it to show any sign of life.
I will have at a-d.h again and see if I can copy it, maybe just stop it at the right moment, before it interrupts the convertion in order to read the value. But. There is a lot of code ot grasp. If I settle on just one chip maybe it is easier to set the registers manually (playing them until it responds back).
The configuration ( not poking about! ) in shown in your ASM. This is the best place to look. This is configured for your chip and therefore works. It is not a case of copying the a-d.h , this is a case of use the ASM produced and copying the required GCBASIC instructions to your program. There will only be a few GCBASIC instructions required.
This approach can be repeated across all 1500 microcontrollers. So, look in the ASM at the GCBASIC source added as part of the compilation for a specific microcontroller.
I examined the asm for a long time, but I could not make out what to extract, so I took a look in the 18FxxQ84 manual to see if it would help. There was an ADC example which I managed to adopt and succeeded in getting working. So after seemingly wasting a lot of valuable time fiddling around, it turned out it was not wasted after all!
I now have a AD-conversion routine that can be started off to do its thing while my code is running.
Happy day! :)
With Bit 4=1 of ADCON0 as in the above example the built-in Analog-to-Digital Converter RC Oscillator (ADCRC) is used, giving a tad of 1-2us and total conversion time 10-20us for 8-bit.
Using FOSC as source instead (+ prescaler /22) conversion is faster and is as fast as possible without violating the specification limits. Code change:
For 8-bit a wait of 10us (instead of 20us with ADCRC) now seems safe. One probably should check the ADCON0.0 flag going low to be perfectly safe, but I found it working without.
While it is working it seems that I should have added some value to ADACQ (ADC Acquisition Time Control Register. ADACQL) = 3 (minium 3-10 is recommended, FOSC cycles). Higher ADACQ value = not as demanding on source being low impedance. With a value of 3 it still should be within 10us total, with a value of 10 the total time should be within 15us(?). The reason for this seemingly working with ADACQ=0 is likely due to only using a single channel/input.
Last edit: Roger Jönsson 2 hours ago
Looking at the asm doing: - MYresult = ReadAD(AN3). -When starting the AD converter conversation it says:
I guess what it does is setting the conversion flag: ADCON0.0=1 (ADCON0.0 being called "GO" in the manual).
Reading the asm, how would I know what bit ADON is?
Just to help me understand how the asm is working. I searched for ADON in the asm file but did not find an explainiation.
The bit mappings are in PICINFO.
I think I misunderstood how GCbasic ReadAD works.
AD_Delay controls is the acquisition delay (during this time the value is sampled, a capacitor is charged up)?
After that the voltage sampled gets measured internally, while ReadAD waits for the flag to signal ready before moving along?
So the total time consumed is AD_Delay + for the logic to find the value and clear the flag.
asm snippet:
;Enable AD Operations
;SET ADON ON
bsf ADCON0,ADON,BANKED
;Acquisition Delay
;Wait AD_Delay //<- sampling starts and continues for 10us?
movlw 2
movwf SysWaitTemp10US,ACCESS
banksel 0
rcall Delay_10US
;Read A/D @1
;SET GO_NOT_DONE ON
banksel ADCON0
bsf ADCON0,GO_NOT_DONE,BANKED //<- flag is set, measuring of what is sampled starts?
;nop
nop
;Wait While GO_NOT_DONE ON //wait until flag signals done?
SysWaitLoop1
btfsc ADCON0,GO_NOT_DONE,BANKED
bra SysWaitLoop1
;Switch off A/D
;SET ADCON0.ADON OFF
bcf ADCON0,ADON,BANKED
There is a minimum sample time ( the wait ) then internal processing ( which is the register.bit check).