You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
CubeSatSim/libs/libmf/source/adccalg.c

425 lines
6.9 KiB

#include "ax8052.h"
#include "libmfadc.h"
SFRX(ADCCALG00GAIN0, 0x7030) /* ADC Calibration Range 00 Gain Low Byte */
SFRX(ADCCALG00GAIN1, 0x7031) /* ADC Calibration Range 00 Gain High Byte */
SFRX(ADCCALG01GAIN0, 0x7032) /* ADC Calibration Range 01 Gain Low Byte */
SFRX(ADCCALG01GAIN1, 0x7033) /* ADC Calibration Range 01 Gain High Byte */
SFRX(ADCCALG10GAIN0, 0x7034) /* ADC Calibration Range 10 Gain Low Byte */
SFRX(ADCCALG10GAIN1, 0x7035) /* ADC Calibration Range 10 Gain High Byte */
#if defined(SDCC)
void adc_calibrate_gain(void)
{
__asm
ar2 = 0x02
ar3 = 0x03
ar4 = 0x04
ar5 = 0x05
ar6 = 0x06
ar7 = 0x07
ar0 = 0x00
ar1 = 0x01
clr a
push _IE
mov _IE,a
push _EIE
mov _EIE,#0x40
push _E2IE
mov _E2IE,a
mov _ADCCONV,a
mov r0,a
mov r1,a
mov r2,a
mov r3,a
mov r4,a
mov r5,a
mov _ADCCLKSRC,#0x28 ; 0.625MHz/16
mov _ADCCH0CONFIG,#0xe0
mov _ADCCH1CONFIG,#0xe8
mov _ADCCH2CONFIG,#0xf0
mov _ADCCH3CONFIG,#0xff
mov dptr,#_ADCTUNE1
mov a,#0xf2
movx @dptr,a
mov dptr,#_ADCCH0VAL0
movx a,@dptr
mov b,#0x10
adccalloop:
mov _ADCCONV,#0x01
adcwait0:
mov a,_PCON
anl a,#0x0C
orl a,#0x01
mov _PCON,a
mov a,_ADCCLKSRC
jb acc.7,adcwait0
mov dptr,#_ADCCH0VAL0
;; channel 0
movx a,@dptr
inc dptr
swap a
anl a,#0x0f
mov r6,a
movx a,@dptr
inc dptr
swap a
mov r7,a
anl a,#0xf0
orl a,r6
add a,r0
mov r0,a
mov a,r7
anl a,#0x0f
addc a,r1
mov r1,a
;; channel 1
movx a,@dptr
inc dptr
swap a
anl a,#0x0f
mov r6,a
movx a,@dptr
inc dptr
swap a
mov r7,a
anl a,#0xf0
orl a,r6
add a,r2
mov r2,a
mov a,r7
anl a,#0x0f
addc a,r3
mov r3,a
;; channel 2
movx a,@dptr
inc dptr
swap a
anl a,#0x0f
mov r6,a
movx a,@dptr
inc dptr
swap a
mov r7,a
anl a,#0xf0
orl a,r6
add a,r4
mov r4,a
mov a,r7
anl a,#0x0f
addc a,r5
mov r5,a
djnz b,adccalloop
;; switch off ADC
mov dptr,#_ADCTUNE1
mov a,#0x02
movx @dptr,a
mov _ADCCLKSRC,#0x07 ; off
pop _E2IE
pop _EIE
pop _IE
;; convert calibration constant to calibration value
calconst0 = 0x0F5C28F6 ; 0.48*2^29
calconst1 = 0x1C28F5C3 ; 0.88*2^29
calconst2 = 0x1999999A ; 0.8*2^29
push ar4
push ar5
push ar2
push ar3
mov __divslong_PARM_2,r0
mov (__divslong_PARM_2 + 1),r1
clr a
mov (__divslong_PARM_2 + 2),a
mov (__divslong_PARM_2 + 3),a
mov dptr,#calconst0&0xffff
mov b,#calconst0>>16
mov a,#calconst0>>24
lcall __divslong
mov a,dpl
mov r0,dph
mov dptr,#_ADCCALG00GAIN0
movx @dptr,a
inc dptr
mov a,r0
movx @dptr,a
pop (__divslong_PARM_2 + 1)
pop __divslong_PARM_2
clr a
mov (__divslong_PARM_2 + 2),a
mov (__divslong_PARM_2 + 3),a
mov dptr,#calconst1&0xffff
mov b,#calconst1>>16
mov a,#calconst1>>24
lcall __divslong
mov a,dpl
mov r0,dph
mov dptr,#_ADCCALG01GAIN0
movx @dptr,a
inc dptr
mov a,r0
movx @dptr,a
pop (__divslong_PARM_2 + 1)
pop __divslong_PARM_2
clr a
mov (__divslong_PARM_2 + 2),a
mov (__divslong_PARM_2 + 3),a
mov dptr,#calconst2&0xffff
mov b,#calconst2>>16
mov a,#calconst2>>24
lcall __divslong
mov a,dpl
mov r0,dph
mov dptr,#_ADCCALG10GAIN0
movx @dptr,a
inc dptr
mov a,r0
movx @dptr,a
__endasm;
}
#elif defined __CX51__ || defined __C51__
void adc_calibrate_gain(void)
{
#pragma asm
using 0
extrn CODE (?C?SLDIV)
clr a
push IE
mov IE,a
push EIE
mov EIE,#0x40
push E2IE
mov E2IE,a
mov ADCCONV,a
mov r0,a
mov r1,a
mov r2,a
mov r3,a
mov r4,a
mov r5,a
mov ADCCLKSRC,#0x28 ; 0.625MHz/16
mov ADCCH0CONFIG,#0xe0
mov ADCCH1CONFIG,#0xe8
mov ADCCH2CONFIG,#0xf0
mov ADCCH3CONFIG,#0xff
mov dptr,#ADCTUNE1
mov a,#0xf2
movx @dptr,a
mov dptr,#ADCCH0VAL0
movx a,@dptr
mov b,#0x10
adccalloop:
mov ADCCONV,#0x01
adcwait0:
mov a,PCON
anl a,#0x0C
orl a,#0x01
mov PCON,a
mov a,ADCCLKSRC
jb acc.7,adcwait0
mov dptr,#ADCCH0VAL0
;; channel 0
movx a,@dptr
inc dptr
swap a
anl a,#0x0f
mov r6,a
movx a,@dptr
inc dptr
swap a
mov r7,a
anl a,#0xf0
orl a,r6
add a,r0
mov r0,a
mov a,r7
anl a,#0x0f
addc a,r1
mov r1,a
;; channel 1
movx a,@dptr
inc dptr
swap a
anl a,#0x0f
mov r6,a
movx a,@dptr
inc dptr
swap a
mov r7,a
anl a,#0xf0
orl a,r6
add a,r2
mov r2,a
mov a,r7
anl a,#0x0f
addc a,r3
mov r3,a
;; channel 2
movx a,@dptr
inc dptr
swap a
anl a,#0x0f
mov r6,a
movx a,@dptr
inc dptr
swap a
mov r7,a
anl a,#0xf0
orl a,r6
add a,r4
mov r4,a
mov a,r7
anl a,#0x0f
addc a,r5
mov r5,a
djnz b,adccalloop
;; switch off ADC
mov dptr,#ADCTUNE1
mov a,#0x02
movx @dptr,a
mov ADCCLKSRC,#0x07 ; off
pop E2IE
pop EIE
pop IE
;; convert calibration constant to calibration value
calconst0l equ 0x28F6 ; 0.48*2^29
calconst0h equ 0x0F5C
calconst1l equ 0xF5C3 ; 0.88*2^29
calconst1h equ 0x1C28
calconst2l equ 0x999A ; 0.8*2^29
calconst2h equ 0x1999
push ar4
push ar5
push ar2
push ar3
mov r3,ar0
mov r2,ar1
clr a
mov r1,a
mov r0,a
mov r7,#calconst0l&0xff
mov r6,#calconst0l>>8
mov r5,#calconst0h&0xff
mov r4,#calconst0h>>8
lcall ?C?SLDIV
mov dptr,#ADCCALG00GAIN0
mov a,r7
movx @dptr,a
inc dptr
mov a,r6
movx @dptr,a
pop ar2
pop ar3
clr a
mov r1,a
mov r0,a
mov r7,#calconst1l&0xff
mov r6,#calconst1l>>8
mov r5,#calconst1h&0xff
mov r4,#calconst1h>>8
lcall ?C?SLDIV
mov dptr,#ADCCALG01GAIN0
mov a,r7
movx @dptr,a
inc dptr
mov a,r6
movx @dptr,a
pop ar2
pop ar3
clr a
mov r1,a
mov r0,a
mov r7,#calconst2l&0xff
mov r6,#calconst2l>>8
mov r5,#calconst2h&0xff
mov r4,#calconst2h>>8
lcall ?C?SLDIV
mov dptr,#ADCCALG10GAIN0
mov a,r7
movx @dptr,a
inc dptr
mov a,r6
movx @dptr,a
#pragma endasm
}
#else
#if defined __ICC8051__
// 6.4: Internal error: [EbkCodeNode::SetNextSpan]: Jump size optimization will not terminate!
#pragma optimize=low
#endif
void adc_calibrate_gain(void)
{
static const int32_t calconst0 = 0x0F5C28F6; /* 0.48*2^29 */
static const int32_t calconst1 = 0x1C28F5C3; /* 0.88*2^29 */
static const int32_t calconst2 = 0x1999999A; /* 0.8*2^29 */
uint8_t __autodata iesave = IE, eiesave = EIE, e2iesave = E2IE, cnt = 0x10;
uint16_t __autodata adcv0 = 0, adcv1 = 0, adcv2 = 0, v;
IE = 0;
EIE = 0x40;
E2IE = 0;
ADCCONV = 0;
ADCCLKSRC = 0x28; /* 0.625MHz/16 */
ADCCH0CONFIG = 0xe0;
ADCCH1CONFIG = 0xe8;
ADCCH2CONFIG = 0xf0;
ADCCH3CONFIG = 0xff;
ADCTUNE1 = 0xf2;
ADCCH0VAL0;
do {
ADCCONV = 0x01;
do {
enter_standby();
} while (ADCCLKSRC & 0x80);
v = ADCCH0VAL1;
v <<= 4;
v |= ADCCH0VAL0 >> 4;
adcv0 += v;
v = ADCCH1VAL1;
v <<= 4;
v |= ADCCH1VAL0 >> 4;
adcv1 += v;
v = ADCCH2VAL1;
v <<= 4;
v |= ADCCH2VAL0 >> 4;
adcv2 += v;
} while (--cnt);
/* switch off ADC */
ADCTUNE1 = 0x02;
ADCCLKSRC = 0x07;
E2IE = e2iesave;
EIE = eiesave;
IE = iesave;
/* convert calibration constant to calibration value */
v = calconst0 / adcv0;
ADCCALG00GAIN0 = v;
ADCCALG00GAIN1 = v >> 8;
v = calconst1 / adcv1;
ADCCALG01GAIN0 = v;
ADCCALG01GAIN1 = v >> 8;
v = calconst2 / adcv2;
ADCCALG10GAIN0 = v;
ADCCALG10GAIN1 = v >> 8;
}
#endif
#if 0
uint32_t mulx(uint8_t a, uint8_t b, int32_t c, int32_t d)
{
return c * d;
}
uint16_t divx(uint8_t a, uint8_t b, int32_t c, int16_t d)
{
return c / d;
}
#endif

Powered by TurnKey Linux.