Skip to content
This repository
Browse code

The rest of the fix for issue#70

Former-commit-id: 1334298
  • Loading branch information...
commit ef798bf599ecbd31e4c73ebac0d781bf1053f85c 1 parent bd65d3d
Mark Sproul authored August 07, 2011

Showing 1 changed file with 195 additions and 164 deletions. Show diff stats Hide diff stats

  1. 359  hardware/pic32/cores/pic32/wiring_analog.c
359  hardware/pic32/cores/pic32/wiring_analog.c
@@ -47,8 +47,8 @@
47 47
 #include "wiring_private.h"
48 48
 #include "pins_arduino.h"
49 49
 
50  
-//uint8_t analog_reference = DEFAULT;
51  
-uint32_t analog_reference = 0;      //default to AVDD, AVSS
  50
+//uint8_t analog_reference	=	DEFAULT;
  51
+uint32_t analog_reference	=	0;      //default to AVDD, AVSS
52 52
 
53 53
 
54 54
 //*********************************************************************
@@ -57,24 +57,24 @@ void analogReference(uint8_t mode)
57 57
 	// can't actually set the register here because the default setting
58 58
 	// will connect AVCC and the AREF pin, which would cause a short if
59 59
 	// there's something connected to AREF.
60  
-//	analog_reference = mode;
  60
+//	analog_reference	=	mode;
61 61
     switch(mode)
62 62
     {
63 63
         case EXTERNAL:		//select Vref+,AVSS
64  
-            analog_reference = 0x2000;
  64
+            analog_reference	=	0x2000;
65 65
             break;
66 66
 
67 67
         case EXTMINUS:		//select AVDD, Vref-
68  
-            analog_reference = 0x4000;
  68
+            analog_reference	=	0x4000;
69 69
             break;
70 70
 
71 71
         case EXTPLUSMINUS:	//select Vref+, Vref-
72  
-            analog_reference = 0x6000;
  72
+            analog_reference	=	0x6000;
73 73
             break;
74 74
 
75 75
         case DEFAULT:
76 76
         default:			//select AVDD, AVSS
77  
-            analog_reference = 0x0000;
  77
+            analog_reference	=	0x0000;
78 78
             break;
79 79
     }
80 80
 
@@ -108,107 +108,107 @@ int analogRead(uint8_t pin)
108 108
 	switch(channelNumber)
109 109
 	{
110 110
 		case 0:
111  
-			AD1PCFG = 0xFFFE;
112  
-			AD1CHS = 0x00000000;
  111
+			AD1PCFG	=	0xFFFE;
  112
+			AD1CHS	=	0x00000000;
113 113
 
114 114
 			break;
115 115
 			
116 116
 		case 1:
117  
-			AD1PCFG = 0xFFFD;
118  
-			AD1CHS = 0x00010000;
  117
+			AD1PCFG	=	0xFFFD;
  118
+			AD1CHS	=	0x00010000;
119 119
 			break;
120 120
 
121 121
 		case 2:
122  
-			AD1PCFG = 0xFFFB;
123  
-			AD1CHS = 0x00020000;
  122
+			AD1PCFG	=	0xFFFB;
  123
+			AD1CHS	=	0x00020000;
124 124
 			break;
125 125
 
126 126
 		case 3:
127  
-			AD1PCFG = 0xFFF7;
128  
-			AD1CHS = 0x00030000;
  127
+			AD1PCFG	=	0xFFF7;
  128
+			AD1CHS	=	0x00030000;
129 129
 			break;
130 130
 
131 131
 		case 4:
132  
-			AD1PCFG = 0xFFEF;
133  
-			AD1CHS = 0x00040000;
  132
+			AD1PCFG	=	0xFFEF;
  133
+			AD1CHS	=	0x00040000;
134 134
 			break;
135 135
 
136 136
 		case 5:
137  
-			AD1PCFG = 0xFFDF;
138  
-			AD1CHS = 0x00050000;
  137
+			AD1PCFG	=	0xFFDF;
  138
+			AD1CHS	=	0x00050000;
139 139
 			break;
140 140
 
141 141
 		case 6:
142  
-			AD1PCFG = 0xFFBF;
143  
-			AD1CHS = 0x00060000;
  142
+			AD1PCFG	=	0xFFBF;
  143
+			AD1CHS	=	0x00060000;
144 144
 			break;
145 145
 
146 146
 		case 7:
147  
-			AD1PCFG = 0xFF7F;
148  
-			AD1CHS = 0x00070000;
  147
+			AD1PCFG	=	0xFF7F;
  148
+			AD1CHS	=	0x00070000;
149 149
 			break;
150 150
 
151 151
 		case 8:
152  
-			AD1PCFG = 0xFEFF;
153  
-			AD1CHS = 0x00080000;
  152
+			AD1PCFG	=	0xFEFF;
  153
+			AD1CHS	=	0x00080000;
154 154
 			break;
155 155
 
156 156
 		case 9:
157  
-			AD1PCFG = 0xFDFF;
158  
-			AD1CHS = 0x00090000;
  157
+			AD1PCFG	=	0xFDFF;
  158
+			AD1CHS	=	0x00090000;
159 159
 			break;
160 160
 
161 161
 		case 10:
162  
-			AD1PCFG = 0xFBFF;
163  
-			AD1CHS = 0x000A0000;
  162
+			AD1PCFG	=	0xFBFF;
  163
+			AD1CHS	=	0x000A0000;
164 164
 			break;
165 165
 
166 166
 		case 11:
167  
-			AD1PCFG = 0xF7FF;
168  
-			AD1CHS = 0x000B0000;
  167
+			AD1PCFG	=	0xF7FF;
  168
+			AD1CHS	=	0x000B0000;
169 169
 			break;
170 170
 
171 171
 		case 12:
172  
-			AD1PCFG = 0xEFFF;
173  
-			AD1CHS = 0x000C0000;
  172
+			AD1PCFG	=	0xEFFF;
  173
+			AD1CHS	=	0x000C0000;
174 174
 			break;
175 175
 
176 176
 		case 13:
177  
-			AD1PCFG = 0xDFFF;
178  
-			AD1CHS = 0x000D0000;
  177
+			AD1PCFG	=	0xDFFF;
  178
+			AD1CHS	=	0x000D0000;
179 179
 			break;
180 180
 
181 181
 		case 14:
182  
-			AD1PCFG = 0xBFFF;
183  
-			AD1CHS = 0x000E0000;
  182
+			AD1PCFG	=	0xBFFF;
  183
+			AD1CHS	=	0x000E0000;
184 184
 			break;
185 185
 
186 186
 		case 15:
187  
-			AD1PCFG = 0x7FFF;
188  
-			AD1CHS = 0x000F0000;
  187
+			AD1PCFG	=	0x7FFF;
  188
+			AD1CHS	=	0x000F0000;
189 189
 			break;
190 190
 
191 191
 	}
192 192
 
193 193
 
194  
-	AD1CON1 = 0; //Ends sampling, and starts converting
  194
+	AD1CON1	=	0; //Ends sampling, and starts converting
195 195
 
196 196
 	//Set up for manual sampling
197  
-	AD1CSSL = 0;
198  
-	AD1CON3 = 0x0002;	//Tad = internal 6 Tpb
199  
-	AD1CON2 = analog_reference;
  197
+	AD1CSSL	=	0;
  198
+	AD1CON3	=	0x0002;	//Tad = internal 6 Tpb
  199
+	AD1CON2	=	analog_reference;
200 200
 
201 201
 	//Turn on ADC
202  
-	AD1CON1SET = 0x8000;
  202
+	AD1CON1SET	=	0x8000;
203 203
 	
204 204
 	//Start sampling
205  
-	AD1CON1SET = 0x0002;
  205
+	AD1CON1SET	=	0x0002;
206 206
 	
207 207
 	//Delay for a bit
208 208
 	delayMicroseconds(2);
209 209
 
210 210
 	//Start conversion
211  
-	AD1CON1CLR = 0x0002;
  211
+	AD1CON1CLR	=	0x0002;
212 212
 	
213 213
 	//Wait for conversion to finish
214 214
 	while (!(AD1CON1 & 0x0001));
@@ -220,8 +220,17 @@ int analogRead(uint8_t pin)
220 220
 	return (analogValue);
221 221
 }
222 222
 
  223
+//*********************************************************************
  224
+//* PWM output only works on the pins with hardware support.
  225
+//* These are defined in the appropriate pins_.c file.
  226
+// For the rest of the pins, we default to digital output.
  227
+//*********************************************************************
  228
+
223 229
 #define	PWM_TIMER_PERIOD	((F_CPU / 256) / 490)
224 230
 
  231
+uint8_t pwm_active = 0; //keep track of active PWM outputs
  232
+
  233
+
225 234
 //*********************************************************************
226 235
 //*	PWM output only works on the pins with hardware support. 
227 236
 //*	These are defined in the appropriate pins_*.c file.
@@ -234,128 +243,127 @@ int analogRead(uint8_t pin)
234 243
 //*********************************************************************
235 244
 void analogWrite(uint8_t pin, int val)
236 245
 {
  246
+	uint8_t timer;
  247
+	uint8_t pwm_mask;
237 248
 
238  
-	// We need to make sure the PWM output is enabled for those pins
239  
-	// that support it, as we turn it off when digitally reading or
240  
-	// writing with them.  Also, make sure the pin is in output mode
241  
-	// for consistenty with Wiring, which doesn't require a pinMode
242  
-	// call for the analog output pins.
  249
+	// Ensure that the pin is an output
243 250
 	pinMode(pin, OUTPUT);
244  
-	if (val == 0)
  251
+
  252
+	// For the min and max values, just set the pin state
  253
+	if (val == 0) 
245 254
 	{
246  
-		digitalWrite(pin, LOW);
  255
+	    digitalWrite(pin, LOW);
247 256
 	}
  257
+
248 258
 	else if (val == 255)
249 259
 	{
250  
-		digitalWrite(pin, HIGH);
  260
+	    digitalWrite(pin, HIGH);
251 261
 	}
  262
+
  263
+	// Otherwise for pins that aren't timer pins, just set the pin
  264
+	// state based on the requested value. If it really is a timer
  265
+	// pin then we can set up the proper PWM behavior.
252 266
 	else
253 267
 	{
254  
-		switch(digitalPinToTimer(pin))
255  
-		{
256  
-		#ifdef _OCMP1
257  
-			case TIMER_OC1:
258  
-				//* Open Timer2 with Period register value
259  
-			//-	OpenTimer2(T2_ON | T2_PS_1_256, PWM_TIMER_PERIOD);
260  
-				T2CON = T2_PS_1_256;
261  
-				// Only reset the timer if we passed the new OCR target already
262  
-				if (PWM_TIMER_PERIOD < TMR2)
263  
-				{
264  
-					TMR2 = 0;
265  
-				}
266  
-				PR2 = PWM_TIMER_PERIOD;
267  
-				T2CONSET = T2_ON;
268  
-				OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, (PWM_TIMER_PERIOD*val)/256, (PWM_TIMER_PERIOD*val)/256  );
269  
-				//Set duty cycle on fly
270  
-				SetDCOC1PWM((PWM_TIMER_PERIOD*val)/256);
271  
-				break;
272  
-		#endif
273  
-
274  
-		#ifdef _OCMP2
275  
-			case TIMER_OC2:
276  
-				//* Open Timer2 with Period register value
277  
-			//-	OpenTimer2(T2_ON | T2_PS_1_256, PWM_TIMER_PERIOD);
278  
-				T2CON = T2_PS_1_256;
279  
-				// Only reset the timer if we passed the new OCR target already
280  
-				if (PWM_TIMER_PERIOD < TMR2)
281  
-				{
282  
-					TMR2 = 0;
283  
-				}
284  
-				PR2 = PWM_TIMER_PERIOD;
285  
-				T2CONSET = T2_ON;
286  
-				OpenOC2( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, (PWM_TIMER_PERIOD*val)/256, (PWM_TIMER_PERIOD*val)/256  );
287  
-				//Set duty cycle on fly
288  
-				SetDCOC2PWM((PWM_TIMER_PERIOD*val)/256);
289  
-				break;
290  
-		#endif
291  
-
292  
-		#ifdef _OCMP3
293  
-			case TIMER_OC3:
294  
-				//* Open Timer2 with Period register value
295  
-			//-	OpenTimer2(T2_ON | T2_PS_1_256, PWM_TIMER_PERIOD);
296  
-				T2CON = T2_PS_1_256;
297  
-				// Only reset the timer if we passed the new OCR target already
298  
-				if (PWM_TIMER_PERIOD < TMR2)
299  
-				{
300  
-					TMR2 = 0;
301  
-				}
302  
-				PR2 = PWM_TIMER_PERIOD;
303  
-				T2CONSET = T2_ON;
304  
-				OpenOC3( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, (PWM_TIMER_PERIOD*val)/256, (PWM_TIMER_PERIOD*val)/256  );
305  
-				//Set duty cycle on fly
306  
-				SetDCOC3PWM((PWM_TIMER_PERIOD*val)/256);
307  
-				break;
308  
-		#endif
309  
-
310  
-		#ifdef _OCMP4
311  
-			case TIMER_OC4:
312  
-				//* Open Timer2 with Period register value
313  
-			//-	OpenTimer2(T2_ON | T2_PS_1_256, PWM_TIMER_PERIOD);
314  
-				T2CON = T2_PS_1_256;
315  
-				// Only reset the timer if we passed the new OCR target already
316  
-				if (PWM_TIMER_PERIOD < TMR2)
317  
-				{
318  
-					TMR2 = 0;
319  
-				}
320  
-				PR2 = PWM_TIMER_PERIOD;
321  
-				T2CONSET = T2_ON;
322  
-				OpenOC4( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, (PWM_TIMER_PERIOD*val)/256, (PWM_TIMER_PERIOD*val)/256  );
323  
-				//Set duty cycle on fly
324  
-				SetDCOC4PWM((PWM_TIMER_PERIOD*val)/256);
325  
-				break;
326  
-		#endif
327  
-
328  
-		#ifdef _OCMP5
329  
-			case TIMER_OC5:
330  
-				//* Open Timer2 with Period register value
331  
-			//-	OpenTimer2(T2_ON | T2_PS_1_256, PWM_TIMER_PERIOD);
332  
-				T2CON = T2_PS_1_256;
333  
-				// Only reset the timer if we passed the new OCR target already
334  
-				if (PWM_TIMER_PERIOD < TMR2)
335  
-				{
336  
-					TMR2 = 0;
337  
-				}
338  
-				PR2 = PWM_TIMER_PERIOD;
339  
-				T2CONSET = T2_ON;
340  
-				OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, (PWM_TIMER_PERIOD*val)/256, (PWM_TIMER_PERIOD*val)/256  );
341  
-				//Set duty cycle on fly
342  
-				SetDCOC5PWM((PWM_TIMER_PERIOD*val)/256);
343  
-				break;
344  
-		#endif
345  
-
346  
-
347  
-			case NOT_ON_TIMER:
348  
-			default:
349  
-				if (val < 128)
350  
-				{
351  
-					digitalWrite(pin, LOW);
352  
-				}
353  
-				else
354  
-				{
355  
-					digitalWrite(pin, HIGH);
356  
-				}
357  
-		}
358  
-	}
  268
+	    timer = digitalPinToTimer(pin);
  269
+	    if (timer != NOT_ON_TIMER)
  270
+	    {
  271
+	        //should assert(timer < 8) here, but assertions aren't being used
  272
+	        pwm_mask = (1 << timer);
  273
+	    }
  274
+
  275
+	    // For pins that aren't actually PWM output pins, set the pin
  276
+	    // state based on the requested duty cycle.
  277
+	    if (timer == NOT_ON_TIMER)
  278
+	    {
  279
+	        if (val < 128)
  280
+	        {
  281
+	            digitalWrite(pin, LOW);
  282
+	        }
  283
+	        else
  284
+	        {
  285
+	            digitalWrite(pin, HIGH);
  286
+	        }
  287
+	    }
  288
+
  289
+	    // It's an actual PWM pin.
  290
+	    else
  291
+	    {
  292
+	        // If no PWM are currently active, then init Timer2
  293
+	        if (pwm_active == 0)
  294
+	        {
  295
+	            T2CON = T2_PS_1_256;
  296
+	            TMR2 = 0;
  297
+	            PR2 = PWM_TIMER_PERIOD;
  298
+	            T2CONSET = T2_ON;
  299
+	       }
  300
+
  301
+	        // If the requested PWM isn't active, init its output compare
  302
+	        if ((pwm_active & pwm_mask) == 0) 
  303
+	        {
  304
+	            switch (timer)
  305
+	            {
  306
+	                case TIMER_OC1:
  307
+	                    OC1R = ((PWM_TIMER_PERIOD*val)/256);
  308
+	                    OC1CON = OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE;
  309
+	                    OC1CONSET = OC_ON;
  310
+	                    break;
  311
+
  312
+	                case TIMER_OC2:
  313
+	                    OC2R = ((PWM_TIMER_PERIOD*val)/256);
  314
+	                    OC2CON = OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE;
  315
+	                    OC2CONSET = OC_ON;
  316
+	                    break;
  317
+
  318
+	                case TIMER_OC3:
  319
+	                    OC3R = ((PWM_TIMER_PERIOD*val)/256);
  320
+	                    OC3CON = OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE;
  321
+	                    OC3CONSET = OC_ON;
  322
+	                    break;
  323
+
  324
+	                case TIMER_OC4:
  325
+	                    OC4R = ((PWM_TIMER_PERIOD*val)/256);
  326
+	                    OC4CON = OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE;
  327
+	                    OC4CONSET = OC_ON;
  328
+	                    break;
  329
+
  330
+	                case TIMER_OC5:
  331
+	                    OC5R = ((PWM_TIMER_PERIOD*val)/256);
  332
+	                    OC5CON = OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE;
  333
+	                    OC5CONSET = OC_ON;
  334
+	                    break;
  335
+	            }
  336
+
  337
+	            pwm_active |= pwm_mask;
  338
+	        }
  339
+
  340
+	        // Set the duty cycle register for the requested output compare
  341
+	        switch (timer)
  342
+	        {
  343
+	            case TIMER_OC1:
  344
+	                OC1RS = ((PWM_TIMER_PERIOD*val)/256);
  345
+	                break;
  346
+
  347
+	            case TIMER_OC2:
  348
+	                OC2RS = ((PWM_TIMER_PERIOD*val)/256);
  349
+	                break;
  350
+
  351
+	            case TIMER_OC3:
  352
+	                OC3RS = ((PWM_TIMER_PERIOD*val)/256);
  353
+	                break;
  354
+
  355
+	            case TIMER_OC4:
  356
+	                OC4RS = ((PWM_TIMER_PERIOD*val)/256);
  357
+	                break;
  358
+
  359
+	            case TIMER_OC5:
  360
+	                OC5RS = ((PWM_TIMER_PERIOD*val)/256);
  361
+	                break;
  362
+	        }
  363
+	    }
  364
+
  365
+	}    
  366
+
359 367
 }
360 368
 
361 369
 
@@ -365,24 +373,47 @@ void turnOffPWM(uint8_t timer)
365 373
 	switch(timer)
366 374
 	{
367 375
 	#ifdef _OCMP1
368  
-		case TIMER_OC1:	CloseOC1();	break;
  376
+		case TIMER_OC1:	
  377
+		//-	CloseOC1();	
  378
+        OC1CONCLR	=	OC_ON;
  379
+		break;
369 380
 	#endif
370 381
 
371 382
 	#ifdef _OCMP2
372  
-		case TIMER_OC2:	CloseOC2();	break;
  383
+		case TIMER_OC2:	
  384
+		//-	CloseOC2();
  385
+	        OC2CONCLR	=	OC_ON;
  386
+			break;
373 387
 	#endif
374 388
 
375 389
 	#ifdef _OCMP3
376  
-		case TIMER_OC3:	CloseOC3();	break;
  390
+		case TIMER_OC3:
  391
+		//-	CloseOC3();
  392
+	        OC3CONCLR	=	OC_ON;
  393
+			break;
377 394
 	#endif
378 395
 
379 396
 	#ifdef _OCMP4
380  
-		case TIMER_OC4:	CloseOC4();	break;
  397
+		case TIMER_OC4:
  398
+		//-	CloseOC4();
  399
+	        OC4CONCLR	=	OC_ON;
  400
+			break;
381 401
 	#endif
382 402
 
383 403
 	#ifdef _OCMP5
384  
-		case TIMER_OC5:	CloseOC5();	break;
  404
+		case TIMER_OC5:
  405
+		//-	CloseOC5();
  406
+	        OC5CONCLR	=	OC_ON;
  407
+			break;
385 408
 	#endif
386 409
 
387 410
 	}
  411
+	// Turn off the bit saying that this PWM is active.
  412
+	pwm_active &=	~(1 << timer);
  413
+
  414
+	// If no PWM are active, turn off the timer.
  415
+	if (pwm_active == 0)
  416
+	{
  417
+    	T2CONCLR	=	T2_ON;
  418
+	}
388 419
 }

0 notes on commit ef798bf

Please sign in to comment.
Something went wrong with that request. Please try again.