@@ -883,3 +883,179 @@ func (p Pin) getMuxMode(config PinConfig) uint32 {
883883 panic ("machine: invalid pin mode" )
884884 }
885885}
886+
887+ // maximum ADC value for the currently configured resolution (used for scaling)
888+ var adcMaximum uint32
889+
890+ // InitADC is not used by this machine. Use `(ADC).Configure()`.
891+ func InitADC () {}
892+
893+ // Configure initializes the receiver's ADC peripheral and pin for analog input.
894+ func (a ADC ) Configure (config ADCConfig ) {
895+ // if not specified, use defaults: 10-bit resolution, 4 samples/conversion
896+ const (
897+ defaultResolution = uint32 (10 )
898+ defaultSamples = uint32 (4 )
899+ )
900+
901+ a .Pin .Configure (PinConfig {Mode : PinInputAnalog })
902+
903+ resolution , samples := config .Resolution , config .Samples
904+ if 0 == resolution {
905+ resolution = defaultResolution
906+ }
907+ if 0 == samples {
908+ samples = defaultSamples
909+ }
910+ if resolution > 12 {
911+ resolution = 12 // maximum resolution of 12 bits
912+ }
913+ adcMaximum = (uint32 (1 ) << resolution ) - 1
914+
915+ mode , average := a .mode (resolution , samples )
916+
917+ nxp .ADC1 .CFG .Set (mode | nxp .ADC_CFG_ADHSC ) // configure ADC1
918+ nxp .ADC2 .CFG .Set (mode | nxp .ADC_CFG_ADHSC ) // configure ADC2
919+
920+ // begin calibration
921+ nxp .ADC1 .GC .Set (average | nxp .ADC_GC_CAL )
922+ nxp .ADC2 .GC .Set (average | nxp .ADC_GC_CAL )
923+
924+ for a .isCalibrating () {
925+ } // wait for calibration
926+ }
927+
928+ // Get performs a single ADC conversion, returning a 16-bit unsigned integer.
929+ // The value returned will be scaled (uniformly distributed) if necessary so
930+ // that it is always in the range [0..65535], regardless of the ADC's configured
931+ // bit size (resolution).
932+ func (a ADC ) Get () uint16 {
933+ if ch1 , ch2 , ok := a .Pin .getADCChannel (); ok {
934+ for a .isCalibrating () {
935+ } // wait for calibration
936+ var val uint32
937+ if noADCChannel != ch1 {
938+ nxp .ADC1 .HC0 .Set (uint32 (ch1 ))
939+ for ! nxp .ADC1 .HS .HasBits (nxp .ADC_HS_COCO0 ) {
940+ }
941+ val = nxp .ADC1 .R0 .Get () & 0xFFFF
942+ } else {
943+ nxp .ADC2 .HC0 .Set (uint32 (ch2 ))
944+ for ! nxp .ADC2 .HS .HasBits (nxp .ADC_HS_COCO0 ) {
945+ }
946+ val = nxp .ADC2 .R0 .Get () & 0xFFFF
947+ }
948+ // should never be zero, but just in case, use UINT16_MAX so that the scalar
949+ // gets factored out of the conversion result, leaving the original reading
950+ // to be returned unaltered/unscaled.
951+ if adcMaximum == 0 {
952+ adcMaximum = 0xFFFF
953+ }
954+ // scale up to a 16-bit value
955+ return uint16 ((val * 0xFFFF ) / adcMaximum )
956+ }
957+ return 0
958+ }
959+
960+ // mode constructs bit masks for mode and average - used in ADC configuration
961+ // registers - from a given ADC bit size (resolution) and sample count.
962+ func (a ADC ) mode (resolution , samples uint32 ) (mode , average uint32 ) {
963+
964+ // use asynchronous clock (ADACK) (0 = IPG, 1 = IPG/2, or 3 = ADACK)
965+ mode = (nxp .ADC_CFG_ADICLK_ADICLK_3 << nxp .ADC_CFG_ADICLK_Pos ) & nxp .ADC_CFG_ADICLK_Msk
966+
967+ // input clock DIV2 (0 = DIV1, 1 = DIV2, 2 = DIV4, or 3 = DIV8)
968+ mode |= (nxp .ADC_CFG_ADIV_ADIV_1 << nxp .ADC_CFG_ADIV_Pos ) & nxp .ADC_CFG_ADIV_Msk
969+
970+ switch resolution {
971+ case 8 : // 8-bit conversion, sample period (ADC clocks) = 8
972+ mode |= (nxp .ADC_CFG_MODE_MODE_0 << nxp .ADC_CFG_MODE_Pos ) & nxp .ADC_CFG_MODE_Msk
973+ mode |= (nxp .ADC_CFG_ADSTS_ADSTS_3 << nxp .ADC_CFG_ADSTS_Pos ) & nxp .ADC_CFG_ADSTS_Msk
974+
975+ case 12 : // 12-bit conversion, sample period (ADC clocks) = 24
976+ mode |= (nxp .ADC_CFG_MODE_MODE_2 << nxp .ADC_CFG_MODE_Pos ) & nxp .ADC_CFG_MODE_Msk
977+ mode |= (nxp .ADC_CFG_ADSTS_ADSTS_3 << nxp .ADC_CFG_ADSTS_Pos ) & nxp .ADC_CFG_ADSTS_Msk
978+ mode |= nxp .ADC_CFG_ADLSMP
979+
980+ default : // 10-bit conversion, sample period (ADC clocks) = 20
981+ mode |= (nxp .ADC_CFG_MODE_MODE_1 << nxp .ADC_CFG_MODE_Pos ) & nxp .ADC_CFG_MODE_Msk
982+ mode |= (nxp .ADC_CFG_ADSTS_ADSTS_2 << nxp .ADC_CFG_ADSTS_Pos ) & nxp .ADC_CFG_ADSTS_Msk
983+ mode |= nxp .ADC_CFG_ADLSMP
984+ }
985+
986+ if samples >= 4 {
987+ if samples >= 32 {
988+ // 32 samples averaged
989+ mode |= (nxp .ADC_CFG_AVGS_AVGS_3 << nxp .ADC_CFG_AVGS_Pos ) & nxp .ADC_CFG_AVGS_Msk
990+ } else if samples >= 16 {
991+ // 16 samples averaged
992+ mode |= (nxp .ADC_CFG_AVGS_AVGS_2 << nxp .ADC_CFG_AVGS_Pos ) & nxp .ADC_CFG_AVGS_Msk
993+ } else if samples >= 8 {
994+ // 8 samples averaged
995+ mode |= (nxp .ADC_CFG_AVGS_AVGS_1 << nxp .ADC_CFG_AVGS_Pos ) & nxp .ADC_CFG_AVGS_Msk
996+ } else {
997+ // 4 samples averaged
998+ mode |= (nxp .ADC_CFG_AVGS_AVGS_0 << nxp .ADC_CFG_AVGS_Pos ) & nxp .ADC_CFG_AVGS_Msk
999+ }
1000+ average = nxp .ADC_GC_AVGE
1001+ }
1002+
1003+ return mode , average
1004+ }
1005+
1006+ // isCalibrating returns true if and only if either one (or both) of ADC1 and
1007+ // ADC2 have their calibrating flags set. ADC reads must wait until these flags
1008+ // are clear before attempting a conversion.
1009+ func (a ADC ) isCalibrating () bool {
1010+ return nxp .ADC1 .GC .HasBits (nxp .ADC_GC_CAL ) || nxp .ADC2 .GC .HasBits (nxp .ADC_GC_CAL )
1011+ }
1012+
1013+ const noADCChannel = uint8 (0xFF )
1014+
1015+ // getADCChannel returns the input channel for ADC1/ADC2 of the receiver Pin p.
1016+ func (p Pin ) getADCChannel () (adc1 , adc2 uint8 , ok bool ) {
1017+ switch p {
1018+ case PA12 : // [AD_B0_12]: ADC1_IN1 ~
1019+ return 1 , noADCChannel , true
1020+ case PA13 : // [AD_B0_13]: ADC1_IN2 ~
1021+ return 2 , noADCChannel , true
1022+ case PA14 : // [AD_B0_14]: ADC1_IN3 ~
1023+ return 3 , noADCChannel , true
1024+ case PA15 : // [AD_B0_15]: ADC1_IN4 ~
1025+ return 4 , noADCChannel , true
1026+ case PA16 : // [AD_B1_00]: ADC1_IN5 ADC2_IN5
1027+ return 5 , 5 , true
1028+ case PA17 : // [AD_B1_01]: ADC1_IN6 ADC2_IN6
1029+ return 6 , 6 , true
1030+ case PA18 : // [AD_B1_02]: ADC1_IN7 ADC2_IN7
1031+ return 7 , 7 , true
1032+ case PA19 : // [AD_B1_03]: ADC1_IN8 ADC2_IN8
1033+ return 8 , 8 , true
1034+ case PA20 : // [AD_B1_04]: ADC1_IN9 ADC2_IN9
1035+ return 9 , 9 , true
1036+ case PA21 : // [AD_B1_05]: ADC1_IN10 ADC2_IN10
1037+ return 10 , 10 , true
1038+ case PA22 : // [AD_B1_06]: ADC1_IN11 ADC2_IN11
1039+ return 11 , 11 , true
1040+ case PA23 : // [AD_B1_07]: ADC1_IN12 ADC2_IN12
1041+ return 12 , 12 , true
1042+ case PA24 : // [AD_B1_08]: ADC1_IN13 ADC2_IN13
1043+ return 13 , 13 , true
1044+ case PA25 : // [AD_B1_09]: ADC1_IN14 ADC2_IN14
1045+ return 14 , 14 , true
1046+ case PA26 : // [AD_B1_10]: ADC1_IN15 ADC2_IN15
1047+ return 15 , 15 , true
1048+ case PA27 : // [AD_B1_11]: ADC1_IN0 ADC2_IN0
1049+ return 16 , 16 , true
1050+ case PA28 : // [AD_B1_12]: ~ ADC2_IN1
1051+ return noADCChannel , 1 , true
1052+ case PA29 : // [AD_B1_13]: ~ ADC2_IN2
1053+ return noADCChannel , 2 , true
1054+ case PA30 : // [AD_B1_14]: ~ ADC2_IN3
1055+ return noADCChannel , 3 , true
1056+ case PA31 : // [AD_B1_15]: ~ ADC2_IN4
1057+ return noADCChannel , 4 , true
1058+ default :
1059+ return noADCChannel , noADCChannel , false
1060+ }
1061+ }
0 commit comments