Page 1 of 1

error in ADC.bas

Posted: Wed Jan 12, 2022 9:14 pm
by Jerry Messina
I don't know when/how this happened, but there's a missing comma in the file ADC.bas.
A comma needs to be added to the end of the line 'AN11 = $0B' as shown below:

Code: Select all

// channel select constants...
public const
   AN0 = $00,
   AN1 = $01,
   AN2 = $02,
   AN3 = $03,
   AN4 = $04,
   AN5 = $05,
   AN6 = $06,
   AN7 = $07
#if (_adc > 8)
public const
   AN8  = $08,
   AN9  = $09,
   AN10 = $0A,
   AN11 = $0B,
   AN12 = $0C,
   AN13 = $0D,
   AN14 = $0E,
   AN15 = $0F
#endif   
edit: I went back and checked... seems this error was introduced in V2.2.3.2 (Apr 2020)

Re: error in ADC.bas

Posted: Sun Feb 12, 2023 9:52 pm
by garryp4
Jerry:

I just updated my copy of Swordfish and get errors in the ADC.BAS file. I can't copy/paste the errors and a screen shot is too large to attach. I changed line 91 and 204 from "> 8" to "> 16". That cleared up the errors. Is this correct?

Re: error in ADC.bas

Posted: Sun Feb 12, 2023 11:24 pm
by Jerry Messina
The error I mentioned was a missing comma in line 41, where it was 'AN11 = $0B' instead of 'AN11 = $0B,'

Here's an updated copy to fix that. This is latest version, from SF v2.2.3.8
ADC.bas v1.2

Code: Select all

{
*****************************************************************************
*  Name    : ADC.bas                                                        *
*  Author  : David John Barker                                              *
*  Notice  : Copyright (c) 2007 Mecanique                                   *
*          : All Rights Reserved                                            *
*  Date    : 12/01/2007                                                     *
*  Version : 1.0                                                            * 
*          : 1.1 Corrected bitnames for 18F1220, 18F1320 devices            *
*          : 1.2 minor edits, adc consts, fix missing comma AN11            *
*  Notes   :                                                                *
*****************************************************************************
}
module ADC
  
// conversion time constants...
public const
   FOSC_2  = %000,
   FOSC_4  = %100,
   FOSC_8  = %001,
   FOSC_16 = %101,
   FOSC_32 = %010,
   FOSC_64 = %110,
   FRC     = %011

// channel select constants...
public const
   AN0 = $00,
   AN1 = $01,
   AN2 = $02,
   AN3 = $03,
   AN4 = $04,
   AN5 = $05,
   AN6 = $06,
   AN7 = $07
#if (_adc > 8)
public const
   AN8  = $08,
   AN9  = $09,
   AN10 = $0A,
   AN11 = $0B,
   AN12 = $0C,
   AN13 = $0D,
   AN14 = $0E,
   AN15 = $0F
#endif   
#if (_adc > 16)
public const
   AN16 = $10,
   AN17 = $11,
   AN18 = $12,
   AN19 = $13,
   AN20 = $14,
   AN21 = $15,
   AN22 = $16,
   AN23 = $17
#endif   
            
public dim
#if _device in (18F1220, 18F1320)
   // ADCON0...
   VCFG1   as ADCON0.6,
   VCFG0   as ADCON0.5,
   CHS2    as ADCON0.4,
   CHS1    as ADCON0.3,
   CHS0    as ADCON0.2,
   GO_DONE as ADCON0.1,
   ADON    as ADCON0.0,

   // ADCON1...
   PCFG6 as ADCON1.6,
   PCFG5 as ADCON1.5,
   PCFG4 as ADCON1.4,
   PCFG3 as ADCON1.3,
   PCFG2 as ADCON1.2,
   PCFG1 as ADCON1.1,
   PCFG0 as ADCON1.0,  
   
   // ADCON2...
   ADFM as ADCON2.7,
   AQT2 as ADCON2.5,
   AQT1 as ADCON2.4,   
   AQT0 as ADCON2.3,
   ADCS2 as ADCON2.2,
   ADCS1 as ADCON2.1,
   ADCS0 as ADCON2.0, 

   // extended alias...
   Convert as ADCON0.Booleans(1),       // GO_DONE, POR = 0
   RightJustify as ADCON2.Booleans(7)   // ADFM, POR = false
#elseif (_adc > 8)
   // ADCON0...
   CHS3    as ADCON0.5,
   CHS2    as ADCON0.4,
   CHS1    as ADCON0.3,
   CHS0    as ADCON0.2,
   GO_DONE as ADCON0.1,
   ADON    as ADCON0.0,

   // ADCON1...
   VCFG1 as ADCON1.5,
   VCFG0 as ADCON1.4,
   PCFG3 as ADCON1.3,
   PCFG2 as ADCON1.2,
   PCFG1 as ADCON1.1,
   PCFG0 as ADCON1.0,  
   
   // ADCON2...
   ADFM as ADCON2.7,
   ADCS2 as ADCON2.2,
   ADCS1 as ADCON2.1,
   ADCS0 as ADCON2.0, 

   // extended alias...
   Convert as ADCON0.Booleans(1),       // GO_DONE, POR = 0
   RightJustify as ADCON2.Booleans(7)   // ADFM, POR = false
#else
   // ADCON0...
   ADCS1   as ADCON0.7,
   ADCS0   as ADCON0.6,
   CHS2    as ADCON0.5,
   CHS1    as ADCON0.4,
   CHS0    as ADCON0.3,
   GO_DONE as ADCON0.2,
   ADON    as ADCON0.0,

   // ADCON1...
   ADFM  as ADCON1.7,
   ADCS2 as ADCON1.6,
   PCFG3 as ADCON1.3,
   PCFG2 as ADCON1.2,
   PCFG1 as ADCON1.1,
   PCFG0 as ADCON1.0,

   // extended alias...
   Convert as ADCON0.Booleans(2),       // GO_DONE, POR = 0
   RightJustify as ADCON1.Booleans(7)   // ADFM, POR = false
#endif

// ADCON(x) extended alias...   
public dim
   Enabled as ADCON0.Booleans(0),       // ADON, POR = 0 
   ADResult as ADRESL.AsWord            // 16 bit ADC result

// local helper variables...
dim 
   FAcquisitionTime as byte            
{
****************************************************************************
* Name    : SetConvTime                                                    *
* Purpose : Set the conversion time. Valid parameters include FOSC_2,      *
*         : FOSC_4, FOSC_8, FOSC_16, FOSC_32, FOSC_64 and FRC              *
****************************************************************************
}
public sub SetConvTime(pValue as byte)
   ADCS2 = pValue.2
   ADCS1 = pValue.1
   ADCS0 = pValue.0
end sub 
{
****************************************************************************
* Name    : SetAcqTime                                                     *
* Purpose : Sets the ADC acquisition time, in microseconds (us)            *
****************************************************************************
}
public sub SetAcqTime(pATime as byte)
   FAcquisitionTime = pATime
end sub
{
****************************************************************************
* Name    : SetConfig                                                      *
* Purpose : Set configuration control bits                                 *
****************************************************************************
}
public sub SetConfig(pConfig as byte) 
  #if (_adc > 8) or _device in (18F1220, 18F1320)
   ADCON1 = pConfig and $3F
  #else
   ADCON1 = ADCON1 and $F0
   pConfig = pConfig and $0F
   ADCON1 = ADCON1 or pConfig 
  #endif
end sub  
{
****************************************************************************
* Name    : Read                                                           *
* Purpose : Read currently uses delayus for the acquistion time, which has *
*         : the following minimum overheads                                *
*         : 4Mhz - 24us                                                    *
*         : 8Mhz - 12us                                                    *
*         : 10Mhz - 8us                                                    *
*         : 16Mhz - 5us                                                    *
*         : 20Mhz plus - 2us                                               * 
*         : If your acquistion time requirements fall below the above,     *
*         : just create a copy of this function in your main program (or   *
*         : another module) and replace delayms(ATime) with a constant     *
****************************************************************************
}
public function Read(pChannel as byte) as word
   // set channel...
   CHS0 = pChannel.0
   CHS1 = pChannel.1
   CHS2 = pChannel.2
  #if (_adc > 8)
   CHS3 = pChannel.3
  #endif
   
   // read ADC...
   if FAcquisitionTime = 0 then
      Enabled = true  
      Convert = true
   else   
      Enabled = true  
      delayus(FAcquisitionTime)
      Convert = true  
   endif  
   
   // wait for completion, then disable ADC...
   while Convert      
   wend           
   Enabled = false   
   Result = ADResult
end function
{
****************************************************************************
* Name    : ShellSort (PRIVATE)                                            *
* Purpose : Shell-Metzner sorting algorithm                                *
****************************************************************************
}
sub ShellSort(byref pArray() as word)
   dim Finished as boolean
   dim Jump, Index, LoopIndex as word
   dim SwapTemp as word
   Jump = bound(pArray)
   while Jump > 1
      Jump = Jump / 2
      repeat
         Finished = true
         for LoopIndex = 0 to bound(pArray) - Jump
            Index = LoopIndex + Jump
            if pArray(LoopIndex) > pArray(Index) then
               SwapTemp = pArray(LoopIndex)
               pArray(LoopIndex) = pArray(Index)
               pArray(Index) = SwapTemp
                Finished = false
            endif
         next
     until Finished
   wend
end sub   
{
****************************************************************************
* Name    : GetMedian (PRIVATE)                                            *
* Purpose : Returns the median of a sample data set                        *
****************************************************************************
}
function GetMedian(byref pSamples() as word) as word
   ShellSort(pSamples)
   result = pSamples((bound(pSamples) + 1) / 2)
end function  
{
****************************************************************************
* Name    : ReadMedian                                                     *
* Purpose : Takes 64 ADC samples and returns the median average. Although  *
*         : computationally expensive, this routine is quite useful as the *
*         : result is not influenced by extreme high and low sample values *
****************************************************************************
}
public function ReadMedian(pChannel as byte) as word
   dim Index as byte
   dim Sum(64) as word 
   for index = 0 to bound(Sum)
      Sum(Index) = Read(pChannel)
      delayus(20)
   next
   Result = GetMedian(Sum) 
end function
{
****************************************************************************
* Name    : ReadMean                                                       *
* Purpose : Takes pRange ADC samples and returns the mean average. Much    *
*         : quicker than median average, but can be influenced by extreme  *
*         : high and low sample values                                     *
****************************************************************************
}
public function ReadMean(pChannel as byte, pRange as byte = 64) as word
   dim Index as byte
   dim Sum as longword
   if pRange = 0 then
      Result = 0
   else   
      Sum = 0
      for index = 0 to pRange - 1
         Sum = Sum + Read(pChannel)
         delayus(20)
      next
      Result = Sum / pRange
   endif   
end function

// defaults
RightJustify = true
FAcquisitionTime = 20

end module
The ADC.bas module hasn't been updated in quite a while, so it may not work with many newer devices since there are a number of different ADC hardware peripherals. If you've just updated to SF v2.2.3.8, it already includes the above file.

If you're getting errors, let me know which device you're using and I'll see if I can get it working...

Re: error in ADC.bas

Posted: Mon Feb 13, 2023 1:38 pm
by Jerry Messina
One thing to note is that most recent devices (including the K40, K42, K83, and entire Q family) have a different ADC peripheral that is not supported by the ADC.bas module.

Here's an updated ADC.bas module (v1.3) that will detect this and issue an appropriate error message.
ADC.bas V1.3

Code: Select all

{
*****************************************************************************
*  Name    : ADC.bas                                                        *
*  Author  : David John Barker                                              *
*  Notice  : Copyright (c) 2007 Mecanique                                   *
*          : All Rights Reserved                                            *
*  Date    : 13 FEB 2023                                                    *
*  Version : 1.3  13 FEB 2023                                               * 
*          :   - add 'unsupported' error if '#define _adc2' detected        *
*          : 1.2  4 MAY 2022                                                *
*          :   - minor edits, adc consts, fix missing comma AN11            *
*          : 1.1  2009                                                      *
*          :   - Corrected bitnames for 18F1220, 18F1320 devices            *
*          : 1.0  2007                                                      *
*          :   - initial release                                            *
*  Notes   : This module does not support devices with ADCC/ADC2 peripheral *
*****************************************************************************
}
module ADC

// check for _adc2 peripheral and flag as unsupported
#if defined(_adc2) and (_adc2 > 0)
  #error "ADC.bas does not support the ADCC/ADC2 peripheral"
#endif
// check if device file has defined the number of adc channels
#if (_adc = 0)
  #error "device file '_adc' is 0... no adc channels defined"
#endif

// conversion time constants...
public const
   FOSC_2  = %000,
   FOSC_4  = %100,
   FOSC_8  = %001,
   FOSC_16 = %101,
   FOSC_32 = %010,
   FOSC_64 = %110,
   FRC     = %011

// channel select constants...
public const
   AN0 = $00,
   AN1 = $01,
   AN2 = $02,
   AN3 = $03,
   AN4 = $04,
   AN5 = $05,
   AN6 = $06,
   AN7 = $07
#if (_adc > 8)
public const
   AN8  = $08,
   AN9  = $09,
   AN10 = $0A,
   AN11 = $0B,
   AN12 = $0C,
   AN13 = $0D,
   AN14 = $0E,
   AN15 = $0F
#endif   
#if (_adc > 16)
public const
   AN16 = $10,
   AN17 = $11,
   AN18 = $12,
   AN19 = $13,
   AN20 = $14,
   AN21 = $15,
   AN22 = $16,
   AN23 = $17
#endif   
            
public dim
#if _device in (18F1220, 18F1320)
   // ADCON0...
   VCFG1   as ADCON0.6,
   VCFG0   as ADCON0.5,
   CHS2    as ADCON0.4,
   CHS1    as ADCON0.3,
   CHS0    as ADCON0.2,
   GO_DONE as ADCON0.1,
   ADON    as ADCON0.0,

   // ADCON1...
   PCFG6 as ADCON1.6,
   PCFG5 as ADCON1.5,
   PCFG4 as ADCON1.4,
   PCFG3 as ADCON1.3,
   PCFG2 as ADCON1.2,
   PCFG1 as ADCON1.1,
   PCFG0 as ADCON1.0,  
   
   // ADCON2...
   ADFM as ADCON2.7,
   AQT2 as ADCON2.5,
   AQT1 as ADCON2.4,   
   AQT0 as ADCON2.3,
   ADCS2 as ADCON2.2,
   ADCS1 as ADCON2.1,
   ADCS0 as ADCON2.0, 

   // extended alias...
   Convert as ADCON0.Booleans(1),       // GO_DONE, POR = 0
   RightJustify as ADCON2.Booleans(7)   // ADFM, POR = false
#elseif (_adc > 8)
   // ADCON0...
   CHS3    as ADCON0.5,
   CHS2    as ADCON0.4,
   CHS1    as ADCON0.3,
   CHS0    as ADCON0.2,
   GO_DONE as ADCON0.1,
   ADON    as ADCON0.0,

   // ADCON1...
   VCFG1 as ADCON1.5,
   VCFG0 as ADCON1.4,
   PCFG3 as ADCON1.3,
   PCFG2 as ADCON1.2,
   PCFG1 as ADCON1.1,
   PCFG0 as ADCON1.0,  
   
   // ADCON2...
   ADFM as ADCON2.7,
   ADCS2 as ADCON2.2,
   ADCS1 as ADCON2.1,
   ADCS0 as ADCON2.0, 

   // extended alias...
   Convert as ADCON0.Booleans(1),       // GO_DONE, POR = 0
   RightJustify as ADCON2.Booleans(7)   // ADFM, POR = false
#else
   // ADCON0...
   ADCS1   as ADCON0.7,
   ADCS0   as ADCON0.6,
   CHS2    as ADCON0.5,
   CHS1    as ADCON0.4,
   CHS0    as ADCON0.3,
   GO_DONE as ADCON0.2,
   ADON    as ADCON0.0,

   // ADCON1...
   ADFM  as ADCON1.7,
   ADCS2 as ADCON1.6,
   PCFG3 as ADCON1.3,
   PCFG2 as ADCON1.2,
   PCFG1 as ADCON1.1,
   PCFG0 as ADCON1.0,

   // extended alias...
   Convert as ADCON0.Booleans(2),       // GO_DONE, POR = 0
   RightJustify as ADCON1.Booleans(7)   // ADFM, POR = false
#endif

// ADCON(x) extended alias...   
public dim
   Enabled as ADCON0.Booleans(0),       // ADON, POR = 0 
   ADResult as ADRESL.AsWord            // 16 bit ADC result

// local helper variables...
dim 
   FAcquisitionTime as byte            
{
****************************************************************************
* Name    : SetConvTime                                                    *
* Purpose : Set the conversion time. Valid parameters include FOSC_2,      *
*         : FOSC_4, FOSC_8, FOSC_16, FOSC_32, FOSC_64 and FRC              *
****************************************************************************
}
public sub SetConvTime(pValue as byte)
   ADCS2 = pValue.2
   ADCS1 = pValue.1
   ADCS0 = pValue.0
end sub 
{
****************************************************************************
* Name    : SetAcqTime                                                     *
* Purpose : Sets the ADC acquisition time, in microseconds (us)            *
****************************************************************************
}
public sub SetAcqTime(pATime as byte)
   FAcquisitionTime = pATime
end sub
{
****************************************************************************
* Name    : SetConfig                                                      *
* Purpose : Set configuration control bits                                 *
****************************************************************************
}
public sub SetConfig(pConfig as byte) 
  #if (_adc > 8) or _device in (18F1220, 18F1320)
   ADCON1 = pConfig and $3F
  #else
   ADCON1 = ADCON1 and $F0
   pConfig = pConfig and $0F
   ADCON1 = ADCON1 or pConfig 
  #endif
end sub  
{
****************************************************************************
* Name    : Read                                                           *
* Purpose : Read currently uses delayus for the acquistion time, which has *
*         : the following minimum overheads                                *
*         : 4Mhz - 24us                                                    *
*         : 8Mhz - 12us                                                    *
*         : 10Mhz - 8us                                                    *
*         : 16Mhz - 5us                                                    *
*         : 20Mhz plus - 2us                                               * 
*         : If your acquistion time requirements fall below the above,     *
*         : just create a copy of this function in your main program (or   *
*         : another module) and replace delayms(ATime) with a constant     *
****************************************************************************
}
public function Read(pChannel as byte) as word
   // set channel...
   CHS0 = pChannel.0
   CHS1 = pChannel.1
   CHS2 = pChannel.2
  #if (_adc > 8)
   CHS3 = pChannel.3
  #endif
   
   // read ADC...
   if FAcquisitionTime = 0 then
      Enabled = true  
      Convert = true
   else   
      Enabled = true  
      delayus(FAcquisitionTime)
      Convert = true  
   endif  
   
   // wait for completion, then disable ADC...
   while Convert      
   wend           
   Enabled = false   
   Result = ADResult
end function
{
****************************************************************************
* Name    : ShellSort (PRIVATE)                                            *
* Purpose : Shell-Metzner sorting algorithm                                *
****************************************************************************
}
sub ShellSort(byref pArray() as word)
   dim Finished as boolean
   dim Jump, Index, LoopIndex as word
   dim SwapTemp as word
   Jump = bound(pArray)
   while Jump > 1
      Jump = Jump / 2
      repeat
         Finished = true
         for LoopIndex = 0 to bound(pArray) - Jump
            Index = LoopIndex + Jump
            if pArray(LoopIndex) > pArray(Index) then
               SwapTemp = pArray(LoopIndex)
               pArray(LoopIndex) = pArray(Index)
               pArray(Index) = SwapTemp
                Finished = false
            endif
         next
     until Finished
   wend
end sub   
{
****************************************************************************
* Name    : GetMedian (PRIVATE)                                            *
* Purpose : Returns the median of a sample data set                        *
****************************************************************************
}
function GetMedian(byref pSamples() as word) as word
   ShellSort(pSamples)
   result = pSamples((bound(pSamples) + 1) / 2)
end function  
{
****************************************************************************
* Name    : ReadMedian                                                     *
* Purpose : Takes 64 ADC samples and returns the median average. Although  *
*         : computationally expensive, this routine is quite useful as the *
*         : result is not influenced by extreme high and low sample values *
****************************************************************************
}
public function ReadMedian(pChannel as byte) as word
   dim Index as byte
   dim Sum(64) as word 
   for index = 0 to bound(Sum)
      Sum(Index) = Read(pChannel)
      delayus(20)
   next
   Result = GetMedian(Sum) 
end function
{
****************************************************************************
* Name    : ReadMean                                                       *
* Purpose : Takes pRange ADC samples and returns the mean average. Much    *
*         : quicker than median average, but can be influenced by extreme  *
*         : high and low sample values                                     *
****************************************************************************
}
public function ReadMean(pChannel as byte, pRange as byte = 64) as word
   dim Index as byte
   dim Sum as longword
   if pRange = 0 then
      Result = 0
   else   
      Sum = 0
      for index = 0 to pRange - 1
         Sum = Sum + Read(pChannel)
         delayus(20)
      next
      Result = Sum / pRange
   endif   
end function

// defaults
RightJustify = true
FAcquisitionTime = 20

end module
When you compile, if you get errors it's usually best to scroll down, find the first one, and work backwards.
Since you can't copy the contents of the 'Results' window, you can get a list of all the errors by opening the project's .sfp file with a text editor and look for the [COMPILE_ERROR] section...

Code: Select all

[COMPILE_ERROR]
ITEM_0="E:\_sfmodules\adc\adc.bas","23","10","ADC.bas does not support the ADCC/ADC2 peripheral"