PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dac_r2r.c
Go to the documentation of this file.
1 /*
2  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
3  * All rights reserved.
4  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
5  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
6  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose, without fee, and without written agreement is
10  * hereby granted, provided that the above copyright notice, the following
11  * two paragraphs and the authors appear in all copies of this software.
12  *
13  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
15  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
16  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17  *
18  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
23  *
24  * Please maintain this header in its entirety when copying/modifying
25  * these files.
26  *
27  *
28  */
29 
30 #include "pic24_all.h"
31 #include "stdio.h"
32 
33 // uncomment the next line to setup this project for a 12-bit ADC
34 #define USE_12BIT_ADC
35 
36 #ifdef USE_12BIT_ADC
37 #define ADC_LEN 12
38 #define ADC_NSTEPS 4096
39 #define ADC_12BIT_FLAG 1
40 #else
41 #define ADC_LEN 10
42 #define ADC_NSTEPS 1024
43 #define ADC_12BIT_FLAG 0
44 #endif
45 
46 // prototypes provided for each DAC we support in this little example
47 void configDAC(void);
48 void writeDAC(uint16_t u16_x, uint16_t u16_y);
49 
50 volatile uint8_t u8_per, u8_amp;
51 volatile uint16_t u16_per;
52 
53 const uint8_t au8_sinetbl[] = {127,133,139,146,152,158,164,170,176,181, \
54  187,192,198,203,208,212,217,221,225,229,233,236,239,242,244,247,249,250, \
55  252,253,253,254,254,254,253,253,252,250,249,247,244,242,239,236,233,229, \
56  225,221,217,212,208,203,198,192,187,181,176,170,164,158,152,146,139,133, \
57  127,121,115,108,102,96,90,84,78,73,67,62,56,51,46,42,37,33,29,25,21,18, \
58  15,12,10,7,5,4,2,1,1,0,0,0,1,1,2,4,5,7,10,12,15,18,21,25,29,33,37,42,46, \
59  51,56,62,67,73,78,84,90,96,102,108,115,121
60  };
61 
62 
63 /**
64 *** Select the DAC you want to use by uncomment _ONLY_ONE_ line below!
65 **/
66 //#define __DAC_R2R
67 //#define __DAC_MAX548A
68 #define __DAC_MAX5353
69 //#define __DAC_MAX518
70 //#define __DAC_MAX518_DUAL
71 
72 
73 #ifdef __DAC_R2R
74 #warning "DAC_R2R.C built for explicit R-2R DAC connected to RB9(MSb)-RB2(LSb)"
75 void configDAC() {
76  CONFIG_RB2_AS_DIG_OUTPUT();
77  CONFIG_RB3_AS_DIG_OUTPUT();
78  CONFIG_RB4_AS_DIG_OUTPUT();
79  CONFIG_RB5_AS_DIG_OUTPUT();
80  CONFIG_RB6_AS_DIG_OUTPUT();
81  CONFIG_RB7_AS_DIG_OUTPUT();
82  CONFIG_RB8_AS_DIG_OUTPUT();
83  CONFIG_RB9_AS_DIG_OUTPUT();
84 }
85 
86 void writeDAC(uint16_t u16_x, uint16_t u16_y) {
87  uint16_t u16_temp;
88 
89  u16_temp = LATB & 0xFC03; // read PORTB removing our eight bits
90  u16_temp |= ((u16_x & 0xFF00) >> 6); // put our eight bits into PORTB value
91  LATB = u16_temp;
92 }
93 #endif
94 
95 #ifdef __DAC_MAX548A
96 #warning "DAC_R2R.C built for SPI-based dual 8-bit MAX548A DAC connected to RP14(SDO) and RP13(SCLK)"
97 #define CONFIG_MAX548A_ENABLE() CONFIG_RA2_AS_DIG_OUTPUT()
98 #define MAX548A_ENABLE() _LATA2 = 0
99 #define MAX548A_DISABLE() _LATA2 = 1
100 
101 void configDAC(void) {
102  //spi clock = 40MHz/1*4 = 40MHz/4 = 10MHz
103  SPI1CON1 = SEC_PRESCAL_1_1 | //1:1 secondary prescale
104  PRI_PRESCAL_4_1 | //4:1 primary prescale
105  CLK_POL_ACTIVE_HIGH | //clock active high (CKP = 0)
106  SPI_CKE_ON | //out changes inactive to active (CKE=0)
107  SPI_MODE8_ON | //8-bit mode
108  MASTER_ENABLE_ON; //master mode
109 
110  //configure pins. Only need SDO, SCLK since MAX548 is output only
111  CONFIG_RB14_AS_DIG_OUTPUT();
112  CONFIG_SDO1_TO_RP(14); //use RP14 for SDO
113  CONFIG_RB13_AS_DIG_OUTPUT();
114  CONFIG_SCK1OUT_TO_RP(13); //use RP13 for SCLK
115  SPI1STATbits.SPIEN = 1; //enable SPI mode
116  CONFIG_MAX548A_ENABLE(); //chip select for MAX548
117  MAX548A_DISABLE(); //disable the chip select
118 }
119 
120 void writeDAC(uint16_t u16_x, uint16_t u16_y) {
121 
122  // only update DAC A
123  //MAX548A_ENABLE(); //assert chipselect
124  //ioMasterSPI1(0x09); //command to immediately write DAC A
125  //ioMasterSPI1(u16_x>>8); //write DAC A data
126  //MAX548A_DISABLE(); //release CS and update DAC outputs
127 
128  MAX548A_ENABLE(); //assert chipselect
129  ioMasterSPI1(0x02); //command to write DAC B input (do not change output)
130  ioMasterSPI1(u16_y>>8); //write DAC B data
131  MAX548A_DISABLE(); //release CS and update DAC input
132  MAX548A_ENABLE(); //assert chipselect
133  ioMasterSPI1(0x09); //command to write DAC A input and update both DAC outputs
134  ioMasterSPI1(u16_x>>8); //write DAC A data
135  MAX548A_DISABLE(); //release CS and update DAC outputs
136 }
137 #endif
138 
139 #ifdef __DAC_MAX5353
140 #warning "DAC_R2R.C built for SPI-based 12-bit MAX5353 DAC connected to RP14(SDO) and RP13(SCLK)"
141 #define CONFIG_MAX5353_ENABLE() CONFIG_RA3_AS_DIG_OUTPUT()
142 #define MAX5353_CMD_ANDMASK 0x1FFE
143 #define MAX5353_ENABLE() _LATA3 = 0
144 #define MAX5353_DISABLE() _LATA3 = 1
145 
146 void configDAC(void) {
147  //spi clock = 40MHz/1*4 = 40MHz/4 = 10MHz
148  SPI1CON1 = SEC_PRESCAL_1_1 | //1:1 secondary prescale
149  PRI_PRESCAL_4_1 | //4:1 primary prescale
150  CLK_POL_ACTIVE_HIGH | //clock active high (CKP = 0)
151  SPI_CKE_ON | //out changes inactive to active (CKE=0)
152  SPI_MODE16_ON | //16-bit mode
153  MASTER_ENABLE_ON; //master mode
154 
155  //configure pins. Only need SDO, SCLK since MAX548 is output only
156  CONFIG_RB14_AS_DIG_OUTPUT();
157  CONFIG_SDO1_TO_RP(14); //use RP14 for SDO
158  CONFIG_RB13_AS_DIG_OUTPUT();
159  CONFIG_SCK1OUT_TO_RP(13); //use RP13 for SCLK
160  SPI1STATbits.SPIEN = 1; //enable SPI mode
161  CONFIG_MAX5353_ENABLE(); //chip select for MAX548
162  MAX5353_DISABLE(); //disable the chip select
163 }
164 
165 void writeDAC(uint16_t u16_x, uint16_t u16_y) {
166  MAX5353_ENABLE(); //assert chipselect
167  //write DAC B data (with command bits and sub-bit cleared)
168  ioMasterSPI1((u16_x>>3) & MAX5353_CMD_ANDMASK);
169  MAX5353_DISABLE(); //release CS and update DAC input
170 }
171 #endif
172 
173 #ifdef __DAC_MAX518
174 #warning "DAC_R2R.C built for I2C-based single output 8-bit MAX518 DAC connected to RB9(SDA) and RB8(SCL)"
175 #define MAX518_I2C_ADDR 0x58 // see MAX518 datasheet 19-0393 Figure 6
176 #define MAX518_WRITE_DACA 0x00 // see MAX518 datasheet 19-0393 Figure 7
177 #define MAX518_WRITE_DACB 0x01 // see MAX518 datasheet 19-0393 Figure 7
178 
179 void configDAC(void) {
180  configI2C1(400); //configure I2C for 400 KHz
181 }
182 
183 void writeDAC(uint16_t u16_x, uint16_t u16_y) {
184  write2I2C1(MAX518_I2C_ADDR, MAX518_WRITE_DACA, (uint8_t) (u16_x>>8) );
185 }
186 #endif
187 
188 #ifdef __DAC_MAX518_DUAL
189 #warning "DAC_R2R.C built for I2C-based DUAL output 8-bit MAX518 DAC connected to RB9(SDA) and RB8(SCL)"
190 #warning "In this example, I2C SCL is beyond specification for the MAX518 DAC."
191 #define MAX518_I2C_ADDR 0x58 // see MAX518 datasheet 19-0393 Figure 6
192 #define MAX518_WRITE_DACA 0x00 // see MAX518 datasheet 19-0393 Figure 7
193 #define MAX518_WRITE_DACB 0x01 // see MAX518 datasheet 19-0393 Figure 7
194 
195 void configDAC(void) {
196  configI2C1(700); //configure I2C for 400 KHz
197 }
198 
199 void writeDAC(uint16_t u16_x, uint16_t u16_y) {
200  static uint8_t au8_buf[]= {MAX518_WRITE_DACA, 0, MAX518_WRITE_DACB, 0 };
201 
202  au8_buf[1] = (uint8_t) (u16_x>>8);
203  au8_buf[3] = (uint8_t) (u16_y>>8);
204  writeNI2C1(MAX518_I2C_ADDR, &au8_buf[0], 4);
205 
206 }
207 #endif
208 
209 
210 
211 void _ISR _T3Interrupt (void) {
212  static uint8_t u8_idx;
213  static uint16_t u16_idx, u16_old;
214  static uint16_t u16_val;
215 
216  writeDAC(u16_val, u16_idx); // write new DAC value
217 
218  // Compute DAC value for next time
219  u16_idx+=u16_per;
220  u8_idx = (uint8_t) (u16_idx>>9 );
221  u16_val = ((uint16_t)au8_sinetbl[u8_idx])<<8; // get sine fcn value
222  u16_val >>= u8_amp; // reduce sine amplitude based on input from pot
223 
224  if ((u16_idx^u16_old)&0x8000) _LATB12 = !_LATB12;
225  u16_old = u16_idx;
226 
227  _T3IF = 0; //clear T3 interrupt flag
228 }
229 
230 void configTimer3(void) {
231  // configure T3 as 32-bit timer to trigger every 1/64 second
232  T3CONbits.TON = 0;
233  T3CON = T3_PS_1_1 | T3_SOURCE_INT;
234  TMR3 = 0;
235  PR3 = usToU16Ticks(50, getTimerPrescale(T3CONbits)) - 1; // # of ticks for 50us (200KHz) seconds
236  _T3IP=7;
237  _T3IF=0;
238  _T3IE=1;
239  T3CONbits.TON = 1;
240 }
241 
242 
243 /** \file
244  * Performs a basic config of the ADC and samples two channels manually
245  * and sequentially with 12-bit results.
246  * Conversion results are printed to screen as both HEX values and voltages.
247 */
248 int main (void) {
249  uint8_t u8_uiCount;
250 
251  configBasic(HELLO_MSG);
252  // configure AN0 and AN1 to for analog input to PIC24 ADC
253  CONFIG_AN0_AS_ANALOG();
254  CONFIG_AN1_AS_ANALOG();
255  configDAC();
256  configTimer3();
257  CONFIG_RB12_AS_DIG_OUTPUT();
258  _LATB12 = 0;
259 
260  u8_uiCount=5;
261  while (1) {
262  configADC1_ManualCH0( ADC_CH0_POS_SAMPLEA_AN0, 31, ADC_12BIT_FLAG );
263  DELAY_MS(100);
264  u16_per =convertADC1();
265  if (u16_per==0) u16_per++; // u16_per must be >= 1
266 
267  configADC1_ManualCH0( ADC_CH0_POS_SAMPLEA_AN1, 31, ADC_12BIT_FLAG );
268  DELAY_MS(100);
269  u8_amp = convertADC1()>>9; // 0 <= u8_amp <= 7
270 
271  if (!u8_uiCount) {
272  printf("timestep=0x%04X amplitude shift = 0x%02X\n", u16_per, u8_amp );
273  u8_uiCount=5;
274  } else
275  u8_uiCount--;
276  } //endof while()
277 } // endof main()