/* * Remote Laboratory Seven Segment Display Widget * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * (c) 2012 - 2015 Timothy Pearson * Raptor Engineering * http://www.raptorengineeringinc.com */ #include #include #include "sevensegment.h" Display7Segment::Display7Segment( TQWidget *parent, const char *name ) : TQFrame( parent, name ) { init(); } Display7Segment::~Display7Segment() { free(m_prevSegments); free(m_currentSegments); } void Display7Segment::init() { setFrameStyle(TQFrame::Box | TQFrame::Raised); prevSegments = 0; val = 0; smallPoint = TRUE; setSegmentStyle(Flat); m_prevSegments = (char*)malloc(sizeof(char)*9); m_currentSegments = (char*)malloc(sizeof(char)*9); m_prevSegments[0] = 99; m_currentSegments[0] = 99; setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum)); } void Display7Segment::setLitSegments(unsigned char segs) { // This produces an array of up to 10 chars, with each char being the number of a lit segment, and the list being terminated with the number 99 // The bit input in segs is active high // The bit sequence, MSB to LSB, is dp a b c d e f g // Segment letters are taken from ug130.pdf if (prevSegments != segs) { int i = 0; if (segs & 0x80) { m_currentSegments[i] = 7; i++; } if (segs & 0x40) { m_currentSegments[i] = 0; i++; } if (segs & 0x20) { m_currentSegments[i] = 2; i++; } if (segs & 0x10) { m_currentSegments[i] = 5; i++; } if (segs & 0x08) { m_currentSegments[i] = 6; i++; } if (segs & 0x04) { m_currentSegments[i] = 4; i++; } if (segs & 0x02) { m_currentSegments[i] = 1; i++; } if (segs & 0x01) { m_currentSegments[i] = 3; i++; } m_currentSegments[i] = 99; update(); } prevSegments = segs; } unsigned char Display7Segment::segmentsForNumericDigit(unsigned char val, bool dp) { unsigned char ret = 0; if (val == 0x0) { ret = 0x7e; } else if (val == 0x1) { ret = 0x30; } else if (val == 0x2) { ret = 0x6d; } else if (val == 0x3) { ret = 0x79; } else if (val == 0x4) { ret = 0x33; } else if (val == 0x5) { ret = 0x5b; } else if (val == 0x6) { ret = 0x5f; } else if (val == 0x7) { ret = 0x70; } else if (val == 0x8) { ret = 0x7f; } else if (val == 0x9) { ret = 0x73; } else if (val == 0xa) { ret = 0x7d; } else if (val == 0xb) { ret = 0x1f; } else if (val == 0xc) { ret = 0x0d; } else if (val == 0xd) { ret = 0x3d; } else if (val == 0xe) { ret = 0x4f; } else if (val == 0xf) { ret = 0x67; } else if (val == 0x10) { ret = 0x01; } // "-" if (dp) { ret |= 0x80; } return ret; } void Display7Segment::drawContents( TQPainter *p ) { // Draw all segments TQPoint pos; int digitSpace = smallPoint ? 2 : 1; int xSegLen = width()*5/(1*(5 + digitSpace) + digitSpace); int ySegLen = height()*5/12; int segLen = ySegLen > xSegLen ? xSegLen : ySegLen; int xAdvance = segLen*( 5 + 1 )/5; int xOffset = ( width() - xAdvance + segLen/5 )/2; int yOffset = ( height() - segLen*2 )/2; pos = TQPoint(xOffset, yOffset); drawDigit(pos, *p, segLen, m_currentSegments); } TQSize Display7Segment::sizeHint() const { return TQSize(10 + 9 * (1 + (smallPoint ? 0 : 1)), 23); } void Display7Segment::setSegmentStyle( SegmentStyle s ) { fill = (s == Flat || s == Filled); shadow = (s == Outline || s == Filled); update(); } Display7Segment::SegmentStyle Display7Segment::segmentStyle() const { Q_ASSERT(fill || shadow); if (!fill && shadow) { return Outline; } if (fill && shadow) { return Filled; } return Flat; } static void addPoint( TQPointArray &a, const TQPoint &p ) { uint n = a.size(); a.resize(n + 1); a.setPoint(n, p); } void Display7Segment::drawDigit(const TQPoint &pos, TQPainter &p, int segLen, const char *newSegs) { char updates[20][2]; // Can hold 2 times number of segments, only // first 10 used if segment table is correct int nErases; int nUpdates; const char *segs; int i,j; const char erase = 0; const char draw = 1; // const char leaveAlone = 2; segs = m_prevSegments; for ( nErases=0; segs[nErases] != 99; nErases++ ) { updates[nErases][0] = erase; // Get segments to erase to updates[nErases][1] = segs[nErases]; // remove old char } nUpdates = nErases; segs = newSegs; for(i = 0 ; segs[i] != 99 ; i++) { for ( j=0; jaddItem(spacerItem); m_layout->setAutoAdd(true); // Allocate display array m_displayArray = (Display7Segment**)malloc(sizeof(Display7Segment*) * m_numberOfDigits); // Create displays for (i=0; i < m_numberOfDigits; i++) { m_displayArray[i] = new Display7Segment(this); } setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum)); // Set up displays for (i=0; i < m_numberOfDigits; i++) { m_displayArray[i]->setBackgroundColor(TQt::black); m_displayArray[i]->setPaletteForegroundColor(TQColor(0, 255, 64)); } // The LED display can work one of two ways #if 0 // Separated segments for (i=0; i < m_numberOfDigits; i++) { m_displayArray[i]->setFrameStyle(TQFrame::Box | TQFrame::Raised); } setFrameStyle(TQFrame::NoFrame); #else // Combined segments for (i=0; i < m_numberOfDigits; i++) { m_displayArray[i]->setFrameStyle(TQFrame::NoFrame); } setBackgroundColor(TQt::black); setFrameStyle(TQFrame::Box); #endif } void Display7SegmentArray::setNumberOfDigits(unsigned int count) { unsigned int i; if (m_numberOfDigits != count) { // Delete displays if (m_displayArray) { for (i=0; i < m_numberOfDigits; i++) { delete m_displayArray[i]; } delete m_displayArray; m_displayArray = NULL; } // Destroy layout if (m_layout) { delete m_layout; } // Set display count m_numberOfDigits = count; // Reinitialize init(); } } void Display7SegmentArray::setSegmentStyle(SegmentStyle s) { unsigned int i; m_segmentStyle = s; for (i=0; i < m_numberOfDigits; i++) { m_displayArray[i]->setSegmentStyle((Display7Segment::SegmentStyle)m_segmentStyle); } } Display7SegmentArray::SegmentStyle Display7SegmentArray::segmentStyle() const { return m_segmentStyle; } void Display7SegmentArray::setValue(double value, int maxDecimalLength, bool forceMinDecimalLength) { bool dp; unsigned int i; TQString displayString = TQString("%1").arg(value); if (displayString.contains("e")) { maxDecimalLength = -1; } if (maxDecimalLength >= 0) { int decPos = displayString.find("."); if (decPos >= 0) { int decLen = (displayString.length() - 1) - decPos; if (decLen > maxDecimalLength) { displayString.truncate(displayString.length() - (decLen - maxDecimalLength)); } } if (forceMinDecimalLength) { if (decPos < 0) { displayString.append("."); decPos = displayString.length() - 1; } for (int i = displayString.length(); i < decPos + maxDecimalLength + 1; i++) { displayString.append("0"); } } } int last_char = displayString.length(); int current_char = (last_char - (int)m_numberOfDigits); if (displayString.contains(".")) { current_char--; } if (displayString.length() > m_numberOfDigits) { // String is too large to display on the specified number of 7-segment digits for (i=0; i < m_numberOfDigits; i++) { m_displayArray[i]->setLitSegments(Display7Segment::segmentsForNumericDigit(0x10, false)); } } else { for (i=0; i < m_numberOfDigits; i++) { if (current_char < 0) { m_displayArray[i]->setLitSegments(0x0); } else { dp = false; if (current_char < (displayString.length() - 1)) { if (displayString[current_char + 1] == '.') { dp = true; } } if (displayString[current_char] == '.') { current_char++; } if (displayString[current_char] == '-') { m_displayArray[i]->setLitSegments(Display7Segment::segmentsForNumericDigit(0x10, dp)); } else if (displayString[current_char] == 'e') { m_displayArray[i]->setLitSegments(Display7Segment::segmentsForNumericDigit(0xe, dp)); } else { m_displayArray[i]->setLitSegments(Display7Segment::segmentsForNumericDigit(TQString(displayString[current_char]).toInt(NULL, 10), dp)); } } current_char++; } } } #include "sevensegment.moc"