blob: 40389ba4518ea7785dc72dcda279a81c192bb742 [file] [log] [blame]
jerrymf1579332013-02-07 01:56:28 +00001/*----------------------------------------------------------------------------*/
2/* Copyright (c) FIRST 2008. All Rights Reserved. */
3/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
5/*----------------------------------------------------------------------------*/
6
7#include "SerialPort.h"
8
9#include "NetworkCommunication/UsageReporting.h"
10#include "visa/visa.h"
11
12//static ViStatus _VI_FUNCH ioCompleteHandler (ViSession vi, ViEventType eventType, ViEvent event, ViAddr userHandle);
13
14/**
15 * Create an instance of a Serial Port class.
16 *
17 * @param baudRate The baud rate to configure the serial port. The cRIO-9074 supports up to 230400 Baud.
18 * @param dataBits The number of data bits per transfer. Valid values are between 5 and 8 bits.
19 * @param parity Select the type of parity checking to use.
20 * @param stopBits The number of stop bits to use as defined by the enum StopBits.
21 */
22SerialPort::SerialPort(UINT32 baudRate, UINT8 dataBits, SerialPort::Parity parity, SerialPort::StopBits stopBits)
23 : m_resourceManagerHandle (0)
24 , m_portHandle (0)
25 , m_consoleModeEnabled (false)
26{
27 ViStatus localStatus = VI_SUCCESS;
28 localStatus = viOpenDefaultRM((ViSession*)&m_resourceManagerHandle);
29 wpi_setError(localStatus);
30
31 localStatus = viOpen(m_resourceManagerHandle, "ASRL1::INSTR", VI_NULL, VI_NULL, (ViSession*)&m_portHandle);
32 wpi_setError(localStatus);
33 if (localStatus != 0)
34 {
35 m_consoleModeEnabled = true;
36 return;
37 }
38
39 localStatus = viSetAttribute(m_portHandle, VI_ATTR_ASRL_BAUD, baudRate);
40 wpi_setError(localStatus);
41 localStatus = viSetAttribute(m_portHandle, VI_ATTR_ASRL_DATA_BITS, dataBits);
42 wpi_setError(localStatus);
43 localStatus = viSetAttribute(m_portHandle, VI_ATTR_ASRL_PARITY, parity);
44 wpi_setError(localStatus);
45 localStatus = viSetAttribute(m_portHandle, VI_ATTR_ASRL_STOP_BITS, stopBits);
46 wpi_setError(localStatus);
47
48 // Set the default timeout to 5 seconds.
49 SetTimeout(5.0f);
50
51 // Don't wait until the buffer is full to transmit.
52 SetWriteBufferMode(kFlushOnAccess);
53
54 EnableTermination();
55
56 //viInstallHandler(m_portHandle, VI_EVENT_IO_COMPLETION, ioCompleteHandler, this);
57 //viEnableEvent(m_portHandle, VI_EVENT_IO_COMPLETION, VI_HNDLR, VI_NULL);
58
59 nUsageReporting::report(nUsageReporting::kResourceType_SerialPort, 0);
60}
61
62/**
63 * Destructor.
64 */
65SerialPort::~SerialPort()
66{
67 if (!m_consoleModeEnabled)
68 {
69 //viUninstallHandler(m_portHandle, VI_EVENT_IO_COMPLETION, ioCompleteHandler, this);
70 viClose(m_portHandle);
71 }
72 viClose(m_resourceManagerHandle);
73}
74
75/**
76 * Set the type of flow control to enable on this port.
77 *
78 * By default, flow control is disabled.
79 */
80void SerialPort::SetFlowControl(SerialPort::FlowControl flowControl)
81{
82 if (!m_consoleModeEnabled)
83 {
84 ViStatus localStatus = viSetAttribute (m_portHandle, VI_ATTR_ASRL_FLOW_CNTRL, flowControl);
85 wpi_setError(localStatus);
86 }
87}
88
89/**
90 * Enable termination and specify the termination character.
91 *
92 * Termination is currently only implemented for receive.
93 * When the the terminator is recieved, the Read() or Scanf() will return
94 * fewer bytes than requested, stopping after the terminator.
95 *
96 * @param terminator The character to use for termination.
97 */
98void SerialPort::EnableTermination(char terminator)
99{
100 if (!m_consoleModeEnabled)
101 {
102 viSetAttribute(m_portHandle, VI_ATTR_TERMCHAR_EN, VI_TRUE);
103 viSetAttribute(m_portHandle, VI_ATTR_TERMCHAR, terminator);
104 viSetAttribute(m_portHandle, VI_ATTR_ASRL_END_IN, VI_ASRL_END_TERMCHAR);
105 }
106}
107
108/**
109 * Disable termination behavior.
110 */
111void SerialPort::DisableTermination()
112{
113 if (!m_consoleModeEnabled)
114 {
115 viSetAttribute(m_portHandle, VI_ATTR_TERMCHAR_EN, VI_FALSE);
116 viSetAttribute(m_portHandle, VI_ATTR_ASRL_END_IN, VI_ASRL_END_NONE);
117 }
118}
119
120/**
121 * Get the number of bytes currently available to read from the serial port.
122 *
123 * @return The number of bytes available to read.
124 */
125INT32 SerialPort::GetBytesReceived()
126{
127 INT32 bytes = 0;
128 if (!m_consoleModeEnabled)
129 {
130 ViStatus localStatus = viGetAttribute(m_portHandle, VI_ATTR_ASRL_AVAIL_NUM, &bytes);
131 wpi_setError(localStatus);
132 }
133 return bytes;
134}
135
136/**
137 * Output formatted text to the serial port.
138 *
139 * @bug All pointer-based parameters seem to return an error.
140 *
141 * @param writeFmt A string that defines the format of the output.
142 */
143void SerialPort::Printf(const char *writeFmt, ...)
144{
145 if (!m_consoleModeEnabled)
146 {
147 va_list args;
148 va_start (args, writeFmt);
149 ViStatus localStatus = viVPrintf(m_portHandle, (ViString)writeFmt, args);
150 va_end (args);
151 wpi_setError(localStatus);
152 }
153}
154
155/**
156 * Input formatted text from the serial port.
157 *
158 * @bug All pointer-based parameters seem to return an error.
159 *
160 * @param readFmt A string that defines the format of the input.
161 */
162void SerialPort::Scanf(const char *readFmt, ...)
163{
164 if (!m_consoleModeEnabled)
165 {
166 va_list args;
167 va_start (args, readFmt);
168 ViStatus localStatus = viVScanf(m_portHandle, (ViString)readFmt, args);
169 va_end (args);
170 wpi_setError(localStatus);
171 }
172}
173
174/**
175 * Read raw bytes out of the buffer.
176 *
177 * @param buffer Pointer to the buffer to store the bytes in.
178 * @param count The maximum number of bytes to read.
179 * @return The number of bytes actually read into the buffer.
180 */
181UINT32 SerialPort::Read(char *buffer, INT32 count)
182{
183 UINT32 retCount = 0;
184 if (!m_consoleModeEnabled)
185 {
186 ViStatus localStatus = viBufRead(m_portHandle, (ViPBuf)buffer, count, (ViPUInt32)&retCount);
187 switch (localStatus)
188 {
189 case VI_SUCCESS_TERM_CHAR:
190 case VI_SUCCESS_MAX_CNT:
191 case VI_ERROR_TMO: // Timeout
192 break;
193 default:
194 wpi_setError(localStatus);
195 }
196 }
197 return retCount;
198}
199
200/**
201 * Write raw bytes to the buffer.
202 *
203 * @param buffer Pointer to the buffer to read the bytes from.
204 * @param count The maximum number of bytes to write.
205 * @return The number of bytes actually written into the port.
206 */
207UINT32 SerialPort::Write(const char *buffer, INT32 count)
208{
209 UINT32 retCount = 0;
210 if (!m_consoleModeEnabled)
211 {
212 ViStatus localStatus = viBufWrite(m_portHandle, (ViPBuf)buffer, count, (ViPUInt32)&retCount);
213 wpi_setError(localStatus);
214 }
215 return retCount;
216}
217
218/**
219 * Configure the timeout of the serial port.
220 *
221 * This defines the timeout for transactions with the hardware.
222 * It will affect reads and very large writes.
223 *
224 * @param timeout The number of seconds to to wait for I/O.
225 */
226void SerialPort::SetTimeout(float timeout)
227{
228 if (!m_consoleModeEnabled)
229 {
230 ViStatus localStatus = viSetAttribute(m_portHandle, VI_ATTR_TMO_VALUE, (UINT32)(timeout * 1e3));
231 wpi_setError(localStatus);
232 }
233}
234
235/**
236 * Specify the size of the input buffer.
237 *
238 * Specify the amount of data that can be stored before data
239 * from the device is returned to Read or Scanf. If you want
240 * data that is recieved to be returned immediately, set this to 1.
241 *
242 * It the buffer is not filled before the read timeout expires, all
243 * data that has been received so far will be returned.
244 *
245 * @param size The read buffer size.
246 */
247void SerialPort::SetReadBufferSize(UINT32 size)
248{
249 if (!m_consoleModeEnabled)
250 {
251 ViStatus localStatus = viSetBuf(m_portHandle, VI_READ_BUF, size);
252 wpi_setError(localStatus);
253 }
254}
255
256/**
257 * Specify the size of the output buffer.
258 *
259 * Specify the amount of data that can be stored before being
260 * transmitted to the device.
261 *
262 * @param size The write buffer size.
263 */
264void SerialPort::SetWriteBufferSize(UINT32 size)
265{
266 if (!m_consoleModeEnabled)
267 {
268 ViStatus localStatus = viSetBuf(m_portHandle, VI_WRITE_BUF, size);
269 wpi_setError(localStatus);
270 }
271}
272
273/**
274 * Specify the flushing behavior of the output buffer.
275 *
276 * When set to kFlushOnAccess, data is synchronously written to the serial port
277 * after each call to either Printf() or Write().
278 *
279 * When set to kFlushWhenFull, data will only be written to the serial port when
280 * the buffer is full or when Flush() is called.
281 *
282 * @param mode The write buffer mode.
283 */
284void SerialPort::SetWriteBufferMode(SerialPort::WriteBufferMode mode)
285{
286 if (!m_consoleModeEnabled)
287 {
288 ViStatus localStatus = viSetAttribute(m_portHandle, VI_ATTR_WR_BUF_OPER_MODE, mode);
289 wpi_setError(localStatus);
290 }
291}
292
293/**
294 * Force the output buffer to be written to the port.
295 *
296 * This is used when SetWriteBufferMode() is set to kFlushWhenFull to force a
297 * flush before the buffer is full.
298 */
299void SerialPort::Flush()
300{
301 if (!m_consoleModeEnabled)
302 {
303 ViStatus localStatus = viFlush(m_portHandle, VI_WRITE_BUF);
304 wpi_setError(localStatus);
305 }
306}
307
308/**
309 * Reset the serial port driver to a known state.
310 *
311 * Empty the transmit and receive buffers in the device and formatted I/O.
312 */
313void SerialPort::Reset()
314{
315 if (!m_consoleModeEnabled)
316 {
317 ViStatus localStatus = viClear(m_portHandle);
318 wpi_setError(localStatus);
319 }
320}
321
322//void SerialPort::_internalHandler(UINT32 port, UINT32 eventType, UINT32 event)
323//{
324//}
325
326//ViStatus _VI_FUNCH ioCompleteHandler (ViSession vi, ViEventType eventType, ViEvent event, ViAddr userHandle)
327//{
328// ((SerialPort*) userHandle)->_internalHandler(vi, eventType, event);
329// return VI_SUCCESS;
330//}
331