Provides a multiplexed dual seven segment display driver used by RenBED

Dependents:   RenBuggy RenBEDCounter RenBEDHelloWorld AmpBoardTest ... more

SevenSegmentDisplay.cpp

Committer:
jf1452
Date:
2014-02-05
Revision:
5:cb7339a2e196
Parent:
3:7c62606a68b8

File content as of revision 5:cb7339a2e196:

/*******************************************************************************
* RenBED two seven segment display driver                                      *
* Copyright (c) 2013 Jon Fuge                                                  *
*                                                                              *
* Permission is hereby granted, free of charge, to any person obtaining a copy *
* of this software and associated documentation files (the "Software"), to deal*
* in the Software without restriction, including without limitation the rights *
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell    *
* copies of the Software, and to permit persons to whom the Software is        *
* furnished to do so, subject to the following conditions:                     *
*                                                                              *
* The above copyright notice and this permission notice shall be included in   *
* all copies or substantial portions of the Software.                          *
*                                                                              *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR   *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,     *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER       *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,*
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN    *
* THE SOFTWARE.                                                                *
*                                                                              *
* SevenSegmentDisplay.cpp                                                      *
*                                                                              *
* V1.0 23/12/2013 First issue of code                      Jon Fuge            *
* V1.1 15/01/2014 Added code to display integers           Jon Fuge            *
*******************************************************************************/

#ifndef _SEVENSEGMENTDISPLAY_C
#define _SEVENSEGMENTDISPLAY_C

#include "mbed.h"
#include "SevenSegmentDisplay.h"

/*******************************************************************************
* SevenSegmentDisplay - Declares the class for the sevent segment display      *
* driver                                                                       *
*------------------------------------------------------------------------------*
* Parameters: uint8_t ui8Fade - Sets the fade mode required                    *
* Returns:    none                                                             *
*******************************************************************************/
SevenSegmentDisplay::SevenSegmentDisplay(uint8_t ui8Fade):
    mux(P1_25),seg_a(P1_23),seg_b(P1_28),seg_c(P0_16),seg_d(P1_31),seg_e(P1_13),seg_f(P1_16),seg_g(P1_19),seg_p(P0_23)
{

    timer.attach_us(this, &SevenSegmentDisplay::SevenSegmentDisplayMux, 1000);       // led smooth control 10ms timer inttruupt

    D_ui8Mode          = ui8Fade;
    D_FadeRatems       = 10;
    D_ui16FlashRatems  = 1000;
    D_ui8Mux           = RIGHT_DIGIT;
}

/*******************************************************************************
* FadeMode - Sets the fade mode for the display drive                          *
*------------------------------------------------------------------------------*
* Parameters: uint8_t ui8Fade - Sets the fade mode required                    *
* Returns:    none                                                             *
*******************************************************************************/
void SevenSegmentDisplay::FadeMode(uint8_t ui8Fade)
{
    D_ui8Mode = ui8Fade;
}

/*******************************************************************************
* SevenSegmentDisplayMux - Alternately drives both digits using the multiplexor*
*------------------------------------------------------------------------------*
* Parameters: none                                                             *
* Returns:    none                                                             *
*******************************************************************************/
void SevenSegmentDisplay::SevenSegmentDisplayMux(void)
{
    static uint16_t ui16IntMux = 0;

    if (D_ui8Mux == RIGHT_DIGIT) {
        D_ui8Mux = LEFT_DIGIT;
        SegmentDrive(D_ui8LeftDigit, LEFT_DIGIT);
    } else {
        D_ui8Mux = RIGHT_DIGIT;
        SegmentDrive(D_ui8RightDigit, RIGHT_DIGIT);
    }
    if (iSequence != -1) {
        if (ui16IntMux++ > 1000) {
            ui16IntMux = 0;
            SevenSegmentIntMux();
        }
    }
}

/*******************************************************************************
* SevenSegmentIntMux - Sequences through 3 pairs of digits to display an       *
* integer on the seven segment display.                                        *
*------------------------------------------------------------------------------*
* Parameters: none                                                             *
* Returns:    none                                                             *
*******************************************************************************/
void SevenSegmentDisplay::SevenSegmentIntMux(void)
{
    uint8_t Digits[6];
    uint8_t Counter;
    int     TempValue;
    int     StartDigit = 0;

    TempValue = iDisplayValue;
    for (Counter = 5; Counter > 0; Counter--) {
        Digits[Counter] = TempValue % 10;
        TempValue   = (int)(TempValue / 10);
    }
    Digits[0] = 0;
    Digits[5] += 0x80;

    for (Counter = 0; Counter < 6; Counter++) {
        if (Digits[Counter] == 0)
            Digits[Counter] = 36;
        else
        {
            StartDigit = Counter & 0xFE;
            break;
        }
    }

    D_ui8LeftDigit  = Digits[iSequence++];
    D_ui8RightDigit = Digits[iSequence++];
    if (iSequence == 6)
        iSequence = StartDigit;
}

/*******************************************************************************
* SegmentDrive                                                                 *
* SegmentDrive - converts ui8Value into a segment drive pattern to load into   *
* the display buffer, this is incremented or decremented according to the      *
* pattern value to give a fade transition effect when digits change            *
*------------------------------------------------------------------------------*
* Parameters: uint8_t ui8Value - Specifies the value to be displayed           *
*             uint8_t ui8Mux   - Specifies which LED to be driven              *
* Returns:    none                                                             *
*******************************************************************************/
void SevenSegmentDisplay::SegmentDrive(uint8_t ui8Value, uint8_t ui8Mux)
{
    const uint8_t SEGMENTS[37] = {
        //*********************************************************
        // 7segment pattern,
        //*********************************************************
        //      seg: g f e  d c b a
        //      bit: 6 5 4  3 2 1 0
        //      --------------------
        0xC0,        // 0         1 0 0  0 0 0 0
        0xF9,        // 1         1 1 1  1 0 0 1
        0xA4,        // 2         0 1 0  0 1 0 0
        0xB0,        // 3         0 1 1  0 0 0 0
        0x99,        // 4         0 0 1  1 0 0 1
        0x92,        // 5         0 0 1  0 0 1 0
        0x82,        // 6         0 0 0  0 0 1 0
        0x58,        // 7         1 0 1  1 0 0 0
        0x80,        // 8         0 0 0  0 0 0 0
        0x90,        // 9         0 0 1  0 0 0 0
        0x88,        // A         0 0 0  1 0 0 0
        0x83,        // B         0 0 0  0 0 1 1
        0xC6,        // C         1 0 0  0 1 1 0
        0xA1,        // D         0 1 0  0 0 0 1
        0x86,        // E         0 0 0  0 1 1 0
        0x8E,        // F         0 0 0  1 1 1 0
        0xC2,        // G         1 0 0  0 0 1 0
        0x8B,        // H         0 0 0  1 0 1 1
        0xCF,        // I         1 0 0  1 1 1 1
        0xE1,        // J         1 1 0  0 0 0 1
        0x8A,        // K         0 0 0  1 0 1 0
        0xC7,        // L         1 0 0  0 1 1 1
        0xEA,        // M         1 1 0  1 0 1 0
        0xAB,        // N         0 1 0  1 0 1 1
        0xA3,        // O         0 1 0  0 0 1 1
        0x8C,        // P         0 0 0  1 1 0 0
        0x98,        // Q         0 0 1  1 0 0 0
        0xCC,        // R         1 0 0  1 1 0 0
        0x96,        // S         0 0 1  0 1 1 0
        0x87,        // T         0 0 0  0 1 1 1
        0xE3,        // U         1 1 0  0 0 1 1
        0xC1,        // V         1 0 0  0 0 0 1
        0xD5,        // W         1 0 1  0 1 0 1
        0x89,        // X         0 0 0  1 0 0 1
        0x91,        // Y         0 0 1  0 0 0 1
        0xB4,        // Z         0 1 1  0 1 0 0
        0xFF         //           1 1 1  1 1 1 1
    };

    uint8_t bSegment;
    uint8_t ui8Segment;
    static uint8_t D_ui8Pwm = D_FadeRatems -1;             // PWM counter for fader
    static uint16_t D_ui16FlashCount = 0;        // Counter for flash rate
    uint8_t ui8FlashCycle;
    uint8_t ui8SegmentState;

    D_ui16FlashCount++;
    if ((D_ui16FlashCount >= (D_ui16FlashRatems/2)) && (D_ui8Mode & FLASH))
        ui8FlashCycle = 1;
    else
        ui8FlashCycle = 0;

    if (D_ui16FlashCount >= D_ui16FlashRatems)
        D_ui16FlashCount = 0;

    mux = ui8Mux;
    for (ui8Segment = 0; ui8Segment < 8; ui8Segment++) {
        if (D_ui8SegmentDrives[ui8Mux][ui8Segment] > D_ui8Pwm)
            ui8SegmentState = ui8FlashCycle;
        else
            ui8SegmentState = 1;
        switch (ui8Segment) {
            case 0:
                seg_a = ui8SegmentState;
            case 1:
                seg_b = ui8SegmentState;
            case 2:
                seg_c = ui8SegmentState;
            case 3:
                seg_d = ui8SegmentState;
            case 4:
                seg_e = ui8SegmentState;
            case 5:
                seg_f = ui8SegmentState;
            case 6:
                seg_g = ui8SegmentState;
            case 7:
                seg_p = ui8SegmentState;
        }
    }

    D_ui8Pwm--;
    if (D_ui8Pwm == 0) {
        D_ui8Pwm = D_FadeRatems - 1;

        bSegment = SEGMENTS[(ui8Value & 0x7f)];
        if (D_ui8Mode & FADE) {
            for (ui8Segment = 0; ui8Segment < 7; ui8Segment++)
                if((bSegment & (0x01 << ui8Segment)) == 0) {
                    if (D_ui8SegmentDrives[ui8Mux][ui8Segment] < D_FadeRatems) D_ui8SegmentDrives[ui8Mux][ui8Segment]++;
                } else {
                    if (D_ui8SegmentDrives[ui8Mux][ui8Segment] > 0) D_ui8SegmentDrives[ui8Mux][ui8Segment]--;
                }
            if (ui8Value & 0x80) {
                if (D_ui8SegmentDrives[ui8Mux][7] < D_FadeRatems) D_ui8SegmentDrives[ui8Mux][7]++;
            } else {
                if (D_ui8SegmentDrives[ui8Mux][7] > 0) D_ui8SegmentDrives[ui8Mux][7]--;
            }
        } else {
            for (ui8Segment = 0; ui8Segment < 7; ui8Segment++)
                if((bSegment & (0x01 << ui8Segment)) == 0)
                    D_ui8SegmentDrives[ui8Mux][ui8Segment] = D_FadeRatems;
                else
                    D_ui8SegmentDrives[ui8Mux][ui8Segment] = 0;
            if (ui8Value & 0x80)
                D_ui8SegmentDrives[ui8Mux][7] = D_FadeRatems;
            else
                D_ui8SegmentDrives[ui8Mux][7] = 0;
        }
    }
}

/*******************************************************************************
* DisplayDigits - Loads the register to display two digits on the display      *
*------------------------------------------------------------------------------*
* Parameters: uint8_t ui8LeftDigit  - Specifies the left digit                 *
*             uint8_t ui8RightDigit - Specifies the right digit                *
* Returns:    none                                                             *
*******************************************************************************/
void SevenSegmentDisplay::DisplayDigits(uint8_t ui8LeftDigit, uint8_t ui8RightDigit)
{
    D_ui8LeftDigit = ui8LeftDigit;
    D_ui8RightDigit = ui8RightDigit;
    inttimer.detach();
    iSequence = -1;
}

/*******************************************************************************
* DisplayInt - Loads the register to display an integer on the display         *
*------------------------------------------------------------------------------*
* Parameters: int iValue - Specifies the integer value to be displayed         *
* Returns:    none                                                             *
*******************************************************************************/
void SevenSegmentDisplay::DisplayInt(int iValue)
{
    iDisplayValue = iValue;
    if (iValue > 9999)
        iSequence = 0;
    else if (iValue > 99)
        iSequence = 2;
    else
        iSequence = 4;
}

/*******************************************************************************
* FlashRate - Sets the flash rate for the display                              *
*------------------------------------------------------------------------------*
* Parameters: uint8_t ui16FlashRateMs - Sets the flash rate in ms              *
* Returns:    none                                                             *
*******************************************************************************/
void SevenSegmentDisplay::FlashRate(uint16_t ui16FlashRateMs)
{
    D_ui16FlashRatems = ui16FlashRateMs;
}

/*******************************************************************************
* FadeRate -  Sets the fade rate for segment transistions                      *
*------------------------------------------------------------------------------*
* Parameters: uint8_t ui8FadeRateMs - Sets the fade rate in ms                 *
* Returns:    none                                                             *
*******************************************************************************/
void SevenSegmentDisplay::FadeRate(uint8_t ui8FadeRateMs)
{
    D_FadeRatems = ui8FadeRateMs;
}


#endif