PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
spi_slave_revstring.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 
32 /** \file
33  * SPI example: PIC24 uC in slave mode talking to PIC24 uC in master mode (spi_master_revstring.c),
34  * which is using this slave PIC24 uC to reverse strings.
35 */
36 void reverseString(volatile char *psz_s1, volatile char *psz_s2);
37 
38 #define CONFIG_SLAVE_ORDY() CONFIG_RB2_AS_DIG_OUTPUT()
39 #define SLAVE_ORDY _LATB2
40 
41 typedef enum {
42  STATE_WAIT_FOR_STRING,
43  STATE_SEND_REV_STRING,
44  STATE_LAST_REVCHAR_STRING,
45 } STATE;
46 
47 volatile STATE e_mystate = STATE_WAIT_FOR_STRING;
48 #define BUFSIZE 63
49 volatile char sz_1[BUFSIZE+1];
50 volatile char sz_2[BUFSIZE+1];
51 volatile uint16_t u16_index;
52 
53 void _ISR _SPI1Interrupt (void) {
54  uint16_t u16_tmp;
55  switch (e_mystate) {
56  case STATE_WAIT_FOR_STRING:
57  //character arrived, place in buffer
58  sz_1[u16_index] = SPI1BUF;
59  u16_index++;
60  if (sz_1[u16_index-1] == 0) {
61 
62  //have a complete string, reverse it.
63  reverseString(sz_1,sz_2);
64  //place first character of reversed string in SPIBUF
65  u16_index = 0;
66  SPI1BUF = sz_2[u16_index];
67  u16_index++;
68  SLAVE_ORDY = 1; //indicate to MASTER that reversed string is ready
69  e_mystate = STATE_SEND_REV_STRING;
70  }
71  break;
72  case STATE_SEND_REV_STRING:
73  u16_tmp = SPI1BUF; //must read the SPIBUF to prevent overflow, discard it.
74  //just keep placing reversed characters in buffer as MASTER reads our SPI port
75  SPI1BUF = sz_2[u16_index];
76  u16_index++;
77  if (sz_2[u16_index-1] == 0) {
78  //this is the last character, no more data
79  SLAVE_ORDY = 0;
80  e_mystate = STATE_LAST_REVCHAR_STRING;
81  }
82  break;
83  case STATE_LAST_REVCHAR_STRING:
84  u16_index = 0;
85  u16_tmp = SPI1BUF; //must read the SPIBUF to prevent overflow, discard it.
86  //null terminator of reversed string just read, wait for next string
87  e_mystate = STATE_WAIT_FOR_STRING;
88  break;
89  default:
90  e_mystate = STATE_WAIT_FOR_STRING;
91  }
92  _SPI1IF = 0; //clear interrupt flag
93 }
94 
95 void reverseString(volatile char *psz_s1, volatile char *psz_s2) {
96  volatile char *psz_s1end;
97  if (!(*psz_s1)) {
98  *psz_s2 = 0; //psz_s1 is empty, return.
99  return;
100  }
101  psz_s1end = psz_s1;
102  //find end of first string
103  while (*psz_s1end) psz_s1end++;
104  psz_s1end--; //backup one to first non-zero byte
105  //now copy to S2 in reverse order
106  while (psz_s1end != psz_s1) {
107  *psz_s2 = *psz_s1end;
108  psz_s1end--;
109  psz_s2++;
110  }
111  //copy last byte
112  *psz_s2 = *psz_s1end;
113  psz_s2++;
114  //mark end of string
115  *psz_s2 = 0;
116 }
117 
118 void configSPI1(void) {
119  //no need for prescaler since master supplies the clock
120  SPI1CON1 = CLK_POL_ACTIVE_HIGH |
121  SPI_CKE_ON |
122  SLAVE_ENABLE_ON |
123  SPI_MODE8_ON |
124  MASTER_ENABLE_OFF;
125 
126  //configure pins
127 #if (defined(__dsPIC33E__) || defined(__PIC24E__))
128  //nothing to do here. On this family, the SPI1 port uses dedicated
129  //pins for higher speed. The SPI2 port can be used with remappable pins.
130  //you may need to add code to disable analog functionality if the SPI ports
131  //are on analog-capable pins.
132 #else
133  CONFIG_SDO1_TO_RP(6); //use RP6 for SDO
134  CONFIG_RP6_AS_DIG_PIN(); //Ensure that this is a digital pin
135  CONFIG_SCK1IN_TO_RP(7); //use RP7 for SCLK input
136  CONFIG_RP7_AS_DIG_PIN(); //Ensure that this is a digital pin
137  CONFIG_SDI1_TO_RP(5); //use RP5 for SDI
138  CONFIG_RP5_AS_DIG_PIN(); //Ensure that this is a digital pin
139  CONFIG_SS1IN_TO_RP(3); //use RP3 for SS#
140  CONFIG_RP3_AS_DIG_PIN(); //Ensure that this is a digital pin
141 #endif
142  CONFIG_SLAVE_ORDY(); //handshake to indicate output ready
143  SLAVE_ORDY = 0; //output is not ready
144  u16_index = 0; //no data yet
145  _SPI1IF = 0; //clear the flag
146  _SPI1IP = 3; //choose a priority
147  _SPI1IE = 1; //enable the interrupt
148  SPI1STATbits.SPIROV = 0; //clear overflow flag
149  SPI1STATbits.SPIEN = 1; //enable SPI mode
150 }
151 
152 
153 int main (void) {
154  configClock(); //no UART for slave
155  configHeartbeat();
156  configSPI1();
157  while (1) doHeartbeat();
158 }