PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
i2c_slave_reverse_string.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 #include "pic24_all.h"
30 
31 
32 /** \file
33 I2C Example: Demonstrates a PIC24 CPU
34 acting as an I2C slave. The PIC24 slave responds
35 to both write and read transactions.
36 */
37 
38 void reverseString(volatile char *psz_s1, volatile char *psz_s2) {
39  volatile char *psz_s1end;
40  if (!(*psz_s1)) {
41  *psz_s2 = 0; //psz_s1 is empty, return.
42  return;
43  }
44  psz_s1end = psz_s1;
45  //find end of first string
46  while (*psz_s1end) psz_s1end++;
47  psz_s1end--; //backup one to first non-zero byte
48  //now copy to S2 in reverse order
49  while (psz_s1end != psz_s1) {
50  *psz_s2 = *psz_s1end;
51  psz_s1end--;
52  psz_s2++;
53  }
54  //copy last byte
55  *psz_s2 = *psz_s1end;
56  psz_s2++;
57  //mark end of string
58  *psz_s2 = 0;
59 }
60 
61 
62 
63 #define SLAVE_I2C_ADDR 0x60
64 
65 typedef enum {
66  STATE_WAIT_FOR_ADDR,
67  STATE_WAIT_FOR_WRITE_DATA,
68  STATE_SEND_READ_DATA,
69  STATE_SEND_READ_LAST
70 } STATE;
71 
72 volatile STATE e_mystate = STATE_WAIT_FOR_ADDR;
73 #define BUFSIZE 64
74 volatile char sz_1[BUFSIZE+1];
75 volatile char sz_2[BUFSIZE+1];
76 volatile uint16_t u16_index;
77 
78 
79 void _ISRFAST _SI2C1Interrupt(void) {
80  uint8_t u8_c;
81  _SI2C1IF = 0;
82  switch (e_mystate) {
83  case STATE_WAIT_FOR_ADDR:
84  u8_c = I2C1RCV; //clear RBF bit for address
85  u16_index = 0;
86  //check the R/W bit and see if read or write transaction
87  if (I2C1STATbits.R_W) {
88  I2C1TRN = sz_2[u16_index++]; //get first data byte
89  I2C1CONbits.SCLREL = 1; //release clock line so MASTER can drive it
90  e_mystate = STATE_SEND_READ_DATA; //read transaction
91  } else e_mystate = STATE_WAIT_FOR_WRITE_DATA;
92  break;
93  case STATE_WAIT_FOR_WRITE_DATA:
94  //character arrived, place in buffer
95  sz_1[u16_index++] = I2C1RCV; //read the byte
96  if (sz_1[u16_index-1] == 0) {
97  //have a complete string, reverse it.
98  reverseString(sz_1,sz_2);
99  e_mystate = STATE_WAIT_FOR_ADDR; //wait for next transaction
100  }
101  break;
102  case STATE_SEND_READ_DATA:
103  //just keep placing reversed characters in buffer as MASTER reads our I2C port
104  I2C1TRN = sz_2[u16_index++];
105  I2C1CONbits.SCLREL = 1; //release clock line so MASTER can drive it
106  if (sz_2[u16_index-1] == 0) e_mystate = STATE_SEND_READ_LAST;
107  //this is the last character, after byte is shifted out, release the clock line again
108  break;
109  case STATE_SEND_READ_LAST: //this is interrupt for last character finished shifting out
110  e_mystate = STATE_WAIT_FOR_ADDR;
111  break;
112  default:
113  e_mystate = STATE_WAIT_FOR_ADDR;
114  }
115 
116 }
117 
118 int main (void) {
119  configBasic(HELLO_MSG);
120  configI2C1(400); //configure I2C for 400 KHz
121  I2C1ADD = SLAVE_I2C_ADDR>>1; //initialize the address register
122  _SI2C1IF = 0;
123 #ifdef _SI2C1IP
124  _SI2C1IP = 1;
125 #else
126 #ifdef _SI2C1IP0
127  _SI2C1IP0 = 1; //header files can be inconsistent in how these are defined for PIC24H versus PIC24F
128  _SI2C1IP1 = 0;
129  _SI2C1IP2 = 0;
130 #endif
131 #endif
132  _SI2C1IE = 1; //enable ISR
133  while (1) doHeartbeat(); //ISR does all work
134 }