001    /*----------------------------------------------------------------------------*/
002    /* Copyright (c) FIRST 2008-2012. All Rights Reserved.                        */
003    /* Open Source Software - may be modified and shared by FRC teams. The code   */
004    /* must be accompanied by the FIRST BSD license file in the root directory of */
005    /* the project.                                                               */
006    /*----------------------------------------------------------------------------*/
007    
008    package edu.wpi.first.wpilibj;
009    
010    import edu.wpi.first.wpilibj.communication.FRCControl;
011    import edu.wpi.first.wpilibj.communication.UsageReporting;
012    import edu.wpi.first.wpilibj.parsing.IInputOutput;
013    
014    /**
015     * Provide access to "LCD" on the Driver Station.
016     * This is the Messages box on the DS Operation tab. 
017     *
018     * Buffer the printed data locally and then send it
019     * when UpdateLCD is called.
020     */
021    public class DriverStationLCD extends SensorBase implements IInputOutput{
022    
023        private static DriverStationLCD m_instance;
024        /**
025         * Driver station timeout in milliseconds
026         */
027        public static final int kSyncTimeout_ms = 20;
028        /**
029         * Command to display text
030         */
031        public static final int kFullDisplayTextCommand = 0x9FFF;
032        /**
033         * Maximum line length for Driver Station display
034         */
035        public static final int kLineLength = 21;
036        /**
037         * Total number of lines available
038         */
039        public static final int kNumLines = 6;
040        
041        /**
042         * The line number on the Driver Station LCD
043         */
044        public static class Line {
045    
046            /**
047             * The integer value representing this enumeration
048             */
049            public final int value;
050            static final int kMain6_val = 0;
051            static final int kUser1_val = 0;
052            static final int kUser2_val = 1;
053            static final int kUser3_val = 2;
054            static final int kUser4_val = 3;
055            static final int kUser5_val = 4;
056            static final int kUser6_val = 5;
057            /**
058             * @deprecated Use kUser1
059             * Line at the Top of the screen
060             */
061            public static final Line kMain6 = new Line(kMain6_val);
062            /**
063             * Line at the Top of the screen
064             */
065            public static final Line kUser1 = new Line(kUser1_val);
066            /**
067             * Line on the user screen
068             */
069            public static final Line kUser2 = new Line(kUser2_val);
070            /**
071             * Line on the user screen
072             */
073            public static final Line kUser3 = new Line(kUser3_val);
074            /**
075             * Line on the user screen
076             */
077            public static final Line kUser4 = new Line(kUser4_val);
078            /**
079             * Line on the user screen
080             */
081            public static final Line kUser5 = new Line(kUser5_val);
082            /**
083             * Bottom line on the user screen
084             */
085            public static final Line kUser6 = new Line(kUser6_val);
086    
087            private Line(int value) {
088                this.value = value;
089            }
090        }
091    
092        byte[] m_textBuffer;
093    
094        /**
095         * Get an instance of the DriverStationLCD
096         * @return an instance of the DriverStationLCD
097         */
098        public static synchronized DriverStationLCD getInstance() {
099            if (m_instance == null)
100                m_instance = new DriverStationLCD();
101            return m_instance;
102        }
103    
104        /**
105         * DriverStationLCD constructor.
106         *
107         * This is only called once the first time GetInstance() is called
108         */
109        private DriverStationLCD() {
110            m_textBuffer = new byte[FRCControl.USER_DS_LCD_DATA_SIZE];
111    
112            for (int i = 0; i < FRCControl.USER_DS_LCD_DATA_SIZE; i++) {
113                m_textBuffer[i] = ' ';
114            }
115    
116            m_textBuffer[0] = (byte) (kFullDisplayTextCommand >> 8);
117            m_textBuffer[1] = (byte) kFullDisplayTextCommand;
118    
119            UsageReporting.report(UsageReporting.kResourceType_DriverStationLCD, 0);
120        }
121    
122        /**
123         * Send the text data to the Driver Station.
124         */
125        public synchronized void updateLCD() {
126            FRCControl.setUserDsLcdData(m_textBuffer, FRCControl.USER_DS_LCD_DATA_SIZE, kSyncTimeout_ms);
127        }
128    
129        /**
130         * Print formatted text to the Driver Station LCD text buffer.
131         *
132         * Use UpdateLCD() periodically to actually send the test to the Driver Station.
133         *
134         * @param line The line on the LCD to print to.
135         * @param startingColumn The column to start printing to.  This is a 1-based number.
136         * @param text the text to print
137         */
138        public void println(Line line, int startingColumn, String text) {
139            int start = startingColumn - 1;
140            int maxLength = kLineLength - start;
141    
142            if (startingColumn < 1 || startingColumn > kLineLength) {
143                throw new IndexOutOfBoundsException("Column must be between 1 and " + kLineLength + ", inclusive");
144            }
145    
146            int length = text.length();
147            int finalLength = (length < maxLength ? length : maxLength);
148            synchronized (this) {
149                for (int i = 0; i < finalLength; i++) {
150                    m_textBuffer[i + start + line.value * kLineLength + 2] = (byte)text.charAt(i);
151                }
152            }
153        }
154    
155        /**
156         * Print formatted text to the Driver Station LCD text buffer.
157         *
158         * Use UpdateLCD() periodically to actually send the test to the Driver Station.
159         *
160         * @param line The line on the LCD to print to.
161         * @param startingColumn The column to start printing to.  This is a 1-based number.
162         * @param text the text to print
163         */
164        public void println(Line line, int startingColumn, StringBuffer text) {
165            int start = startingColumn - 1;
166            int maxLength = kLineLength - start;
167    
168            if (startingColumn < 1 || startingColumn > kLineLength) {
169                throw new IndexOutOfBoundsException("Column must be between 1 and " + kLineLength + ", inclusive");
170            }
171    
172            int length = text.length();
173            int finalLength = (length < maxLength ? length : maxLength);
174            synchronized (this) {
175                for (int i = 0; i < finalLength; i++) {
176                    m_textBuffer[i + start + line.value * kLineLength + 2] = (byte) text.charAt(i);
177                }
178            }
179        }
180        
181        /**
182         * Clear User Messages box on DS Operations Tab
183         * 
184         * This method will clear all text currently displayed in the message box
185         */
186        public void clear() {
187            synchronized (this) {
188                for (int i=0; i < kLineLength*kNumLines; i++) {
189                    m_textBuffer[i+2] = ' ';
190                }
191            }
192            updateLCD();
193        }
194    }