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