VFD modular clock firmware

Dependencies:   DipCortex-EEprom RTC flw mbed

Committer:
Backstr?m
Date:
Tue Feb 24 23:01:40 2015 +0900
Revision:
12:dfb422107412
Parent:
0:f6e68b4ce169
Added tag v1.0.2 for changeset 34b344fdec98

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Backstrom 0:f6e68b4ce169 1 /*
Backstrom 0:f6e68b4ce169 2 * VFD Modular Clock - mbed
Backstrom 0:f6e68b4ce169 3 * (C) 2011-14 Akafugu Corporation
Backstrom 0:f6e68b4ce169 4 *
Backstrom 0:f6e68b4ce169 5 * This program is free software; you can redistribute it and/or modify it under the
Backstrom 0:f6e68b4ce169 6 * terms of the GNU General Public License as published by the Free Software
Backstrom 0:f6e68b4ce169 7 * Foundation; either version 2 of the License, or (at your option) any later
Backstrom 0:f6e68b4ce169 8 * version.
Backstrom 0:f6e68b4ce169 9 *
Backstrom 0:f6e68b4ce169 10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
Backstrom 0:f6e68b4ce169 11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
Backstrom 0:f6e68b4ce169 12 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
Backstrom 0:f6e68b4ce169 13 *
Backstrom 0:f6e68b4ce169 14 */
Backstrom 0:f6e68b4ce169 15
Backstrom 0:f6e68b4ce169 16 #include "VFDDisplay.h"
Backstrom 0:f6e68b4ce169 17 #include <stdarg.h>
Backstrom 0:f6e68b4ce169 18
Backstrom 0:f6e68b4ce169 19 #define sbi(a, b) (a) |= (1 << (b))
Backstrom 0:f6e68b4ce169 20 #define cbi(a, b) (a) &= ~(1 << (b))
Backstrom 0:f6e68b4ce169 21
Backstrom 0:f6e68b4ce169 22 uint8_t calculate_segments_7(uint8_t character);
Backstrom 0:f6e68b4ce169 23
Backstrom 0:f6e68b4ce169 24 VFDDisplay::VFDDisplay(PinName data, PinName clock, PinName latch, PinName blank, uint8_t digits)
Backstrom 0:f6e68b4ce169 25 : m_mode(Long)
Backstrom 0:f6e68b4ce169 26 , m_blink_mode(Full)
Backstrom 0:f6e68b4ce169 27 , m_data(data)
Backstrom 0:f6e68b4ce169 28 , m_clock(clock)
Backstrom 0:f6e68b4ce169 29 , m_latch(latch)
Backstrom 0:f6e68b4ce169 30 , m_blank(blank)
Backstrom 0:f6e68b4ce169 31 , m_digits(digits)
Backstrom 0:f6e68b4ce169 32 , m_multiplex_counter(0)
Backstrom 0:f6e68b4ce169 33 , m_position(0)
Backstrom 0:f6e68b4ce169 34 , m_scroll_offset(0)
Backstrom 0:f6e68b4ce169 35 , m_message_length(0)
Backstrom 0:f6e68b4ce169 36 , m_blink(false)
Backstrom 0:f6e68b4ce169 37 , m_display_on(true)
Backstrom 0:f6e68b4ce169 38 , m_brightness(10)
Backstrom 0:f6e68b4ce169 39 {
Backstrom 0:f6e68b4ce169 40 //m_blank.period_ms(1);
Backstrom 0:f6e68b4ce169 41 //m_blank = 0.0;
Backstrom 0:f6e68b4ce169 42 m_blank = 0;
Backstrom 0:f6e68b4ce169 43 }
Backstrom 0:f6e68b4ce169 44
Backstrom 0:f6e68b4ce169 45 void VFDDisplay::cls()
Backstrom 0:f6e68b4ce169 46 {
Backstrom 0:f6e68b4ce169 47 memset(m_buffer, ' ', MESSAGE_LIMIT);
Backstrom 0:f6e68b4ce169 48 memset(m_char_buffer, ' ', MESSAGE_LIMIT);
Backstrom 0:f6e68b4ce169 49 memset(m_dot_buffer, ' ', MESSAGE_LIMIT);
Backstrom 0:f6e68b4ce169 50 m_position = 0;
Backstrom 0:f6e68b4ce169 51 m_scroll_offset = 0;
Backstrom 0:f6e68b4ce169 52 m_message_length = 0;
Backstrom 0:f6e68b4ce169 53 }
Backstrom 0:f6e68b4ce169 54
Backstrom 0:f6e68b4ce169 55 void VFDDisplay::setPosition(uint8_t pos)
Backstrom 0:f6e68b4ce169 56 {
Backstrom 0:f6e68b4ce169 57 m_position = pos;
Backstrom 0:f6e68b4ce169 58 if (m_position >= MESSAGE_LIMIT)
Backstrom 0:f6e68b4ce169 59 m_position = MESSAGE_LIMIT-1;
Backstrom 0:f6e68b4ce169 60 }
Backstrom 0:f6e68b4ce169 61
Backstrom 0:f6e68b4ce169 62 // Write 8 bits to HV5812 driver
Backstrom 0:f6e68b4ce169 63 void VFDDisplay::writeHV5812(uint8_t data)
Backstrom 0:f6e68b4ce169 64 {
Backstrom 0:f6e68b4ce169 65 // shift out MSB first
Backstrom 0:f6e68b4ce169 66 for (uint8_t i = 0; i < 8; i++) {
Backstrom 0:f6e68b4ce169 67 if (!!(data & (1 << (7 - i))))
Backstrom 0:f6e68b4ce169 68 m_data = 1;
Backstrom 0:f6e68b4ce169 69 else
Backstrom 0:f6e68b4ce169 70 m_data = 0;
Backstrom 0:f6e68b4ce169 71
Backstrom 0:f6e68b4ce169 72 m_clock = 1;
Backstrom 0:f6e68b4ce169 73 m_clock = 0;
Backstrom 0:f6e68b4ce169 74 }
Backstrom 0:f6e68b4ce169 75 }
Backstrom 0:f6e68b4ce169 76
Backstrom 0:f6e68b4ce169 77 const uint32_t BLINK_OFF_TIMER = 200;
Backstrom 0:f6e68b4ce169 78 const uint32_t BLINK_ON_TIMER = 350;
Backstrom 0:f6e68b4ce169 79 volatile uint32_t blink_countdown = BLINK_ON_TIMER;
Backstrom 0:f6e68b4ce169 80
Backstrom 0:f6e68b4ce169 81 extern DigitalOut led;
Backstrom 0:f6e68b4ce169 82
Backstrom 0:f6e68b4ce169 83 void VFDDisplay::multiplexTick()
Backstrom 0:f6e68b4ce169 84 {
Backstrom 0:f6e68b4ce169 85 char d;
Backstrom 0:f6e68b4ce169 86
Backstrom 0:f6e68b4ce169 87 if (m_reverse_display)
Backstrom 0:f6e68b4ce169 88 d = m_char_buffer[m_digits - m_multiplex_counter - 1 + m_scroll_offset];
Backstrom 0:f6e68b4ce169 89 else
Backstrom 0:f6e68b4ce169 90 d = m_char_buffer[m_multiplex_counter + m_scroll_offset];
Backstrom 0:f6e68b4ce169 91
Backstrom 0:f6e68b4ce169 92 // fixme: does not work properly when scrolling
Backstrom 0:f6e68b4ce169 93 if (m_dot_buffer[m_multiplex_counter + m_scroll_offset - 1] == '.')
Backstrom 0:f6e68b4ce169 94 setDot(m_multiplex_counter, true);
Backstrom 0:f6e68b4ce169 95 else
Backstrom 0:f6e68b4ce169 96 setDot(m_multiplex_counter, false);
Backstrom 0:f6e68b4ce169 97
Backstrom 0:f6e68b4ce169 98 if (m_blink) {
Backstrom 0:f6e68b4ce169 99 blink_countdown--;
Backstrom 0:f6e68b4ce169 100
Backstrom 0:f6e68b4ce169 101 if (blink_countdown == 0) {
Backstrom 0:f6e68b4ce169 102 m_display_on = !m_display_on;
Backstrom 0:f6e68b4ce169 103
Backstrom 0:f6e68b4ce169 104 if (m_display_on)
Backstrom 0:f6e68b4ce169 105 blink_countdown = BLINK_ON_TIMER;
Backstrom 0:f6e68b4ce169 106 else
Backstrom 0:f6e68b4ce169 107 blink_countdown = BLINK_OFF_TIMER;
Backstrom 0:f6e68b4ce169 108 }
Backstrom 0:f6e68b4ce169 109 }
Backstrom 0:f6e68b4ce169 110
Backstrom 0:f6e68b4ce169 111 handleBlink(d);
Backstrom 0:f6e68b4ce169 112
Backstrom 0:f6e68b4ce169 113 m_multiplex_counter++;
Backstrom 0:f6e68b4ce169 114 if (m_multiplex_counter > m_multiplex_limit)
Backstrom 0:f6e68b4ce169 115 m_multiplex_counter = 0;
Backstrom 0:f6e68b4ce169 116 }
Backstrom 0:f6e68b4ce169 117
Backstrom 0:f6e68b4ce169 118 int VFDDisplay::printf(const char* format, ...)
Backstrom 0:f6e68b4ce169 119 {
Backstrom 0:f6e68b4ce169 120 va_list ap;
Backstrom 0:f6e68b4ce169 121 va_start(ap, format);
Backstrom 0:f6e68b4ce169 122 int ret = vsnprintf(m_buffer, MESSAGE_LIMIT, format, ap);
Backstrom 0:f6e68b4ce169 123 va_end(ap);
Backstrom 0:f6e68b4ce169 124
Backstrom 0:f6e68b4ce169 125 // post-processing for seamless dot support
Backstrom 0:f6e68b4ce169 126 // splits buffer into two: one that contains characters
Backstrom 0:f6e68b4ce169 127 // and one that contains dots
Backstrom 0:f6e68b4ce169 128 uint8_t pos = 0;
Backstrom 0:f6e68b4ce169 129
Backstrom 0:f6e68b4ce169 130 char* temp = m_buffer;
Backstrom 0:f6e68b4ce169 131
Backstrom 0:f6e68b4ce169 132 while (*temp) {
Backstrom 0:f6e68b4ce169 133 if (*temp == '.') {
Backstrom 0:f6e68b4ce169 134 if (pos > 0) m_dot_buffer[pos-1] = '.';
Backstrom 0:f6e68b4ce169 135 temp++;
Backstrom 0:f6e68b4ce169 136 }
Backstrom 0:f6e68b4ce169 137 else {
Backstrom 0:f6e68b4ce169 138 m_dot_buffer[pos] = ' ';
Backstrom 0:f6e68b4ce169 139 m_char_buffer[pos++] = *temp;
Backstrom 0:f6e68b4ce169 140 temp++;
Backstrom 0:f6e68b4ce169 141 }
Backstrom 0:f6e68b4ce169 142 }
Backstrom 0:f6e68b4ce169 143
Backstrom 0:f6e68b4ce169 144 /*
Backstrom 0:f6e68b4ce169 145 for (uint8_t i = 0; i < strlen(m_buffer); i++) {
Backstrom 0:f6e68b4ce169 146 char c = m_buffer[i];
Backstrom 0:f6e68b4ce169 147
Backstrom 0:f6e68b4ce169 148 if (c == '.') {
Backstrom 0:f6e68b4ce169 149 m_dot_buffer[pos-1] = '.';
Backstrom 0:f6e68b4ce169 150 //m_char_buffer[pos++] = c;
Backstrom 0:f6e68b4ce169 151 i++;
Backstrom 0:f6e68b4ce169 152 }
Backstrom 0:f6e68b4ce169 153 else {
Backstrom 0:f6e68b4ce169 154 m_dot_buffer[pos] = ' ';
Backstrom 0:f6e68b4ce169 155 m_char_buffer[pos++] = c;
Backstrom 0:f6e68b4ce169 156 }
Backstrom 0:f6e68b4ce169 157 }
Backstrom 0:f6e68b4ce169 158 */
Backstrom 0:f6e68b4ce169 159
Backstrom 0:f6e68b4ce169 160 m_dot_buffer[pos] = 0;
Backstrom 0:f6e68b4ce169 161 m_char_buffer[pos] = 0;
Backstrom 0:f6e68b4ce169 162
Backstrom 0:f6e68b4ce169 163 m_position = ret;
Backstrom 0:f6e68b4ce169 164 m_message_length = strlen(m_char_buffer);
Backstrom 0:f6e68b4ce169 165
Backstrom 0:f6e68b4ce169 166 return ret;
Backstrom 0:f6e68b4ce169 167 }
Backstrom 0:f6e68b4ce169 168
Backstrom 0:f6e68b4ce169 169 int VFDDisplay::_putc(int c)
Backstrom 0:f6e68b4ce169 170 {
Backstrom 0:f6e68b4ce169 171 // fixme: support dot buffer
Backstrom 0:f6e68b4ce169 172 m_char_buffer[m_position] = c;
Backstrom 0:f6e68b4ce169 173 m_buffer[m_position++] = c;
Backstrom 0:f6e68b4ce169 174 m_message_length++;
Backstrom 0:f6e68b4ce169 175 return 1;
Backstrom 0:f6e68b4ce169 176 }
Backstrom 0:f6e68b4ce169 177
Backstrom 0:f6e68b4ce169 178 int VFDDisplay::_getc()
Backstrom 0:f6e68b4ce169 179 {
Backstrom 0:f6e68b4ce169 180 return -1;
Backstrom 0:f6e68b4ce169 181 }
Backstrom 0:f6e68b4ce169 182
Backstrom 0:f6e68b4ce169 183 void VFDDisplay::scroll(int8_t spaces /*= 1*/)
Backstrom 0:f6e68b4ce169 184 {
Backstrom 0:f6e68b4ce169 185 m_scroll_offset += spaces;
Backstrom 0:f6e68b4ce169 186 //if (m_scroll_offset > MESSAGE_LIMIT - m_digits)
Backstrom 0:f6e68b4ce169 187 // m_scroll_offset = 0;
Backstrom 0:f6e68b4ce169 188 }
Backstrom 0:f6e68b4ce169 189
Backstrom 0:f6e68b4ce169 190 void VFDDisplay::resetScroll()
Backstrom 0:f6e68b4ce169 191 {
Backstrom 0:f6e68b4ce169 192 m_scroll_offset = 0;
Backstrom 0:f6e68b4ce169 193 }
Backstrom 0:f6e68b4ce169 194
Backstrom 0:f6e68b4ce169 195 bool VFDDisplay::scrollFinished()
Backstrom 0:f6e68b4ce169 196 {
Backstrom 0:f6e68b4ce169 197 if (m_scroll_offset > strlen(m_char_buffer))
Backstrom 0:f6e68b4ce169 198 return true;
Backstrom 0:f6e68b4ce169 199 return false;
Backstrom 0:f6e68b4ce169 200 }
Backstrom 0:f6e68b4ce169 201
Backstrom 0:f6e68b4ce169 202 void VFDDisplay::setDot(uint8_t pos, bool on)
Backstrom 0:f6e68b4ce169 203 {
Backstrom 0:f6e68b4ce169 204 if (on) {
Backstrom 0:f6e68b4ce169 205 sbi(m_dots, pos);
Backstrom 0:f6e68b4ce169 206 }
Backstrom 0:f6e68b4ce169 207 else {
Backstrom 0:f6e68b4ce169 208 cbi(m_dots, pos);
Backstrom 0:f6e68b4ce169 209 }
Backstrom 0:f6e68b4ce169 210 }
Backstrom 0:f6e68b4ce169 211
Backstrom 0:f6e68b4ce169 212 void VFDDisplay::toggleTimeMode()
Backstrom 0:f6e68b4ce169 213 {
Backstrom 0:f6e68b4ce169 214 if (m_mode == Short) m_mode = Extra;
Backstrom 0:f6e68b4ce169 215 else if (m_mode == Extra) m_mode = Long;
Backstrom 0:f6e68b4ce169 216 else m_mode = Short;
Backstrom 0:f6e68b4ce169 217 }
Backstrom 0:f6e68b4ce169 218
Backstrom 0:f6e68b4ce169 219 void VFDDisplay::setBrightness(uint8_t brite)
Backstrom 0:f6e68b4ce169 220 {
Backstrom 0:f6e68b4ce169 221 if (brite > 10) brite = 10;
Backstrom 0:f6e68b4ce169 222 m_brightness = brite;
Backstrom 0:f6e68b4ce169 223 }
Backstrom 0:f6e68b4ce169 224
Backstrom 0:f6e68b4ce169 225 uint8_t VFDDisplay::incBrightness()
Backstrom 0:f6e68b4ce169 226 {
Backstrom 0:f6e68b4ce169 227 float f = m_blank;
Backstrom 0:f6e68b4ce169 228 if (f >= 0.9) f = 0.0;
Backstrom 0:f6e68b4ce169 229 f+= 0.1;
Backstrom 0:f6e68b4ce169 230 m_blank = f;
Backstrom 0:f6e68b4ce169 231 return f*10;
Backstrom 0:f6e68b4ce169 232 }