PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dataXfer.c
Go to the documentation of this file.
1 #include "dataXfer.h"
2 #include <string.h>
3 #include <stdio.h>
4 
5 /** \file
6  * \brief Implementation of the \ref index "uC data transfer protocol".
7  */
8 
9 void
13 }
14 
15 
16 /// \name Send functions
17 //@{
18 
19 void
20 outCharXfer(char c) {
21  // If we're sending a character that needs escaping, then escape it.
22  OUT_CHAR(c);
23  if (c == CMD_TOKEN)
24  OUT_CHAR(ESCAPED_CMD);
25 }
26 
27 void
28 specifyVar(uint u_varIndex, volatile void* pv_data, uint u_size,
29  BOOL b_isWriteable, char* psz_format, char* psz_name,
30  char* psz_desc) {
31  uint u_len;
32 
33  // Make sure this variable exists
34  ASSERTM("specifyVar:indexTooHigh", u_varIndex < NUM_XFER_VARS);
35  // Make sure the data isn't NULL
36  ASSERTM("specifyVar:nullData", pv_data != NULL);
37  // Make sure the size is valid
38  ASSERTM("specifyVar:invalidSize", (u_size > 0) && (u_size <= 256));
39 
40  // Update data structure
41  xferVar[u_varIndex].pu8_data = (uint8_t*) pv_data;
42  xferVar[u_varIndex].u8_size = u_size - 1;
43  assignBit(u_varIndex, b_isWriteable);
44 
45  // Send a command
46  OUT_CHAR(CMD_TOKEN);
47 
48  // Send a specification: The spec code, index, then length
50  outCharXfer(u_varIndex);
51  // Include the space taken by the three NULL characters, minus one since a
52  // length of 1 is sent as 0, plus one for the variable size byte.
53  u_len = strlen(psz_format) + strlen(psz_name) + strlen(psz_desc) + 3 - 1 + 1;
54  // Allow a maximum string length of 255.
55  outCharXfer(u_len <= 255 ? u_len : 255);
56 
57  // Send the size of this variable, minus 1 since a size of 1 is sent as a 0.
58  outCharXfer(u_size - 1);
59 
60  // Send the strings
61  u_len = 1;
62  do {
63  if (u_len++ > 256) return;
64  outCharXfer(*psz_format);
65  } while (*psz_format++);
66  do {
67  if (u_len++ > 256) return;
68  outCharXfer(*psz_name);
69  } while (*psz_name++);
70  do {
71  if (u_len++ > 256) return;
72  outCharXfer(*psz_desc);
73  } while (*psz_desc++);
74 }
75 
76 void
77 sendVar(uint u_varIndex) {
78  XFER_VAR* pXferVar;
79  uint8_t u8_size;
80  uint8_t* pu8_data;
81  // Make sure this variable exists
82  ASSERTM("sendVar:indexTooHigh", u_varIndex < NUM_XFER_VARS);
83  // Note: The MS C compiler flags the statement
84  // XFER_VAR* pXferVar = xferVar + u_varIndex;
85  // as an error. It's OK in MS C++. Apparently, the C compiler doesn't
86  // support the newer C99 syntax. Therefore, u8_size and pu8_data are
87  // also declared above.
88  pXferVar = xferVar + u_varIndex;
89  ASSERTM("sendVar:indexNotSpecified", pXferVar->pu8_data != NULL);
90  // Make sure it's read/write (PC only)
91 #ifndef __PIC__
92  ASSERTM("sendVar:notWriteable", isVarWriteable(u_varIndex));
93 #endif
94 
95  // Send a command
96  OUT_CHAR(CMD_TOKEN);
97 
98  // Send short/long var info
99  u8_size = pXferVar->u8_size;
100  if ((u8_size + 1) > SHORT_VAR_MAX_LEN) {
101  // Send a long var: The long var code, index, then length
103  outCharXfer(u_varIndex);
104  outCharXfer(u8_size);
105  } else {
106  // Send a short var
107  outCharXfer((u_varIndex << VAR_SIZE_BITS) | u8_size);
108  }
109 
110  // Send data
111  pu8_data = pXferVar->pu8_data;
112  do {
113  outCharXfer(*pu8_data++);
114  } while (u8_size--);
115 }
116 
117 //@}
118 
119 #ifndef __PIC__
120 int
121 formatVar(uint u_varIndex, char* psz_buf) {
122  XFER_VAR* pXferVar;
123  uint8_t u8_size;
124  unsigned long long ull_buf = 0; // The biggest data type available
125 
126  // Make sure this variable exists
127  ASSERTM("formatVar:indexTooHigh", u_varIndex < NUM_XFER_VARS);
128  // Note: The MS C compiler flags the statement
129  // XFER_VAR* pXferVar = xferVar + u_varIndex;
130  // as an error. It's OK in MS C++. Apparently, the C compiler doesn't
131  // support the newer C99 syntax. Therefore, u8_size and pu8_data are
132  // also declared above.
133  pXferVar = xferVar + u_varIndex;
134  ASSERTM("formatVar:indexNotSpecified", pXferVar->pu8_data != NULL);
135  u8_size = pXferVar->u8_size + 1;
136 
137  // Copy the data over to the largest available var for formatting
138  ASSERT(u8_size <= sizeof(ull_buf));
139  memcpy(&ull_buf, pXferVar->pu8_data, u8_size);
140  return sprintf(psz_buf, pXferVar->psz_format, ull_buf);
141 }
142 #endif
143 
144 #ifdef __PIC__
145 
146 #include "pic24_clockfreq.h"
147 #include "pic24_util.h"
148 #include "pic24_serial.h"
149 
150 uint
151 receiveVar(char* p_c) {
152  // Receive the data by stepping the machine until it outputs
153  // something
154  do {
155  // While there's no data, run the timeout counter
156  RECEIVE_ERROR re;
157  uint32_t u32_count = 0;
158  while (!isCharReady()) {
159  if (u32_count < RECEIVE_TIMEOUT)
160  u32_count++;
161  doHeartbeat();
162  }
163 
164  // Step the machine
165  *p_c = inChar();
166  if (u32_count >= RECEIVE_TIMEOUT)
167  notifyOfTimeout();
168  re = stepReceiveMachine(*p_c);
169  if (re != ERR_NONE) {
170  outString("Data receive error: ");
172  outChar('\n');
173  }
174  } while (!isReceiveMachineChar() && !isReceiveMachineData());
175 
176  // Note that p_c already contains the received character, since it's
177  // always the last thing received from inChar().
178  return getReceiveMachineIndex();
179 }
180 
181 char
182 inCharXfer() {
183  char c;
184  while (receiveVar(&c) != CHAR_RECEIVED_INDEX);
185  return c;
186 }
187 #endif