123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- /*********************************************************************
- *
- * Analog library for Fraise pic18f device
- *
- *
- *********************************************************************
- * Author Date Comment
- *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * Antoine Rousseau march 2013 Original.
- ********************************************************************/
- /*
- # This program is free software; you can redistribute it and/or
- # modify it under the terms of the GNU General Public License
- # as published by the Free Software Foundation; either version 2
- # of the License, or (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- # MA 02110-1301, USA.
- */
- #include "analog.h"
- #define CHANNELS_GROUPS ((ANALOG_MAX_CHANNELS+7)/8)
- static int Value[ANALOG_MAX_CHANNELS];
- static int oldValue[ANALOG_MAX_CHANNELS];
- static int inValue[ANALOG_MAX_CHANNELS]; // input values
- static int Max[ANALOG_MAX_CHANNELS];
- static int Min[ANALOG_MAX_CHANNELS];
- static int Dist[ANALOG_MAX_CHANNELS]; // distance of oldValue from inValue
- static unsigned char Scaling=0; // 1 when scaling
- static unsigned char Selected[CHANNELS_GROUPS];
- static unsigned char HWChan[ANALOG_MAX_CHANNELS];
- static unsigned char Pins[ANALOG_MAX_CHANNELS];
- static int Threshold=ANALOG_THRESHOLD;
- static char Mode = AMODE_NUM;
- #define MINMAX_MARGIN ANALOG_MINMAX_MARGIN
- /*#define bitset(var,bitno) ((var) |= (1 << (bitno)))
- #define bitclr(var,bitno) ((var) &= ~(1 << (bitno)))
- #define bittst(var,bitno) (var & (1 << (bitno)))*/
- #define isSelected(num) (bittst(Selected[num>>3],num&7))
- void analogInit()
- {
- unsigned char i;
-
- for(i=0;i<CHANNELS_GROUPS;i++) {
- Selected[i]=0;
- }
-
- for(i=0;i<ANALOG_MAX_CHANNELS;i++) {
- Value[i]=0;
- inValue[i]=0;
- oldValue[i]=0;
- Min[i]=0;
- Max[i]=0x7FFF;
- Pins[i]=255;
- }
-
- ADCON2=0b10101111; //right justified, 12 AD, RC
- ADCON1=0; //0->Vdd
- ADCON0=1; //on, channel 0
-
- ADCON0bits.GO=1; // go !
- }
- void analogInitTouch(){
- CTMUCONH = 0x00;
- CTMUCONL = 0x90;
- CTMUICON = 0x03; //55uA
- CTMUCONHbits.CTMUEN = 1; //Enable CTMU
- }
- void analogSelectAdc(unsigned char chan,unsigned char hwchan )
- {
- bitset(Selected[chan>>3],chan&7);
- HWChan[chan]=hwchan;
- Pins[chan]=255;
- }
- void analogSelectAdcTouch(unsigned char chan,unsigned char hwchan, unsigned char *port, unsigned char bit)
- {
- bitset(Selected[chan>>3],chan&7);
- HWChan[chan]=hwchan;
- Pins[chan]=(((unsigned int)(port-&PORTA)&7)<<4) + (bit&7);
- }
- void analogDeselect(unsigned char chan)
- {
- bitclr(Selected[chan>>3],chan&7);
- }
- unsigned char analogService(void)
- {
- static unsigned char chan=0, conv=0;
- int v;
- unsigned char pin;
-
- if(ADCON0bits.GO) return chan;
-
- if(conv) {
- v = Value[chan];
- // v = oldv-oldv/N+ADres = ((ADres*N)+oldv*(N-1))/N : v = N*lowpass[N](ADres) N=2^ANALOG_FILTER
- pin = Pins[chan];
- if(pin != 255) {
- bitclr(*(&TRISA+(pin>>4)),pin&7);
- bitclr(*(&LATA+(pin>>4)),pin&7);
- }
- Value[chan] = v - (v>>ANALOG_FILTER) + ADRESL+(ADRESH<<8);
- if(Scaling == 1) {
- v = Value[chan];
- if(v < (Min[chan]-MINMAX_MARGIN)) Min[chan] = v+MINMAX_MARGIN;
- if(v > (Max[chan]+MINMAX_MARGIN)) Max[chan] = v-MINMAX_MARGIN;
- }
- conv=0;
- }
-
- chan++;
- if(chan >= ANALOG_MAX_CHANNELS) chan = 0;
-
- if(isSelected(chan)) {
- ADCON0=(HWChan[chan] << 2) + 1;
- pin = Pins[chan];
- if(pin != 255) {
- bitset(*(&TRISA+(pin>>4)),pin&7);// set channel to digital input
- bitset(*(__data unsigned char*)((int)&ANSELA + (pin>>4)),pin&7);// set channel to analog input
- CTMUCONHbits.IDISSEN = 1; // Drain any charge on the A/D circuit
- Nop(); Nop();
- CTMUCONHbits.IDISSEN = 0; // Stop discharge of A/D circuit
- CTMUCONLbits.EDG2STAT = 0; // Make sure edge2 is 0
- __critical{
- CTMUCONLbits.EDG1STAT = 1; // Set edge1 - Start Charge
- Nop(); Nop(); Nop(); Nop();
- Nop(); Nop(); Nop(); Nop();
- Nop(); Nop(); Nop(); Nop();
- Nop(); Nop(); Nop(); Nop();
- Nop(); Nop(); Nop(); Nop();
- CTMUCONLbits.EDG1STAT = 0; //Clear edge1 - Stop Charge
- }
- }
- ADCON0bits.GO = 1;
- conv = 1;
- }
-
- return chan;
- }
- char analogSend()
- {
- static unsigned char chan = 0;
- unsigned char loop = 0, count = 0, len = 0;
- int v, d;
- static unsigned char buf[13] = { 'B' }; //'B' + 3x4 chars
-
- while((count < 4) && (loop++ < ANALOG_MAX_CHANNELS)){
- chan++;
- if(chan >= ANALOG_MAX_CHANNELS) {
- chan = 0;
- }
- if(! isSelected(chan)) continue;
- v = Value[chan];
- if(Mode & AMODE_SCALE) { // scale :
- if(v < Min[chan]) v = 0;
- else if(v > Max[chan]) v = ANALOG_SCALED_MAX;
- else v = (unsigned int)(
- ((ANALOG_SCALED_MAX+1UL) * (v - Min[chan])) /
- (Max[chan] - Min[chan]) );
- if(v <= Threshold ) v = 0;
- else if(v >= (ANALOG_SCALED_MAX - Threshold))
- v = ANALOG_SCALED_MAX;
- }
- d = v - oldValue[chan];
- if(d < 0) d = -d;
-
- count++;
-
- if(d <= Threshold) continue;
- oldValue[chan] = v;
-
- if(Mode & AMODE_CROSS) {
- if(Dist[chan] != 0) {
- d = v - inValue[chan];
- if((d != 0) && ((d > 0) == (Dist[chan] > 0))) {
- Dist[chan] = d;
- continue;
- }
- else Dist[chan] = 0;
- }
- }
-
- if(Mode & AMODE_NUM) {
- if( !len ) buf[len++] = 'B';
- buf[len++] = chan + 100;
- buf[len++] = v >> 8;
- buf[len++] = v & 255;
- }
- else printf("C A %d %d\n",chan,v);
- }
-
- if((len != 0) && (Mode & AMODE_NUM)) {
- buf[len++] = '\n';
- fraiseSend(buf,len);
- }
-
- return count;
- }
- void analogSetMode(unsigned char mode) // scale : bit0 = scale_on ; bit1 = num_on(=text_off) ; bit2 = cross_inval
- {
- Mode = mode;
- }
- void analogSet(unsigned char chan, int val)
- {
- int d;
-
- inValue[chan] = val;
- d = oldValue[chan] - val;
- Dist[chan] = d;
- if(d < 0) d = -d;
- if(d < 3) d = 0;
- if(d == 0) Dist[chan] = 0;
- }
- int analogGet(unsigned char chan)
- {
- return Value[chan];
- }
-
- int analogGetDistance(unsigned char chan)
- {
- return Dist[chan];
- }
- void analogScaling(unsigned char scaling) // when scaling, min and max are updated each sample
- {
- unsigned char i;
-
- if(scaling==1) {
- for(i=0;i<ANALOG_MAX_CHANNELS;i++) {
- Min[i]=0x7FFF;
- Max[i]=0;
- }
- }
-
- Scaling=scaling;
- }
- #define EEDECLARE(x) \
- EEdeclareInt(&Max[x]); \
- EEdeclareInt(&Min[x])
- void analogDeclareEE()
- {
- #if ANALOG_MAX_CHANNELS > 0
- EEDECLARE(0);
- EEDECLARE(1);
- EEDECLARE(2);
- EEDECLARE(3);
- #endif
- #if ANALOG_MAX_CHANNELS > 4
- EEDECLARE(4);
- EEDECLARE(5);
- EEDECLARE(6);
- EEDECLARE(7);
- #endif
- #if ANALOG_MAX_CHANNELS > 8
- EEDECLARE(8);
- EEDECLARE(9);
- EEDECLARE(10);
- EEDECLARE(11);
- #endif
- #if ANALOG_MAX_CHANNELS > 12
- EEDECLARE(12);
- EEDECLARE(13);
- EEDECLARE(14);
- EEDECLARE(15);
- #endif
-
- }
|