VFD modular clock firmware

Dependencies:   DipCortex-EEprom RTC flw mbed

IV18Display.cpp

Committer:
Backstr?m
Date:
2015-02-24
Revision:
12:dfb422107412
Parent:
0:f6e68b4ce169

File content as of revision 12:dfb422107412:

/*
 * VFD Modular Clock - mbed
 * (C) 2011-14 Akafugu Corporation
 *
 * 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 2 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.
 *
 */

#include "IV18Display.h"
#include "prefs.h"

uint8_t calculate_segments_7(uint8_t character);

IV18Display::IV18Display(PinName data, PinName clock, PinName latch, PinName blank)
  : VFDDisplay(data, clock, latch, blank, 8)
{
    m_reverse_display = true;
    m_multiplex_limit = 8; // fixme: set to 8 to run . and - digit
    m_has_dots = true;
    
    printf(" Akafugu");
}

// Writes to the HV5812 driver for IV-18
// HV1~10:  Digit grids, 10 bits
// HV11~18: VFD segments, 8 bits
// HV19~20: NC
void IV18Display::writeDisplay(uint8_t digit, uint16_t segments)
{
  if (digit < 8 && m_dots & (1<<digit))
    segments |= (1<<7); // DP is at bit 7
  
  uint32_t val = (1 << digit) | ((uint32_t)segments << 10);

  writeHV5812(0); // unused upper byte: for HV518P compatibility
  writeHV5812(val >> 16);
  writeHV5812(val >> 8);
  writeHV5812(val);
  
  m_latch = 1;
  m_latch = 0;
}

uint16_t IV18Display::calculateSegments(char c, uint8_t digit)
{
    if (digit == 8) {
        uint16_t ret = 0;
        if (m_alarm_indicator)
            ret |= (1<<7);
        if (m_gps_indicator)
            ret |= (1<<6);
        return ret;
    }
    else {
        return calculate_segments_7(c);
    }
}

/*
void IV18Display::printTime(time_t t, uint8_t hundredths) {
    struct tm *tmp = localtime(&t);
    if (tmp == NULL) return;
    
    char buf[16];

    if (m_mode == Short) {
        strftime(buf, 16, " %H.%M.%S ", tmp);
    }
    else if (m_mode == Extra) {
        strftime(buf, 16, "%H.%M.%S", tmp);        
    }
    else {
        strftime(buf, 16, "%H-%M-%S", tmp);
    }
    
    if (m_mode == Extra)
        printf("%s.%d", buf, hundredths-1);
    else
        printf(buf);
}
*/

void IV18Display::printTime(struct tm* tm, uint8_t hundredths) {
    char buf[16];
    
    PrefsData* prefs = get_prefs();
    
    if (!prefs->prefs.disp_24h && tm->tm_hour >= 12) { // set dot for PM
        m_gps_indicator = true;
    }
    else {
        m_gps_indicator = false;
    }

    if (m_mode == Short && prefs->prefs.disp_24h) {
        strftime(buf, 16, " %H.%M.%S ", tm);
    }
    else if (m_mode == Short) {
        strftime(buf, 16, " %I.%M.%S ", tm);        
    }
    else if (m_mode == Extra && prefs->prefs.disp_24h) {
        strftime(buf, 16, "%H.%M.%S", tm);        
    }
    else if (m_mode == Extra) {
        strftime(buf, 16, "%I.%M.%S", tm);        
    }
    else if (prefs->prefs.disp_24h) {
        strftime(buf, 16, "%H-%M-%S", tm);    
    }
    else {
        strftime(buf, 16, "%I-%M-%S", tm);
    }
    
    if (m_mode == Extra)
        printf("%s.%d", buf, hundredths-1);
    else
        printf(buf);    
}

void IV18Display::printTimeLong(struct tm* tm, uint8_t hundredths) {
    char buf[48];

    if (m_mode == Short || m_mode == Extra) {
        strftime(buf, 48, " %H%M%S %A %B %d %Y", tm);
    }
    else {
        strftime(buf, 48, "%H-%M-%S %A %B %d %Y", tm);
    }
    
    printf(buf);    
}

void IV18Display::printTimeSet(struct tm* tm, bool showSeconds) {
        char buf[16];
        if (showSeconds) {
                strftime(buf, 16, "%H-%M-%S", tm);
        }
        else {
                strftime(buf, 16, "AL %H-%M", tm);
        }
        printf(buf); 
}

void IV18Display::printDate(struct tm* tm) {
    char buf[16];
    strftime(buf, 16, "%F", tm);
    printf(buf);
}

void IV18Display::handleBlink(char d) {
        // fixme: blink should be handled in virtual function in IV18Display
    if (m_display_on)
        writeDisplay(m_multiplex_counter, calculateSegments(d, m_multiplex_counter));
    else {
            if (m_blink_mode == Seconds && m_multiplex_counter <= 1) {
        writeDisplay(m_multiplex_counter, 0);               
            }
            else if (m_blink_mode == Minutes && m_multiplex_counter >= 3 && m_multiplex_counter <= 4) {
        writeDisplay(m_multiplex_counter, 0);               
            }
            else if (m_blink_mode == Hours && m_multiplex_counter >= 6 && m_multiplex_counter <= 7) {
        writeDisplay(m_multiplex_counter, 0);               
            }
            else if (m_blink_mode == Full) {
        writeDisplay(m_multiplex_counter, 0);               
            }
            else {
        writeDisplay(m_multiplex_counter, calculateSegments(d, m_multiplex_counter));
            }
        }
}