blob: df84ef8338fa02308e2eebaff868aaadf6ca07b3 [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 "DriverStationLCD.h"
8#include "NetworkCommunication/FRCComm.h"
9#include "NetworkCommunication/UsageReporting.h"
10#include "Synchronized.h"
11#include "WPIErrors.h"
12#include <strLib.h>
13
14const UINT32 DriverStationLCD::kSyncTimeout_ms;
15const UINT16 DriverStationLCD::kFullDisplayTextCommand;
16const INT32 DriverStationLCD::kLineLength;
17const INT32 DriverStationLCD::kNumLines;
18DriverStationLCD* DriverStationLCD::m_instance = NULL;
19
20/**
21 * DriverStationLCD contructor.
22 *
23 * This is only called once the first time GetInstance() is called
24 */
25DriverStationLCD::DriverStationLCD()
26 : m_textBuffer (NULL)
27 , m_textBufferSemaphore (NULL)
28{
29 m_textBuffer = new char[USER_DS_LCD_DATA_SIZE];
30 memset(m_textBuffer, ' ', USER_DS_LCD_DATA_SIZE);
31
32 *((UINT16 *)m_textBuffer) = kFullDisplayTextCommand;
33
34 m_textBufferSemaphore = semMCreate(SEM_DELETE_SAFE);
35
36 nUsageReporting::report(nUsageReporting::kResourceType_DriverStationLCD, 0);
37
38 AddToSingletonList();
39}
40
41DriverStationLCD::~DriverStationLCD()
42{
43 semDelete(m_textBufferSemaphore);
44 delete [] m_textBuffer;
45 m_instance = NULL;
46}
47
48/**
49 * Return a pointer to the singleton DriverStationLCD.
50 */
51DriverStationLCD* DriverStationLCD::GetInstance()
52{
53 if (m_instance == NULL)
54 {
55 m_instance = new DriverStationLCD();
56 }
57 return m_instance;
58}
59
60/**
61 * Send the text data to the Driver Station.
62 */
63void DriverStationLCD::UpdateLCD()
64{
65 Synchronized sync(m_textBufferSemaphore);
66 setUserDsLcdData(m_textBuffer, USER_DS_LCD_DATA_SIZE, kSyncTimeout_ms);
67}
68
69/**
70 * Print formatted text to the Driver Station LCD text bufer.
71 *
72 * Use UpdateLCD() periodically to actually send the text to the Driver Station.
73 *
74 * @param line The line on the LCD to print to.
75 * @param startingColumn The column to start printing to. This is a 1-based number.
76 * @param writeFmt The printf format string describing how to print.
77 */
78void DriverStationLCD::Printf(Line line, INT32 startingColumn, const char *writeFmt, ...)
79{
80 va_list args;
81 va_start (args, writeFmt);
82 VPrintf(line, startingColumn, writeFmt, args);
83 va_end (args);
84}
85
86void DriverStationLCD::VPrintf(Line line, INT32 startingColumn, const char *writeFmt, va_list args)
87{
88 UINT32 start = startingColumn - 1;
89 INT32 maxLength = kLineLength - start;
90 char lineBuffer[kLineLength + 1];
91
92 if (startingColumn < 1 || startingColumn > kLineLength)
93 {
94 wpi_setWPIErrorWithContext(ParameterOutOfRange, "startingColumn");
95 return;
96 }
97
98 if (line < kMain_Line6 || line > kUser_Line6)
99 {
100 wpi_setWPIErrorWithContext(ParameterOutOfRange, "line");
101 return;
102 }
103
104 {
105 Synchronized sync(m_textBufferSemaphore);
106 // snprintf appends NULL to its output. Therefore we can't write directly to the buffer.
107 INT32 length = vsnprintf(lineBuffer, kLineLength + 1, writeFmt, args);
108 if (length < 0) length = kLineLength;
109
110 memcpy(m_textBuffer + start + line * kLineLength + sizeof(UINT16), lineBuffer, std::min(maxLength,length));
111 }
112}
113
114/**
115 * Print formatted text to the Driver Station LCD text bufer. This function
116 * pads the line with empty spaces.
117 *
118 * Use UpdateLCD() periodically to actually send the text to the Driver Station.
119 *
120 * @param line The line on the LCD to print to.
121 * @param writeFmt The printf format string describing how to print.
122 */
123void DriverStationLCD::PrintfLine(Line line, const char *writeFmt, ...)
124{
125 va_list args;
126 va_start (args, writeFmt);
127 VPrintfLine(line, writeFmt, args);
128 va_end (args);
129}
130
131void DriverStationLCD::VPrintfLine(Line line, const char *writeFmt, va_list args)
132{
133 char lineBuffer[kLineLength + 1];
134
135 if (line < kMain_Line6 || line > kUser_Line6)
136 {
137 wpi_setWPIErrorWithContext(ParameterOutOfRange, "line");
138 return;
139 }
140
141 {
142 Synchronized sync(m_textBufferSemaphore);
143 // snprintf appends NULL to its output. Therefore we can't write directly to the buffer.
144 INT32 length = std::min(vsnprintf(lineBuffer, kLineLength + 1, writeFmt, args), kLineLength);
145 if (length < 0) length = kLineLength;
146
147 // Fill the rest of the buffer
148 if (length < kLineLength)
149 {
150 memset(lineBuffer + length, ' ', kLineLength - length);
151 }
152
153 memcpy(m_textBuffer + line * kLineLength + sizeof(UINT16), lineBuffer, kLineLength);
154 }
155}
156
157/**
158 * Clear all lines on the LCD.
159 */
160void DriverStationLCD::Clear()
161{
162 Synchronized sync(m_textBufferSemaphore);
163 memset(m_textBuffer + sizeof(UINT16), ' ', kLineLength*kNumLines);
164}
165