PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
app_ds1722.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 /** \file
31  * ESOS application program to demonstrate SPI mastering in ESOS.
32  * Application recreates code in \ref ds1722_spi_tempsense.c in Figure 10.34.
33  * (See Figure 10.31 in the text for circuit.)
34  *
35  * Application also has a flashing LED on RB15. Flashing LED is generated
36  * by an <em>software timer</em> calling a user-provided callback function.
37  *
38  * \note Demonstrates child tasks, ESOS software timers, and SPI service
39  */
40 
41 
42 // INCLUDEs go here (First include the main esos.h file)
43 // After that, the user can include what they need
44 #include "esos.h"
45 #ifdef __linux
46 #include "esos_pc.h"
47 #include "esos_pc_stdio.h"
48 // INCLUDE these so that printf() and our PC hacks work
49 #include <stdio.h>
50 #include <sys/select.h>
51 #include <termios.h>
52 #include <unistd.h>
53 #else
54 #include "esos_pic24.h"
55 #include "esos_pic24_rs232.h"
56 #include "esos_pic24_spi.h"
57 #include <stdio.h>
58 #endif
59 
60 // DEFINEs go here
61 
62 //#define PDBG(str) do{printf((str));printf("\n");}while(0)
63 #define PDBG(str)
64 
65 #ifndef __linux
66 #define CONFIG_LED1() CONFIG_RB15_AS_DIG_OUTPUT()
67 #define LED1 _LATB15
68 #define CONFIG_SLAVE_ENABLE() CONFIG_RB3_AS_DIG_OUTPUT()
69 #define SLAVE_ENABLE() _LATB3 = 1 //high true assertion
70 #define SLAVE_DISABLE() _LATB3 = 0
71 #else
72 #define CONFIG_LED1() printf("called CONFIG_LED1()\n")
73 #define CONFIG_SLAVE_ENABLE() printf("called CONFIG_SLAVE_ENABLE()\n")
74 #define SLAVE_ENABLE() printf("called SLAVE_ENABLE()\n")
75 #define SLAVE_DISABLE() printf("called SLAVE_DISABLE()\n")
76 uint8_t LED1 = TRUE; // LED1 is initially "on"
77 #endif
78 
79 // PROTOTYPEs go here
80 void configSPI1(void);
81 
82 // GLOBALs go here
83 // Generally, the user-created semaphores will be defined/allocated here
84 char psz_CRNL[3]= {0x0D, 0x0A, 0};
85 char psz_prompt[] = "Temp is ";
86 char psz_done[9]= {' ','D','O','N','E','!',0x0D, 0x0A, 0};
87 int16_t i16_temp;
88 
89 ESOS_SEMAPHORE(sem_dataReady);
90 ESOS_SEMAPHORE(sem_dataPrinted);
91 ESOS_SEMAPHORE(sem_ds1722Ready);
92 
93 #ifdef __linux
94 /*
95  * Simulate the timer ISR found on a MCU
96  * The PC doesn't have a timer ISR, so this task will periodically
97  * call the timer services callback instead.
98  * USED ONLY FOR DEVELOPMENT AND TESTING ON PC.
99  * Real MCU hardware doesn't need this task
100  */
101 ESOS_USER_TASK( __simulated_isr ) {
102  ESOS_TASK_BEGIN();
103  while (TRUE) {
104  // call the ESOS timer services callback just like a real H/W ISR would
105  __esos_tmrSvcsExecute();
107 
108  } // endof while(TRUE)
109  ESOS_TASK_END();
110 } // end child_task
111 #endif
112 
113 /************************************************************************
114  * User supplied functions
115  ************************************************************************
116  */
117 
118 /*
119  * An ESOS software timer callback function strobe the heartbeat LED.
120  *
121  * Toggles LED1 everytime the callback is called. Exact period is
122  * determined by application when this timer callback function is
123  * registered with ESOS. See \ref esos_RegisterTimer
124  * Application can change timer period on-the-fly with \ref esos_ChangeTimerPeriod
125  *
126  * \note Since this heartbeat is performed in an ESOS software
127  * timer callabck, a flashing LED indicates that the ESOS system
128  * tick ISR is being called properly. If the LED quits flashing,
129  * then the ESOS system tick has ceased working. This probably indicates
130  * some catastrophic failure of the system. However, the cause could
131  * be poorly-behaved user code that is manipulating the hardware registers
132  * with the timer or interrupt enables directly. ESOS provides functions
133  * to change state of interrupts and user code should never modify the
134  * hardware used by ESOS to implement the system tick.
135  * \hideinitializer
136  */
137 
138 // user-created timer callback
139 ESOS_USER_TIMER( swTimerLED ) {
140  LED1 = !LED1;
141 #ifdef __linux
142  if (LED1) {
143  printf("\a");
144  fflush(stdout);
145  }
146 #endif
147 } //endof swTimerLED
148 
149 
150 /*
151  * user task to setup DS1722 for temperature conversion.
152  * Will signal when DS1722 is ready to be used.
153  */
154 ESOS_USER_TASK(start_ds1722) {
155  ESOS_TASK_BEGIN();
156  configSPI1();
157  // configure DS1722 for 12-bit mode, continuous conversion
158  SLAVE_ENABLE(); //assert chipselect
159  ESOS_TASK_WAIT_ON_WRITE2SPI1(0x80, 0xE8);
160  SLAVE_DISABLE(); //deassert chipselect
161  // wait for first conversion to finish, then let other tasks proceed
162  ESOS_TASK_WAIT_TICKS(1500);
163  ESOS_SIGNAL_SEMAPHORE(sem_ds1722Ready, 1);
164  ESOS_TASK_END();
165 } //end task start_ds1722
166 
167 /*
168  * user task to read DS1722 SPI temerature sensor
169  */
170 ESOS_USER_TASK(read_ds1722) {
171  static uint16_t u16_lo, u16_hi;
172  static uint16_t au16_data[3];
173 
174  ESOS_TASK_BEGIN();
175  ESOS_TASK_WAIT_SEMAPHORE(sem_ds1722Ready, 1);
176  while (TRUE) {
177  // There are (at least) three different ways to cause the
178  // DS1722 to read the temperature. Choose one of the following:
179 #if 0
180  SLAVE_ENABLE(); //assert chipselect
181  ESOS_TASK_WAIT_ON_WRITE1SPI1(0x01); // LSB address
182  ESOS_TASK_WAIT_ON_READ2SPI1(u16_lo, u16_hi);
183  SLAVE_DISABLE(); //deassert chipselect
184 #endif
185 #if 0
186  SLAVE_ENABLE(); //assert chipselect
187  ESOS_TASK_WAIT_ON_WRITE1SPI1(0x01); // LSB address
190  SLAVE_DISABLE(); //deassert chipselect
191 #endif
192 #if 1
193  au16_data[0]= 0x01;
194  au16_data[1]= 0x00;
195  au16_data[2]= 0x00;
196  SLAVE_ENABLE();
197  ESOS_TASK_WAIT_ON_XFERNSPI1(&au16_data[0],&au16_data[0],3);
198  SLAVE_DISABLE();
199  u16_hi = au16_data[2];
200  u16_lo = au16_data[1];
201 #endif
202  i16_temp = ((u16_hi<<8) | u16_lo);
203  ESOS_SIGNAL_SEMAPHORE(sem_dataReady, 1);
204  ESOS_TASK_WAIT_TICKS(1500);
205  ESOS_TASK_WAIT_SEMAPHORE(sem_dataPrinted, 1);
206  } //end while()
207  ESOS_TASK_END();
208 } //end task read_ds1722
209 
210 
211 /*
212  * User task to display temperature results from DS1722.
213  * Used printf and floating point for convenience. A
214  * production application would likely create custom functions
215  * to avoid including these huge libraries.
216  */
217 ESOS_USER_TASK(update) {
218  float f_tempC, f_tempF;
219 
220  ESOS_TASK_BEGIN();
221  while (TRUE) {
222  ESOS_TASK_WAIT_SEMAPHORE(sem_dataReady, 1);
223  f_tempC = (float) i16_temp; //convert to floating point
224  f_tempC = f_tempC/256; //divide by precision
225  f_tempF = f_tempC*9/5 + 32;
226  printf("Temp is: 0x%0X, %4.4f (C), %4.4f (F)\n", i16_temp, (double) f_tempC, (double) f_tempF);
227  ESOS_SIGNAL_SEMAPHORE(sem_dataPrinted, 1);
228  } // end while(TRUE)
229  ESOS_TASK_END();
230 } // end update()
231 
232 void configSPI1(void) {
233  //spi clock = 40MHz/1*4 = 40MHz/4 = 10MHz
234  SPI1CON1 = SEC_PRESCAL_1_1 | //1:1 secondary prescale
235  PRI_PRESCAL_4_1 | //4:1 primary prescale
236  CLK_POL_ACTIVE_HIGH | //clock active high (CKP = 0)
237  SPI_CKE_OFF | //out changes inactive to active (CKE=0)
238  SPI_MODE8_ON | //8-bit mode
239  MASTER_ENABLE_ON; //master mode
240  //configure pins. Only need SDO, SCLK, and SDI
241  CONFIG_SDO1_TO_RP(6); //use RP6 for SDO
242  CONFIG_SCK1OUT_TO_RP(7); //use RP7 for SCLK
243  CONFIG_SDI1_TO_RP(5); //use RP5 for SDI
244  CONFIG_SLAVE_ENABLE(); //chip select for DS1722
245  SLAVE_DISABLE(); //disable the chip select
246  SPI1STATbits.SPIEN = 1; //enable SPI mode
247 }
248 
249 /****************************************************
250  * user_init()
251  ****************************************************
252  */
253 void user_init(void) {
254 
255  // Call the hardware-provided routines to print the
256  // HELLO_MSG to the screen. Must use this call because
257  // the ESOS communications subsystems is not yet fully
258  // initialized, since this call is in user_init()
259  //
260  // In general, users should call hardware-specific
261  // function like this.
262  __esos_unsafe_PutString( HELLO_MSG );
263 
264 #ifdef __linux
265  // register our little ESOS task to mimic MCU's TIMER T1 IRQ which kicks off
266  // the ESOS S/W timers when they expire
267  esos_RegisterTask( __simulated_isr );
268 #endif
269 
270  // configure our hardware to support to support our application
271  CONFIG_LED1();
272 
273  ESOS_INIT_SEMAPHORE(sem_ds1722Ready, 0);
274  ESOS_INIT_SEMAPHORE(sem_dataReady, 0);
275  ESOS_INIT_SEMAPHORE(sem_dataPrinted, 0);
276 
277  // user_init() should register at least one user task
278  esos_RegisterTask(start_ds1722);
279  esos_RegisterTask(read_ds1722);
280  esos_RegisterTask(update);
281 
282  // register our callback function with ESOS to create a software timer
283  esos_RegisterTimer( swTimerLED, 250);
284 
285 } // end user_init()