1 /*
2  * Copyright (c) 2022 OpenLuat & AirM2M
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy of
5  * this software and associated documentation files (the "Software"), to deal in
6  * the Software without restriction, including without limitation the rights to
7  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8  * the Software, and to permit persons to whom the Software is furnished to do so,
9  * subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20  */
21 
22 #include "user.h"
23 #define SAMPLE_PER_CH   (15)
24 #if 0
25 typedef struct
26 {
27     uint32_t Data[SAMPLE_PER_CH];
28 
29 }Channel_DataStruct;
30 
31 typedef struct
32 {
33     Channel_DataStruct ChannelData[ADC_CHANNEL_MAX];
34     uint32_t Ctrl;
35     uint8_t Enable[ADC_CHANNEL_MAX];
36     uint8_t CurChannel;
37 }ADC_CtrlStruct;
38 
39 static ADC_CtrlStruct prvADC;
40 
41 static void __FUNC_IN_RAM__ ADC_IrqHandle(int32_t IrqLine, void *pData)
42 {
43     int i;
44     uint8_t NextChannel;
45 
46     ADC0->ADC_CR1 = 0;
47     {
48         for(i = 0; i < SAMPLE_PER_CH; i++)
49         {
50             prvADC.ChannelData[prvADC.CurChannel].Data[i] = ADC0->ADC_DATA & 0x0fff;
51         }
52 
53 
54         if (prvADC.CurChannel == (ADC_CHANNEL_MAX - 1))
55         {
56             NextChannel = 0;
57         }
58         else
59         {
60             NextChannel = prvADC.CurChannel + 1;
61         }
62         prvADC.CurChannel = 0;
63         for(i = NextChannel; i < ADC_CHANNEL_MAX; i++)
64         {
65             if (prvADC.Enable[i])
66             {
67                 prvADC.CurChannel = i;
68                 break;
69             }
70         }
71         ADC0->ADC_FIFO = 3;
72         ADC0->ADC_CR1 = 0x060 | prvADC.Ctrl | prvADC.CurChannel;
73     }
74 }
75 
76 void ADC_GlobalInit(void)
77 {
78     int i;
79 //  for(i = 0; i < ADC_CHANNEL_MAX;i++)
80 //  {
81 //      prvADC.Enable[i] = 1;
82 //  }
83     prvADC.Enable[0] = 1;
84     prvADC.Ctrl = 2 << 3;
85     ADC0->ADC_FIFO_THR = SAMPLE_PER_CH - 1;
86     ADC0->ADC_FIFO = 3;
87     ADC0->ADC_CR2 &= ~(1 << 14);
88     ADC0->ADC_CR2 &= ~(1 << 13);
89     ISR_SetHandler(ADC0_IRQn, ADC_IrqHandle, NULL);
90 #ifdef __BUILD_OS___
91     ISR_SetPriority(ADC0_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY);
92 #else
93     ISR_SetPriority(ADC0_IRQn, 6);
94 #endif
95     ISR_OnOff(ADC0_IRQn, 1);
96     ADC0->ADC_CR1 = 0x060 | prvADC.Ctrl | prvADC.CurChannel;
97 }
98 
99 void ADC_SetSpeed(uint8_t Level)
100 {
101     prvADC.Ctrl = Level << 3;
102 }
103 
104 void ADC_IntelResistance(uint8_t OnOff)
105 {
106     if (OnOff)
107     {
108         ADC0->ADC_CR2 |= (1 << 13);
109     }
110     else
111     {
112         ADC0->ADC_CR2 &= ~(1 << 13);
113     }
114 }
115 void ADC_ChannelOnOff(uint8_t Channel, uint8_t OnOff)
116 {
117     if (!Channel) return;
118     int i;
119     ISR_OnOff(ADC0_IRQn, 0);
120     prvADC.Enable[Channel] = OnOff;
121     ISR_OnOff(ADC0_IRQn, 1);
122 }
123 uint32_t ADC_GetChannelValue(uint8_t Channel)
124 {
125     uint32_t total= 0;
126     uint32_t value = 0;
127     uint32_t max = 0;
128     uint32_t min = 0xffff;
129     uint32_t i;
130     uint32_t Data[SAMPLE_PER_CH];
131     ISR_OnOff(ADC0_IRQn, 0);
132     memcpy(&Data[10], &prvADC.ChannelData[Channel].Data[10], (SAMPLE_PER_CH - 10) * sizeof(uint32_t));
133     ISR_OnOff(ADC0_IRQn, 1);
134     for (i = 10; i < SAMPLE_PER_CH; i++)
135     {
136 //      DBG("%d,%d", i, Data[i]);
137         value = Data[i];
138         if(max < value)
139             max = value;
140         if(min > value)
141             min = value;
142         total += value;
143     }
144 
145     return ((total - max) -min)/(SAMPLE_PER_CH-12);
146 }
147 
148 uint32_t ADC_GetChannelValueBlock(uint8_t Channel)
149 {
150 
151 }
152 #else
153 
154 typedef struct
155 {
156     uint32_t Data[SAMPLE_PER_CH];
157     volatile uint8_t Done;
158 }ADC_CtrlStruct;
159 static ADC_CtrlStruct prvADC;
ADC_IrqHandle(int32_t IrqLine,void * pData)160 static void ADC_IrqHandle(int32_t IrqLine, void *pData)
161 {
162     int i;
163 
164     ADC0->ADC_CR1 = 0;
165     prvADC.Done = 1;
166     for(i = 0; i < SAMPLE_PER_CH; i++)
167     {
168         prvADC.Data[i] = ADC0->ADC_DATA & 0x0fff;
169     }
170     ADC0->ADC_FIFO = 3;
171 }
172 
ADC_GlobalInit(void)173 void ADC_GlobalInit(void)
174 {
175     int i;
176     ADC0->ADC_FIFO_THR = SAMPLE_PER_CH - 1;
177     ADC0->ADC_FIFO = 3;
178     ADC0->ADC_CR2 &= ~(1 << 14);
179     ADC0->ADC_CR2 &= ~(1 << 13);
180     ADC0->ADC_CR1 = 0;
181     ISR_SetHandler(ADC0_IRQn, ADC_IrqHandle, NULL);
182 #ifdef __BUILD_OS___
183     ISR_SetPriority(ADC0_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY - 1);
184 #else
185     ISR_SetPriority(ADC0_IRQn, 6);
186 #endif
187     ISR_OnOff(ADC0_IRQn, 0);
188 }
189 
ADC_IntelResistance(uint8_t OnOff)190 void ADC_IntelResistance(uint8_t OnOff)
191 {
192     if (OnOff)
193     {
194         ADC0->ADC_CR2 |= (1 << 13);
195     }
196     else
197     {
198         ADC0->ADC_CR2 &= ~(1 << 13);
199     }
200 }
ADC_ChannelOnOff(uint8_t Channel,uint8_t OnOff)201 void ADC_ChannelOnOff(uint8_t Channel, uint8_t OnOff)
202 {
203 
204 }
205 
ADC_GetChannelValue(uint8_t Channel)206 uint32_t ADC_GetChannelValue(uint8_t Channel)
207 {
208 
209     uint32_t total= 0;
210     uint32_t value = 0;
211     uint32_t max = 0;
212     uint32_t min = 0x0fff;
213     uint32_t i;
214     ADC0->ADC_FIFO = 3;
215     prvADC.Done = 0;
216     ISR_OnOff(ADC0_IRQn, 1);
217     ADC0->ADC_CR1 = 0x060 | Channel;
218     while(!prvADC.Done){;}
219     for (i = 10; i < SAMPLE_PER_CH; i++)
220     {
221 //      DBG("%d,%d", i, prvADC.Data[i]);
222         value = prvADC.Data[i];
223         if(max < value)
224             max = value;
225         if(min > value)
226             min = value;
227         total += value;
228     }
229     ADC0->ADC_CR1 = 0;
230     return ((total - max) -min)/(SAMPLE_PER_CH-12);
231 }
232 #endif
233