VFD modular clock firmware
Dependencies: DipCortex-EEprom RTC flw mbed
Revision 0:f6e68b4ce169, committed 2015-02-09
- Comitter:
- Backstrom
- Date:
- Mon Feb 09 13:40:46 2015 +0000
- Child:
- 1:391b0fbc3bc0
- Commit message:
- Initial commit
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.gitignore Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,2 @@ +.hg +.hgignore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DipCortex-EEprom/DipCortex-EEprom.cpp Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,211 @@ +//----------------------------------------------------------------------------- +//* Software that is described herein is for illustrative purposes only +//* which provides customers with programming information regarding the +//* products. This software is supplied "AS IS" without any warranties. +//* NXP Semiconductors assumes no responsibility or liability for the +//* use of the software, conveys no license or title under any patent, +//* copyright, or mask work right to the product. NXP Semiconductors +//* reserves the right to make changes in the software without +//* notification. NXP Semiconductors also make no representation or +//* warranty that such application will be suitable for the specified +//* use without further testing or modification. +//* Permission to use, copy, modify, and distribute this software and its +//* documentation is hereby granted, under NXP Semiconductors' +//* relevant copyright in the software, without fee, provided that it +//* is used in conjunction with NXP Semiconductors microcontrollers. This +//* copyright, permission, and disclaimer notice must appear in all copies of +//* this code. +//----------------------------------------------------------------------------- + +#include <stdint.h> +#include <string.h> +#include "DipCortex-EEprom.h" +#include "LPC13Uxx.h" + +unsigned param_table[5]; +unsigned result_table[5]; + +unsigned cclk; +char flash_buf[FLASH_BUF_SIZE]; +unsigned * flash_address; +unsigned byte_ctr; + +#define iap_entry ((void (*)(unsigned [],unsigned []))(IAP_ADDRESS)) + +void IAP_WriteData(unsigned cclk,unsigned flash_address,unsigned * flash_data_buf, unsigned count); +void IAP_PrepareEraseSector( unsigned flash_address ); +void IAP_EraseSector(unsigned start_sector,unsigned end_sector,unsigned cclk); +void IAP_PrepareSector(unsigned start_sector,unsigned end_sector,unsigned cclk); + + +void IAP_WriteData(unsigned cclk,unsigned flash_address,unsigned * flash_data_buf, unsigned count) +{ + param_table[0] = COPY_RAM_TO_FLASH; + param_table[1] = flash_address; + param_table[2] = (unsigned)flash_data_buf; + param_table[3] = count; + param_table[4] = cclk; + iap_entry(param_table,result_table); +} + +void IAP_EraseSector(unsigned start_sector,unsigned end_sector,unsigned cclk) +{ + param_table[0] = ERASE_SECTOR; + param_table[1] = start_sector; + param_table[2] = end_sector; + param_table[3] = cclk; + iap_entry(param_table,result_table); +} + +void IAP_PrepareSector(unsigned start_sector,unsigned end_sector,unsigned cclk) +{ + param_table[0] = PREPARE_SECTOR_FOR_WRITE; + param_table[1] = start_sector; + param_table[2] = end_sector; + param_table[3] = cclk; + iap_entry(param_table,result_table); +} + +int IAP_ErasePage ( unsigned startPageNo, unsigned endPageNo, unsigned cclk ) +{ + param_table[0] = ERASE_PAGE; + param_table[1] = startPageNo; + param_table[2] = endPageNo; + param_table[3] = cclk; + iap_entry(param_table,result_table); + + if( result_table[0] == CMD_SUCCESS ) + { + return (1); + } + else + { + return (0); + } +} + +void IAP_PrepareEraseSector( unsigned flash_address ) +{ +unsigned i; +unsigned end_sector; + + end_sector = MAX_USER_SECTOR; + + for(i=0; i<=end_sector; i++) + { + if(flash_address < (SECTOR_0_START_ADDR + ((i + 1) * SECTOR_SIZE))) + { + LPC_GPIO->NOT[ 1 ] = 1<<16; + + // if its the start of a sector, erase it + if( flash_address == SECTOR_0_START_ADDR + (SECTOR_SIZE * i)) + { + IAP_PrepareSector(i,i,cclk); + IAP_EraseSector(i,i,cclk); + } + IAP_PrepareSector(i,i,cclk); + break; + } + } +} + +int IAP_WritePage (unsigned * dst, char * src, unsigned no_of_bytes) +{ +unsigned enabled_irqs; + + // A copy of any enabled interrupts + enabled_irqs = NVIC->ISER[0]; + NVIC->ICER[0] = enabled_irqs; + + memcpy(&flash_buf[0], src, no_of_bytes); + + // If the address is the start of a sector then, prepare and erase it + IAP_PrepareEraseSector((unsigned)dst); + //IAP_ErasePage (1, 1, cclk); + + IAP_WriteData(cclk, (unsigned)dst, (unsigned *)flash_buf, FLASH_BUF_SIZE); + + NVIC->ISER[0] = enabled_irqs; + + return( result_table[0] ); +} + +int IAP_CheckForUserCode(void) +{ + unsigned *pmem, checksum,i; + + param_table[0] = BLANK_CHECK_SECTOR; + param_table[1] = USER_START_SECTOR; + param_table[2] = USER_START_SECTOR; + iap_entry(param_table,result_table); + + if( result_table[0] == CMD_SUCCESS ) + { + // it's blank + return (0); + } + else + { + /* + * The reserved Cortex-M3 exception vector location 7 (offset 0x001C + * in the vector table) should contain the 2’s complement of the + * checksum of table entries 0 through 6. This causes the checksum + * of the first 8 table entries to be 0. This code checksums the + * first 8 locations of the start of user flash. If the result is 0, + * then the contents is deemed a 'valid' image. + */ + checksum = 0; + pmem = (unsigned *)USER_START_SECTOR; + for (i = 0; i <= 7; i++) + { + checksum += *pmem; + pmem++; + } + if (checksum != 0) + { + // Failed to checksum, not valid + } + else + { + // Checksum passed + return (1); + } + } + + return (0); +} + +void IAP_Init( void ) +{ + cclk = CCLK; + byte_ctr = 0; + flash_address = (unsigned *)UPDATE_REQD; +} + +void IAP_Eeprom_Write ( uint32_t eeAddress, uint8_t* buffAddress, uint32_t byteCount ) +{ + unsigned int command[5], result[4]; + + command[0] = EEPROM_WRITE; + command[1] = (uint32_t) eeAddress; + command[2] = (uint32_t) buffAddress; + command[3] = byteCount; + command[4] = cclk; + + /* Invoke IAP call...*/ + iap_entry(command, result); +} + +void IAP_Eeprom_Read ( uint32_t eeAddress, uint8_t* buffAddress, uint32_t byteCount ) +{ + unsigned int command[5], result[4]; + + command[0] = EEPROM_READ; + command[1] = (uint32_t) eeAddress; + command[2] = (uint32_t) buffAddress; + command[3] = byteCount; + command[4] = cclk; + + /* Invoke IAP call...*/ + iap_entry( command, result); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DipCortex-EEprom/DipCortex-EEprom.h Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,83 @@ +#define USER_START_SECTOR SECTOR_2_START + +#ifndef _SBL_IAP_H +#define _SBL_IAP_H + + +#define SECTOR_0_START 0x00000000 +#define SECTOR_1_START 0x00001000 +#define SECTOR_2_START 0x00002000 +#define SECTOR_3_START 0x00003000 +#define SECTOR_4_START 0x00004000 +#define SECTOR_5_START 0x00005000 +#define SECTOR_6_START 0x00006000 +#define SECTOR_7_START 0x00007000 +#define SECTOR_8_START 0x00008000 +#define SECTOR_9_START 0x00009000 +#define SECTOR_10_START 0x0000A000 +#define SECTOR_11_START 0x0000B000 +#define SECTOR_12_START 0x0000C000 +#define SECTOR_13_START 0x0000D000 +#define SECTOR_14_START 0x0000E000 +#define SECTOR_15_START 0x0000F000 + + +#define SECTOR_0_END 0x00000FFF +#define SECTOR_1_END 0x00001FFF +#define SECTOR_2_END 0x00002FFF +#define SECTOR_3_END 0x00003FFF +#define SECTOR_4_END 0x00004FFF +#define SECTOR_5_END 0x00005FFF +#define SECTOR_6_END 0x00006FFF +#define SECTOR_7_END 0x00007FFF +#define SECTOR_8_END 0x00008FFF +#define SECTOR_9_END 0x00009FFF +#define SECTOR_10_END 0x0000AFFF +#define SECTOR_11_END 0x0000BFFF +#define SECTOR_12_END 0x0000CFFF +#define SECTOR_13_END 0x0000DFFF +#define SECTOR_14_END 0x0000EFFF +#define SECTOR_15_END 0x0000FFFF + +#define CCLK 72000 /* 72,000 KHz for IAP call WiFI Dip and M3 - TODO : Addjust for M0*/ + +#define FLASH_BUF_SIZE 256 +#define SECTOR_0_START_ADDR 0 +#define SECTOR_SIZE 4096 +#define MAX_USER_SECTOR 16 +#define PAGES_PER_SECTOR 16 + +//extern const unsigned sector_start_map[]; +//extern const unsigned sector_end_map[]; +extern const unsigned crp; + +unsigned write_flash(unsigned * dst, char * src, unsigned no_of_bytes); +void erase_user_flash(void); +void IAP_Init(void); +int IAP_CheckForUserCode(void); +int IAP_WritePage (unsigned * dst, char * src, unsigned no_of_bytes); +void IAP_Eeprom_Write ( uint32_t eeAddress, uint8_t* buffAddress, uint32_t byteCount ); +void IAP_Eeprom_Read ( uint32_t eeAddress, uint8_t* buffAddress, uint32_t byteCount ); + +typedef enum +{ +PREPARE_SECTOR_FOR_WRITE=50, +COPY_RAM_TO_FLASH=51, +ERASE_SECTOR=52, +BLANK_CHECK_SECTOR=53, +READ_PART_ID=54, +READ_BOOT_VER=55, +COMPARE=56, +REINVOKE_ISP=57, +ERASE_PAGE=59, +EEPROM_WRITE=61, +EEPROM_READ=62, + +}IAP_Command_Code; + +#define CMD_SUCCESS 0 +#define IAP_ADDRESS 0x1FFF1FF1 + +#define UPDATE_REQD 133 + +#endif /* _SBL_IAP_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IV18Display.cpp Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,178 @@ +/* + * 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)); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IV18Display.h Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,40 @@ +/* + * VFDDeluxe / Simpleclock VFD - 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. + * + */ + + +#ifndef __IV18_DISPLAY_H_ +#define __IV18_DISPLAY_H_ + +#include "mbed.h" +#include "VFDDisplay.h" + +class IV18Display : public VFDDisplay +{ +public: + IV18Display(PinName data, PinName clock, PinName latch, PinName blank); + + virtual void writeDisplay(uint8_t digit, uint16_t segments); + //virtual void printTime(time_t t, uint8_t hundredths); + virtual void printTime(struct tm* tm, uint8_t hundredths); + virtual void printTimeLong(struct tm* tm, uint8_t hundredths); + virtual void printTimeSet(struct tm* tm, bool showSeconds = true); + virtual void printDate(struct tm* tm); + +private: + virtual uint16_t calculateSegments(char c, uint8_t digit); + virtual void handleBlink(char d); +}; + +#endif // __IV18_DISPLAY_H_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RTC/ds1302.cpp Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,189 @@ +/* + * 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 "global.h" +#include "ds1302.h" + +DS1302::DS1302(PinName sclk, PinName io, PinName rst) + : m_sclk(sclk) + , m_io(io) + , m_rst(rst) +{ +} + +void DS1302::begin() +{ + uint8_t x; + + m_rst = 0; + wait_us(2); + m_sclk = 0; + + write_byte(0x8e,0); + write_byte(0x90,0xa4); + + x=read_byte(0x81); + + if((x & 0x80) != 0) // start oscillator + write_byte(0x80,0); +} + + +time_t DS1302::time() +{ + return m_time; +} + +struct tm* DS1302::getTime() +{ + m_tm.tm_sec = bcd2dec(read_byte(0x81)); + m_tm.tm_min = bcd2dec(read_byte(0x83)); + m_tm.tm_hour = bcd2dec(read_byte(0x84)); + + return &m_tm; +} + +void DS1302::getTime(uint8_t* hour, uint8_t* min, uint8_t* sec) +{ + if (sec) *sec = bcd2dec(read_byte(0x81)); + if (min) *min = bcd2dec(read_byte(0x83)); + if (hour) *hour = bcd2dec(read_byte(0x84)); +} + +void DS1302::setTime(time_t t) +{ +} + +void DS1302::setTime(uint8_t hour, uint8_t min, uint8_t sec) +{ + write_byte(0x84, dec2bcd(hour)); + write_byte(0x82, dec2bcd(min)); + write_byte(0x80, dec2bcd(sec)); +} + +void DS1302::setTime(struct tm* tm) +{ +/* + write_byte(0x86, dec2bcd(day)); + write_byte(0x88, dec2bcd(month)); + write_byte(0x8c, dec2bcd(year)); + write_byte(0x8a, dec2bcd(dayofweek)); + write_byte(0x84, dec2bcd(hour)); + write_byte(0x82, dec2bcd(min)); + write_byte(0x80, dec2bcd(sec)); + +void ds1302::set_datetime(BYTE day, BYTE mth, BYTE year, BYTE dow, BYTE hr, BYTE min) +{ + write(0x86,get_bcd(day)); + write(0x88,get_bcd(mth)); + write(0x8c,get_bcd(year)); + write(0x8a,get_bcd(dow)); + write(0x84,get_bcd(hr)); + write(0x82,get_bcd(min)); + write(0x80,get_bcd(0)); +} +*/ +} + +void DS1302::setAlarm(time_t t) +{ +} + +void DS1302::setAlarm(uint8_t hour, uint8_t min, uint8_t sec) +{ +} + +struct tm* DS1302::getAlarm(void) +{ + return 0; +} + +void DS1302::getAlarm(uint8_t* hour, uint8_t* min, uint8_t* sec) +{ +} + +bool DS1302::checkAlarm(void) +{ + return false; +} + +void DS1302::SQWEnable(bool enable) +{ +} + +void DS1302::SQWSetFreq(enum RTC_SQW_FREQ freq) +{ +} + +uint8_t DS1302::read_byte(uint8_t cmd) +{ + uint8_t data=0; + + m_rst = 1; + write_byte(cmd); + + m_io.input(); + wait_us(1); + + for (uint8_t i = 0; i <= 7; i++) + { + data += m_io<<i; + m_sclk = 1; + wait_us(1); + m_sclk = 0; + wait_us(1); + } + + m_rst = 0; + + return data; +} + +void DS1302::write_byte(uint8_t cmd, uint8_t data) +{ + m_rst = 1; + wait_us(1); + + write_byte(cmd); + write_byte(data); + + m_rst = 0; +} + +void DS1302::write_byte(uint8_t cmd) +{ + m_io.output(); + + for (uint8_t i=0; i<=7; i++) + { + m_io = (cmd >> i) & 0x01; + wait_us(1); + m_sclk = 1; + wait_us(1); + m_sclk = 0; + } + + m_io.input(); +} + +void DS1302::writeRam(uint8_t addr, uint8_t data) +{ + write_byte(addr|0xC0, data); +} + +uint8_t DS1302::readRam(uint8_t addr) +{ + return read_byte(addr|0xC1); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RTC/ds1302.h Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,58 @@ +/* + * 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. + * + */ + +#ifndef __DS1302_H_ +#define __DS1302_H_ + +#include "rtc.h" + +class DS1302 : public RTC { +public: + DS1302(PinName sclk, PinName io, PinName rst); + + virtual void begin(); + + virtual time_t time(); + virtual struct tm* getTime(); + virtual void getTime(uint8_t* hour, uint8_t* min, uint8_t* sec); + + virtual void setTime(time_t t); + virtual void setTime(struct tm* tm); + virtual void setTime(uint8_t hour, uint8_t min, uint8_t sec); + + virtual void setAlarm(time_t t); + virtual void setAlarm(uint8_t hour, uint8_t min, uint8_t sec); + virtual struct tm* getAlarm(void); + virtual void getAlarm(uint8_t* hour, uint8_t* min, uint8_t* sec); + virtual bool checkAlarm(void); + + virtual void SQWEnable(bool enable); + virtual void SQWSetFreq(enum RTC_SQW_FREQ freq); + +private: + DigitalOut m_sclk; + DigitalInOut m_io; + DigitalOut m_rst; + + uint8_t read_byte(uint8_t cmd); + void write_byte(uint8_t cmd, uint8_t data); + void write_byte(uint8_t cmd); + + void writeRam(uint8_t addr, uint8_t data); + uint8_t readRam(uint8_t addr); +}; + + +#endif // __DS1302_H_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RTC/ds3231m.cpp Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,225 @@ +/* + * 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 "global.h" +#include "ds3231m.h" + +#define DS3231M_SLAVE_ADDR 0xD0 + +DS3231M::DS3231M(I2C& i2c) + : RTC() + , m_i2c(i2c) +{ + m_i2c.frequency(100000); +} + +void DS3231M::begin() +{ +} + +time_t DS3231M::time() +{ + return m_time; +} + +struct tm* DS3231M::getTime() +{ + char rtc[7]; + + rtc[0] = 0; // second register, 0 + int w = m_i2c.write(DS3231M_SLAVE_ADDR, rtc, 1); + int r = m_i2c.read(DS3231M_SLAVE_ADDR, rtc, 7); + + // Clear clock halt bit from read data + //rtc[0] &= ~(_BV(CH_BIT)); + + m_tm.tm_sec = bcd2dec(rtc[0]); + m_tm.tm_min = bcd2dec(rtc[1]); + m_tm.tm_hour = bcd2dec(rtc[2]); + m_tm.tm_wday = bcd2dec(rtc[3])-1; + m_tm.tm_mday = bcd2dec(rtc[4]); + m_tm.tm_mon = bcd2dec(rtc[5])-1; // tm_mon is 0-11 + m_tm.tm_year = bcd2dec(rtc[6]); + + return &m_tm; +} + +void DS3231M::getTime(uint8_t* hour, uint8_t* min, uint8_t* sec) +{ + char rtc[3]; + + rtc[0] = 0; // second register, 0 + int w = m_i2c.write(DS3231M_SLAVE_ADDR, rtc, 1); + int r = m_i2c.read(DS3231M_SLAVE_ADDR, rtc, 3); + + // Clear clock halt bit from read data + //rtc[0] &= ~(_BV(CH_BIT)); + + if (sec) *sec = bcd2dec(rtc[0]); + if (min) *min = bcd2dec(rtc[1]); + if (hour) *hour = bcd2dec(rtc[2]); +} + +void DS3231M::setTime(time_t t) +{ + struct tm * timeinfo; + timeinfo = localtime (&t); + setTime(timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); +} + +void DS3231M::setTime(uint8_t hour, uint8_t min, uint8_t sec) +{ + write_byte(dec2bcd(sec), 0); + write_byte(dec2bcd(min), 1); + write_byte(dec2bcd(hour), 2); +} + +void DS3231M::setTime(struct tm* tm) +{ + write_byte(dec2bcd(tm->tm_sec), 0); + write_byte(dec2bcd(tm->tm_min), 1); + write_byte(dec2bcd(tm->tm_hour), 2); + write_byte(dec2bcd(tm->tm_wday+1), 3); + write_byte(dec2bcd(tm->tm_mday), 4); + write_byte(dec2bcd(tm->tm_mon+1), 5); + write_byte(dec2bcd(tm->tm_year), 6); +} + +void DS3231M::setAlarm(time_t t) +{ + struct tm * timeinfo; + timeinfo = localtime (&t); + setAlarm(timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); +} + +void DS3231M::setAlarm(uint8_t hour, uint8_t min, uint8_t sec) +{ + /* + * 07h: A1M1:0 Alarm 1 seconds + * 08h: A1M2:0 Alarm 1 minutes + * 09h: A1M3:0 Alarm 1 hour (bit6 is am/pm flag in 12h mode) + * 0ah: A1M4:1 Alarm 1 day/date (bit6: 1 for day, 0 for date) + * Sets alarm to fire when hour, minute and second matches + */ + write_byte(dec2bcd(sec), 0x07); // second + write_byte(dec2bcd(min), 0x08); // minute + write_byte(dec2bcd(hour), 0x09); // hour + write_byte(0x81, 0x0a); // day (upper bit must be set) + + // clear alarm flag + uint8_t val = read_byte(0x0f); + write_byte(val & ~0x01, 0x0f); +} + + +struct tm* DS3231M::getAlarm(void) +{ + struct tm * timeinfo = getTime(); + uint8_t hour, min, sec; + + getAlarm(&hour, &min, &sec); + timeinfo->tm_hour = hour; + timeinfo->tm_min = min; + timeinfo->tm_sec = sec; + return timeinfo; +} + +void DS3231M::getAlarm(uint8_t* hour, uint8_t* min, uint8_t* sec) +{ + *sec = bcd2dec(read_byte(0x07) & ~0x80); + *min = bcd2dec(read_byte(0x08) & ~0x80); + *hour = bcd2dec(read_byte(0x09) & ~0x80); +} + +bool DS3231M::checkAlarm(void) +{ + // Alarm 1 flag (A1F) in bit 0 + uint8_t val = read_byte(0x0f); + + // clear flag when set + if (val & 1) + write_byte(val & ~0x01, 0x0f); + + return val & 1 ? 1 : 0; +} + +void DS3231M::SQWEnable(bool enable) +{ + uint8_t control = read_byte(0x0E); // read control register + if (enable) { + control |= 0x40; // set BBSQW to 1 + control &= ~0x04; // set INTCN to 0 + } + else { + control &= ~0x40; // set BBSQW to 0 + } + // write control back + write_byte(control, 0x0E); +} + +void DS3231M::SQWSetFreq(enum RTC_SQW_FREQ freq) +{ + uint8_t control = read_byte(0x0E); // read control register + control &= ~0x18; // Set to 0 + control |= (freq << 4); // Set freq bitmask + + // write control back + write_byte(control, 0x0E); +} + +void DS3231M::Osc32kHzEnable(bool enable) +{ + uint8_t status = read_byte(0x0F); // read status + + if (enable) + status |= 0x08; // set to 1 + else + status &= ~0x08; // Set to 0 + + // write status back + write_byte(status, 0x0F); +} + +uint8_t DS3231M::read_byte(uint8_t offset) +{ + char buf[1]; + buf[0] = offset; + + int w = m_i2c.write(DS3231M_SLAVE_ADDR, buf, 1); + int r = m_i2c.read(DS3231M_SLAVE_ADDR, buf, 1); + //error = ((w!=0) || (r!=0)); + + return buf[0]; +} + +void DS3231M::write_byte(uint8_t b, uint8_t offset) +{ + char buf[2]; + buf[0] = offset; + buf[1] = b; + + int w = m_i2c.write(DS3231M_SLAVE_ADDR, buf, 2); + //error=(w!=0); +} + +void DS3231M::write_addr(uint8_t addr) +{ + /* + Wire.beginTransmission(RTC_ADDR); + Wire.write(addr); + Wire.endTransmission(); + */ +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RTC/ds3231m.h Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,67 @@ +/* + * 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. + * + */ + +#ifndef __DS3231M_H_ +#define __DS3231M_H_ + +#include "rtc.h" + +// leap year calulator expects year argument as years offset from 1970 +#define LEAP_YEAR(Y) ( ((1970+Y)>0) && !((1970+Y)%4) && ( ((1970+Y)%100) || !((1970+Y)%400) ) ) +/* Useful Constants */ +#define SECS_PER_MIN (60UL) +#define SECS_PER_HOUR (3600UL) +#define SECS_PER_DAY (SECS_PER_HOUR * 24UL) +#define DAYS_PER_WEEK (7UL) +#define SECS_PER_WEEK (SECS_PER_DAY * DAYS_PER_WEEK) +#define SECS_PER_YEAR (SECS_PER_WEEK * 52UL) +#define SECS_YR_2000 (946684800UL) // the time at the start of y2k + +class DS3231M : public RTC { +public: + DS3231M(I2C& i2c); + + virtual void begin(); + + virtual time_t time(); + virtual struct tm* getTime(); + virtual void getTime(uint8_t* hour, uint8_t* min, uint8_t* sec); + + virtual void setTime(time_t t); + virtual void setTime(struct tm* tm); + virtual void setTime(uint8_t hour, uint8_t min, uint8_t sec); + + virtual void setAlarm(time_t t); + virtual void setAlarm(uint8_t hour, uint8_t min, uint8_t sec); + virtual struct tm* getAlarm(void); + virtual void getAlarm(uint8_t* hour, uint8_t* min, uint8_t* sec); + virtual bool checkAlarm(void); + + virtual void SQWEnable(bool enable); + virtual void SQWSetFreq(enum RTC_SQW_FREQ freq); + virtual void Osc32kHzEnable(bool enable); + +private: + I2C& m_i2c; + + bool m_is_ds1307; + bool m_is_ds3231; + + uint8_t read_byte(uint8_t offset); + void write_byte(uint8_t b, uint8_t offset); + void write_addr(uint8_t addr); +}; + +#endif // __DS3231M_H_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RTC/rtc.cpp Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,107 @@ +/* + * 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 "global.h" +#include "rtc.h" + +RTC::RTC() : m_time(1388534400+40000+60) +{ + m_tenths = 0; +} + +void RTC::begin() +{ +} + +void RTC::tick() +{ + m_time++; + m_tenths = 0; +} + +void RTC::tenth_tick() +{ + m_tenths++; +} + +time_t RTC::time() +{ + return m_time; +} + +struct tm* RTC::getTime() +{ + struct tm *tmp = localtime(&m_time); + return tmp; +} + +void RTC::getTime(uint8_t* hour, uint8_t* min, uint8_t* sec) +{ + +} + +void RTC::setTime(time_t t) +{ + m_time = t; +} + +void RTC::setTime(uint8_t hour, uint8_t min, uint8_t sec) +{ +} + +void RTC::setTime(struct tm* tm) +{ +} + +void RTC::setAlarm(time_t t) +{ +} + +void RTC::setAlarm(uint8_t hour, uint8_t min, uint8_t sec) +{ +} + +struct tm* RTC::getAlarm(void) +{ + return 0; +} + +void RTC::getAlarm(uint8_t* hour, uint8_t* min, uint8_t* sec) +{ +} + +bool RTC::checkAlarm(void) +{ + return false; +} + +void RTC::SQWEnable(bool enable) +{ +} + +void RTC::SQWSetFreq(enum RTC_SQW_FREQ freq) +{ +} + +uint8_t RTC::dec2bcd(uint8_t d) +{ + return ((d/10 * 16) + (d % 10)); +} + +uint8_t RTC::bcd2dec(uint8_t d) +{ + return(((d&0xF0)>>4) * 10 + (d&0x0F)); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RTC/rtc.h Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,61 @@ +/* + * 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. + * + */ + +#ifndef __RTC_H_ +#define __RTC_H_ + +#include "mbed.h" + +class RTC { +protected: + struct tm m_tm; + time_t m_time; + uint8_t m_tenths; + +public: + RTC(); + + enum RTC_SQW_FREQ { FREQ_1 = 0, FREQ_1024, FREQ_4096, FREQ_8192 }; + + virtual void begin(); + + void tick(); + void tenth_tick(); + + virtual time_t time(); + virtual struct tm* getTime(); + virtual void getTime(uint8_t* hour, uint8_t* min, uint8_t* sec); + + virtual void setTime(time_t t); + virtual void setTime(uint8_t hour, uint8_t min, uint8_t sec); + virtual void setTime(struct tm* tm); + + virtual void setAlarm(time_t t); + virtual void setAlarm(uint8_t hour, uint8_t min, uint8_t sec); + virtual struct tm* getAlarm(void); + virtual void getAlarm(uint8_t* hour, uint8_t* min, uint8_t* sec); + virtual bool checkAlarm(void); + + virtual void SQWEnable(bool enable); + virtual void SQWSetFreq(enum RTC_SQW_FREQ freq); + + uint8_t getTenths() { return m_tenths; } + +protected: + uint8_t bcd2dec(uint8_t d); + uint8_t dec2bcd(uint8_t d); +}; + +#endif // __RTC_H_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VFDDisplay.cpp Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,232 @@ +/* + * 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 "VFDDisplay.h" +#include <stdarg.h> + +#define sbi(a, b) (a) |= (1 << (b)) +#define cbi(a, b) (a) &= ~(1 << (b)) + +uint8_t calculate_segments_7(uint8_t character); + +VFDDisplay::VFDDisplay(PinName data, PinName clock, PinName latch, PinName blank, uint8_t digits) + : m_mode(Long) + , m_blink_mode(Full) + , m_data(data) + , m_clock(clock) + , m_latch(latch) + , m_blank(blank) + , m_digits(digits) + , m_multiplex_counter(0) + , m_position(0) + , m_scroll_offset(0) + , m_message_length(0) + , m_blink(false) + , m_display_on(true) + , m_brightness(10) +{ + //m_blank.period_ms(1); + //m_blank = 0.0; + m_blank = 0; +} + +void VFDDisplay::cls() +{ + memset(m_buffer, ' ', MESSAGE_LIMIT); + memset(m_char_buffer, ' ', MESSAGE_LIMIT); + memset(m_dot_buffer, ' ', MESSAGE_LIMIT); + m_position = 0; + m_scroll_offset = 0; + m_message_length = 0; +} + +void VFDDisplay::setPosition(uint8_t pos) +{ + m_position = pos; + if (m_position >= MESSAGE_LIMIT) + m_position = MESSAGE_LIMIT-1; +} + +// Write 8 bits to HV5812 driver +void VFDDisplay::writeHV5812(uint8_t data) +{ + // shift out MSB first + for (uint8_t i = 0; i < 8; i++) { + if (!!(data & (1 << (7 - i)))) + m_data = 1; + else + m_data = 0; + + m_clock = 1; + m_clock = 0; + } +} + +const uint32_t BLINK_OFF_TIMER = 200; +const uint32_t BLINK_ON_TIMER = 350; +volatile uint32_t blink_countdown = BLINK_ON_TIMER; + +extern DigitalOut led; + +void VFDDisplay::multiplexTick() +{ + char d; + + if (m_reverse_display) + d = m_char_buffer[m_digits - m_multiplex_counter - 1 + m_scroll_offset]; + else + d = m_char_buffer[m_multiplex_counter + m_scroll_offset]; + + // fixme: does not work properly when scrolling + if (m_dot_buffer[m_multiplex_counter + m_scroll_offset - 1] == '.') + setDot(m_multiplex_counter, true); + else + setDot(m_multiplex_counter, false); + + if (m_blink) { + blink_countdown--; + + if (blink_countdown == 0) { + m_display_on = !m_display_on; + + if (m_display_on) + blink_countdown = BLINK_ON_TIMER; + else + blink_countdown = BLINK_OFF_TIMER; + } + } + + handleBlink(d); + + m_multiplex_counter++; + if (m_multiplex_counter > m_multiplex_limit) + m_multiplex_counter = 0; +} + +int VFDDisplay::printf(const char* format, ...) +{ + va_list ap; + va_start(ap, format); + int ret = vsnprintf(m_buffer, MESSAGE_LIMIT, format, ap); + va_end(ap); + + // post-processing for seamless dot support + // splits buffer into two: one that contains characters + // and one that contains dots + uint8_t pos = 0; + + char* temp = m_buffer; + + while (*temp) { + if (*temp == '.') { + if (pos > 0) m_dot_buffer[pos-1] = '.'; + temp++; + } + else { + m_dot_buffer[pos] = ' '; + m_char_buffer[pos++] = *temp; + temp++; + } + } + + /* + for (uint8_t i = 0; i < strlen(m_buffer); i++) { + char c = m_buffer[i]; + + if (c == '.') { + m_dot_buffer[pos-1] = '.'; + //m_char_buffer[pos++] = c; + i++; + } + else { + m_dot_buffer[pos] = ' '; + m_char_buffer[pos++] = c; + } + } + */ + + m_dot_buffer[pos] = 0; + m_char_buffer[pos] = 0; + + m_position = ret; + m_message_length = strlen(m_char_buffer); + + return ret; +} + +int VFDDisplay::_putc(int c) +{ + // fixme: support dot buffer + m_char_buffer[m_position] = c; + m_buffer[m_position++] = c; + m_message_length++; + return 1; +} + +int VFDDisplay::_getc() +{ + return -1; +} + +void VFDDisplay::scroll(int8_t spaces /*= 1*/) +{ + m_scroll_offset += spaces; + //if (m_scroll_offset > MESSAGE_LIMIT - m_digits) + // m_scroll_offset = 0; +} + +void VFDDisplay::resetScroll() +{ + m_scroll_offset = 0; +} + +bool VFDDisplay::scrollFinished() +{ + if (m_scroll_offset > strlen(m_char_buffer)) + return true; + return false; +} + +void VFDDisplay::setDot(uint8_t pos, bool on) +{ + if (on) { + sbi(m_dots, pos); + } + else { + cbi(m_dots, pos); + } +} + +void VFDDisplay::toggleTimeMode() +{ + if (m_mode == Short) m_mode = Extra; + else if (m_mode == Extra) m_mode = Long; + else m_mode = Short; +} + +void VFDDisplay::setBrightness(uint8_t brite) +{ + if (brite > 10) brite = 10; + m_brightness = brite; +} + +uint8_t VFDDisplay::incBrightness() +{ + float f = m_blank; + if (f >= 0.9) f = 0.0; + f+= 0.1; + m_blank = f; + return f*10; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VFDDisplay.h Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,129 @@ +/* + * 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. + * + */ + +#ifndef __VFDDISPLAY_H_ +#define __VFDDISPLAY_H_ + +#include "mbed.h" + +#define MESSAGE_LIMIT 96 + +class VFDDisplay : public Stream { +public: + enum TimeMode { + Long = 0, + Short, + Extra + }; + + // Controls how display blinks when m_blink is true + enum BlinkMode { + Full = 0, // Blink whole display + Hours, // Blink hours + Minutes, // Blink minutes + Seconds // Blink seconds + }; + +protected: + TimeMode m_mode; + BlinkMode m_blink_mode; + +public: + VFDDisplay(PinName data, PinName clock, PinName latch, PinName blank, uint8_t digits); + + virtual void cls(); + virtual void setPosition(uint8_t pos); + + virtual int putc(int c) { return _putc(c); } + int printf(const char* format, ...); + + void scroll(int8_t spaces = 1); + void resetScroll(); + bool scrollFinished(); + bool scrollAtOrigin() { return m_scroll_offset == 0; } + + void setAlarmIndicator(bool on) { m_alarm_indicator = on; } + void setGPSIndicator(bool on) { m_gps_indicator = on; } + void setColon(bool on) { m_colon = on; } + + void setDots(uint16_t dots) { m_dots = dots; } + void setDot(uint8_t pos, bool on); + + void setTimeMode(TimeMode mode) { m_mode = mode; } + void toggleTimeMode(); + + //virtual void printTime(time_t t, uint8_t hundredths) = 0; + virtual void printTime(struct tm* tm, uint8_t hundredths) = 0; + virtual void printTimeLong(struct tm* tm, uint8_t hundredths) = 0; + virtual void printTimeSet(struct tm* tm, bool showSeconds = true) = 0; + virtual void printDate(struct tm* tm) = 0; + + void setBrightness(uint8_t brite); + uint8_t getBrightness() { return m_brightness; } + uint8_t incBrightness(); + + uint8_t digits() { return m_digits; } + + void setBlinkMode(BlinkMode blink_mode) { m_blink_mode = blink_mode; } + void blink(bool b) { m_blink = b; m_display_on = true; } + void blank(bool b) { m_blank = b; } + +protected: + DigitalOut m_data; + DigitalOut m_clock; + DigitalOut m_latch; + //PwmOut m_blank; + DigitalOut m_blank; + + uint8_t m_digits; + uint8_t m_multiplex_limit; + uint8_t m_multiplex_counter; + bool m_reverse_display; + uint8_t m_position; + int8_t m_scroll_offset; + uint8_t m_message_length; + bool m_has_dots; + + char m_buffer[MESSAGE_LIMIT]; + char m_dot_buffer[MESSAGE_LIMIT]; + char m_char_buffer[MESSAGE_LIMIT]; + + void writeHV5812(uint8_t data); + virtual uint16_t calculateSegments(char c, uint8_t digit) = 0; + virtual void handleBlink(char d) = 0; + + // extra indicators (not present on all displays + bool m_alarm_indicator; + bool m_gps_indicator; + bool m_colon; + uint16_t m_dots; + + // display blinking + volatile bool m_blink; + volatile bool m_display_on; + + // brightness + uint8_t m_brightness; + +public: + virtual void writeDisplay(uint8_t digit, uint16_t segments) = 0; + void multiplexTick(); + +protected: + virtual int _putc(int c); + virtual int _getc(); +}; + +#endif // __VFDDISPLAY_H_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/_24LCXXX.lib Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/bant62/code/_24LCXXX/#859387a87312
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/beep/beep.cpp Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,163 @@ +#include "beep.h" +#include "mbed.h" + +/** class to make sound with a buzzer, based on a PwmOut + * The class use a timeout to switch off the sound - it is not blocking while making noise + * + * Example: + * @code + * // Beep with 1Khz for 0.5 seconds + * #include 'mbed.h' + * #include 'beep.h' + * + * Beep buzzer(p21); + * + * int main() { + * ... + * buzzer.beep(1000,0.5); + * ... + * } + * @endcode + */ + +//using namespace mbed; + // constructor + /** Create a Beep object connected to the specified PwmOut pin + * + * @param pin PwmOut pin to connect to + */ + +Beep::Beep(PinName pin) : _pwm(pin) { + _pwm.write(0.0); // after creating it have to be off +} + + /** stop the beep instantaneous + * usually not used + */ +void Beep::nobeep() { + _pwm.write(0.0); +} + +/** Beep with given frequency and duration. + * + * @param frequency - the frequency of the tone in Hz + * @param time - the duration of the tone in seconds + */ + +void Beep::beep(float freq, float time) { + + _pwm.period(1.0/freq); + _pwm.write(0.5); // 50% duty cycle - beep on + toff.attach(this,&Beep::nobeep, time); // time to off +} + +#define NOTE_GB 0 +#define NOTE_EB 1 +#define NOTE_FS 2 + +void Beep::play(char note) { + if (note=='a') { + beep(880,0.1); + } + if (note=='b') { + beep(987,0.1); + } + if (note=='c') { + beep(1024,0.1); + } + if (note=='d') { + beep(1175,0.1); + } + if (note=='e') { + beep(1319,0.1); + } + if (note=='f') { + beep(1397,0.1); + } + if (note=='g') { + beep(1568,0.1); + } + + if (note==NOTE_GB) { + beep(830,0.1); + } + if (note==NOTE_EB) { + beep(659,0.1); + } + if (note==NOTE_FS) { + beep(1480,0.1); + } + if (note=='w') { + wait(0.05); + } + wait (0.2); //wait while the note plays. +} + +void Beep::popcorn() { + + play('e'); + play('d'); + play('e'); + play('c'); + play(NOTE_GB); + play('c'); + play(NOTE_EB); + play('w'); + play('e'); + play('d'); + play('e'); + play('c'); + play(NOTE_GB); + play('c'); + play(NOTE_EB); + play('w'); + play('e'); + play(NOTE_FS); + play('g'); + play(NOTE_FS); + play('g'); + play('e'); + play(NOTE_FS); + play('e'); + play(NOTE_FS); + play('d'); + play('e'); + play('d'); + play('e'); + play('d'); + play('e'); + play('w'); + play('e'); + play('d'); + play('e'); + play('c'); + play(NOTE_GB); + play('c'); + play(NOTE_EB); + play('w'); + play('e'); + play('d'); + play('e'); + play('c'); + play(NOTE_GB); + play('c'); + play(NOTE_EB); + play('w'); + play('e'); + play(NOTE_FS); + play('g'); + play(NOTE_FS); + play('g'); + play('e'); + play(NOTE_FS); + play('e'); + play(NOTE_FS); + play('d'); + play('e'); + play('d'); + play('e'); + play('d'); + play('g'); + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/beep/beep.h Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,62 @@ +#ifndef MBED_BEEP_H +#define MBED_BEEP_H + +#include "mbed.h" + +/** class to make sound with a buzzer, based on a PwmOut + * The class use a timeout to switch off the sound - it is not blocking while making noise + * + * Example: + * @code + * // Beep with 1Khz for 0.5 seconds + * #include "mbed.h" + * #include "beep.h" + * + * Beep buzzer(p21); + * + * int main() { + * ... + * buzzer.beep(1000,0.5); + * ... + * } + * @endcode + */ + + +namespace mbed { + +/* Class: Beep + * A class witch uses pwm to controle a beeper to generate sounds. + */ +class Beep { + +public: + +/** Create a Beep object connected to the specified PwmOut pin + * + * @param pin PwmOut pin to connect to + */ + Beep (PinName pin); + +/** Beep with given frequency and duration. + * + * @param frequency - the frequency of the tone in Hz + * @param time - the duration of the tone in seconds + */ + void beep (float frequency, float time); + +/** stop the beep instantaneous + * usually not used + */ + void nobeep(); + + void play(char note); + void popcorn(); + +private : + PwmOut _pwm; + Timeout toff; +}; + +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/button.cpp Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,122 @@ +/* + * 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 "global.h" +#include "button.h" + +DigitalIn button1(PinMap::button1); +DigitalIn button2(PinMap::button2); +DigitalIn button3(PinMap::button3); + +uint8_t button_count = 3; + +uint8_t saved_keystatus = 0; +uint8_t keydown_keys = 0; +uint8_t keyup_keys = 0; +uint8_t keyrepeat_keys = 0; + +uint16_t keyboard_counter[3] = {0, 0, 0}; +uint8_t button_bit[3] = { 1, 2, 4}; + +#define REPEAT_SPEED 35 +volatile uint8_t repeat_speed = REPEAT_SPEED; + +void initialize_buttons() +{ + // enable pullups + button1.mode(PullUp); + button2.mode(PullUp); + button3.mode(PullUp); +} + +uint8_t get_keystatus() { + return (!button1) | (!button2 << 1) | (!button3 << 2); +} + +void button_tick() +{ + uint8_t keystatus = (!button1) | (!button2 << 1) | (!button3 << 2); + + keydown_keys |= (uint8_t)(keystatus & ~(saved_keystatus)); + keyup_keys |= (uint8_t)(~(keystatus) & saved_keystatus); + saved_keystatus = keystatus; + + for(uint8_t i = 0; i < button_count; i++) { + if(~(keydown_keys)&button_bit[i]) + ; // Do nothing, no keyrepeat is needed + else if(keyup_keys&button_bit[i]) + keyboard_counter[i] = 0; + else { + if(keyboard_counter[i] >= repeat_speed) { + keyrepeat_keys |= button_bit[i]; + keyboard_counter[i] = 0; + } + + keyboard_counter[i]++; + } + } +} + +void get_button_state(struct BUTTON_STATE* buttons) +{ + buttons->b1_keydown = keydown_keys&(button_bit[0]); + buttons->b1_keyup = keyup_keys&(button_bit[0]); + buttons->b1_repeat = keyrepeat_keys&(button_bit[0]); + + if (keyrepeat_keys&(button_bit[0])) + keyrepeat_keys &= ~(button_bit[0]); + + // Reset if we got keyup + if(keyup_keys&(button_bit[0])) { + keydown_keys &= ~(button_bit[0]); + keyup_keys &= ~(button_bit[0]); + keyrepeat_keys &= ~(button_bit[0]); + keyboard_counter[0] = 0; + } + + buttons->b2_keydown = keydown_keys&(button_bit[1]); + buttons->b2_keyup = keyup_keys&(button_bit[1]); + buttons->b2_repeat = keyrepeat_keys&(button_bit[1]); + + if (keyrepeat_keys&(button_bit[1])) + keyrepeat_keys &= ~(button_bit[1]); + + // Reset if we got keyup + if(keyup_keys&(button_bit[1])) { + keydown_keys &= ~(button_bit[1]); + keyup_keys &= ~(button_bit[1]); + keyrepeat_keys &= ~(button_bit[1]); + keyboard_counter[1] = 0; + } + + buttons->b3_keydown = keydown_keys&(button_bit[2]); + buttons->b3_keyup = keyup_keys&(button_bit[2]); + buttons->b3_repeat = keyrepeat_keys&(button_bit[2]); + + if (keyrepeat_keys&(button_bit[2])) + keyrepeat_keys &= ~(button_bit[2]); + + // Reset if we got keyup + if(keyup_keys&(button_bit[2])) { + keydown_keys &= ~(button_bit[2]); + keyup_keys &= ~(button_bit[2]); + keyrepeat_keys &= ~(button_bit[2]); + keyboard_counter[2] = 0; + } + + buttons->both_held = (keydown_keys&(button_bit[0])) && (keydown_keys&(button_bit[1])); + buttons->none_held = ~(saved_keystatus)&(button_bit[0]) && ~(saved_keystatus)&((button_bit[1])); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/button.h Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,42 @@ +/* + * 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. + * + */ + +#ifndef BUTTON_H_ +#define BUTTON_H_ + +#include <stdbool.h> + +struct BUTTON_STATE +{ + bool b1_keydown : 1; + bool b1_keyup : 1; + bool b1_repeat : 1; + bool b2_keydown : 1; + bool b2_keyup : 1; + bool b2_repeat : 1; + bool b3_keydown : 1; + bool b3_keyup : 1; + bool b3_repeat : 1; + bool both_held : 1; + bool none_held : 1; +}; + +void initialize_buttons(); +void get_button_state(struct BUTTON_STATE* buttons); +void button_tick(void); + +uint8_t get_keystatus(); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/features.h Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,66 @@ +/* + * 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. + * + */ + +#ifndef FEATURES_H_ +#define FEATURES_H_ + +#define YES 2 +#define NO 1 + +/////////////////////////////////////////// + +#if !(defined FEATURE_3BUTTON) || FEATURE_3BUTTON < NO || FEATURE_3BUTTON > YES +# error Must define FEATURE_3BUTTON to be YES or NO +#endif + +#if FEATURE_3BUTTON == YES +#define HAVE_3BUTTON +#endif + +/////////////////////////////////////////// + +#if !(defined FEATURE_GPS) || FEATURE_GPS < NO || FEATURE_GPS > YES +# error Must define FEATURE_GPS to be YES or NO +#endif + +#if FEATURE_GPS == YES +#define HAVE_GPS +#endif + +/////////////////////////////////////////// + +#if !(defined FEATURE_DS1302) || FEATURE_DS1302 < NO || FEATURE_DS1302 > YES +# error Must define FEATURE_DS1302 to be YES or NO +#endif + +#if FEATURE_DS1302 == YES +#define HAVE_DS1302 +#endif + +/////////////////////////////////////////// + +#if !(defined FEATURE_DS3231M) || FEATURE_DS3231M < NO || FEATURE_DS3231M > YES +# error Must define FEATURE_DS3231M to be YES or NO +#endif + +#if FEATURE_DS3231M == YES +#define HAVE_DS3231M +#endif + +#if FEATURE_DS1302 == YES && FEATURE_DS3231M == YES +# error Use either FEATURE_DS1202 or FEATURE_DS3231M, not both +#endif + +#endif /* FEATURES_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flw/flw.cpp Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,146 @@ +/* + * Four Letter Word Generator + * (C) 2015 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. + * + */ + +/* + * To use this Four Letter Word generator you will need the following: + * + * - A 512kbit/64kb I2C EEPROM + * - A database file, generated from this Processing application: + * https://github.com/perjg/fourletterword + * - A method for uploading the data file to the EEPROM + * (Either an Arduino Mega, or a normal Arduino with a micro SD card) + */ + +#include <string.h> +#include "flw.h" +#include "flw_blacklist.h" + + +#define EEPROM_ADDR 0b1010000 + +void FourLetterWord::rot13(char* w) +{ + while (*w != '\0') { + if (*w >= 'A' && *w <= 'M') { + *w += 13; + } + else if (*w >= 'N' && *w <= 'Z') { + *w -= 13; + } + + w++; + } +} + +bool FourLetterWord::binary_search(const char *key, int imin, int imax) +{ + int pos; + int cond = 0; + char buf[5]; + + while (imin <= imax) { + pos = (imin+imax) / 2; + + strcpy(buf, flw_blacklist[pos]); + rot13(buf); + cond = strcmp(key, buf); + + if (cond == 0) return true; + else if (cond>0) imin = pos+1; + else imax = pos-1; + } + + return false; +} + + +uint8_t FourLetterWord::read_byte(unsigned int addr) { + uint8_t rdata = 0xFF; + + _24lc.nbyte_read(addr, &rdata, 1); + return rdata; +} + +void FourLetterWord::read_buffer(unsigned int addr, uint8_t *buffer, int length) { + _24lc.nbyte_read(addr, buffer, length); +} + + +void FourLetterWord::begin(uint32_t seed, bool censored) +{ + m_lfsr = seed; + m_censored = censored; +} + +uint32_t FourLetterWord::randomize() +{ + // http://en.wikipedia.org/wiki/Linear_feedback_shift_register + // Galois LFSR: taps: 32 31 29 1; characteristic polynomial: x^32 + x^31 + x^29 + x + 1 */ + m_lfsr = (m_lfsr >> 1) ^ (-(m_lfsr & 1u) & 0xD0000001u); + return m_lfsr; +} + +bool FourLetterWord::hasEeprom() +{ + uint8_t b1 = read_byte(0); + uint8_t b2 = read_byte(1); + + if (b1 == 65 && b2 == 66) + return true; + return false; +} + +char* FourLetterWord::get_word_censored() +{ + char* w = get_word_uncensored(); + + // assume a maximum of 5 censored words chosen in a row + for (uint8_t i = 0; i < 5; i++) { + if (binary_search(w, 0, BLACKLIST_SIZE)) { // censored + w = get_word_uncensored(); + } + else + return w; + } + + return w; +} + +char* FourLetterWord::get_word_uncensored() +{ + unsigned char low = 0xFF, high = 0xFF; + unsigned char count = 0; + int next = 0; + + read_buffer(m_offset, (uint8_t*)m_current_word, 5); + count = m_current_word[4]; + m_current_word[4] = '\0'; + + next = randomize() % count; + m_offset += 5 + next * 2; + + high = read_byte(m_offset++); + low = read_byte(m_offset++); + + m_offset = (high << 8) | low; + + return m_current_word; +} + +char* FourLetterWord::getWord() +{ + if (m_censored) return get_word_censored(); + return get_word_uncensored(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flw/flw.h Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,59 @@ +/* + * Four Letter Word Generator + * (C) 2015 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. + * + */ + +#ifndef FLW_H__ +#define FLW_H__ + +#include <inttypes.h> +#include <stdbool.h> + + +#include "_24LCXXX.h" + +class FourLetterWord +{ +private: + _24LCXXX _24lc; + bool m_censored; + unsigned long m_offset; + char m_current_word[6]; + uint32_t m_lfsr; + + uint32_t randomize(); + + void rot13(char* w); + bool binary_search(const char *key, int imin, int imax); + uint8_t read_byte(unsigned int addr); + void read_buffer(unsigned int addr, uint8_t *buffer, int length); + + char* get_word_censored(); + char* get_word_uncensored(); + +public: + FourLetterWord(I2C *i2c, uint8_t addr = 0x50) : + _24lc(i2c, addr), + m_censored(true), + m_offset(0), + m_lfsr(0xbeefcace) {} + + void begin(uint32_t seed = 0xbeefcace, bool censored = true); + + void setCensored(bool c) { m_censored = c; } + + bool hasEeprom(); + char* getWord(); +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flw/flw_blacklist.h Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,72 @@ +/* + * Four Letter Word Generator + * (C) 2015 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. + * + */ + +// +// Swear word blacklist for Four Letter Word database +// All words are encoded using ROT13 so that the cencored words are not +// directly visible in the file +// +// Must be alphabetized (according to the decrypted value!), since the +// list is searched by binary search +// + +const char word_0[] = "NAHF"; +const char word_1[] = "NEFR"; +const char word_2[] = "PNJX"; +const char word_3[] = "PYVG"; +const char word_4[] = "PBPX"; +const char word_5[] = "PBBA"; +const char word_6[] = "PENC"; +const char word_7[] = "PHAG"; +const char word_8[] = "QNTB"; +const char word_9[] = "QNZA"; +const char word_10[] = "QVPX"; +const char word_11[] = "QLXR"; +const char word_12[] = "SNTF"; +const char word_13[] = "SNEG"; +const char word_14[] = "SHPX"; +const char word_15[] = "TBBX"; +const char word_16[] = "URYY"; +const char word_17[] = "WRJF"; +const char word_18[] = "WVFZ"; +const char word_19[] = "WVMZ"; +const char word_20[] = "WVMM"; +const char word_21[] = "XVXR"; +const char word_22[] = "ZHSS"; +const char word_23[] = "ANMV"; +const char word_24[] = "CNXV"; +const char word_25[] = "CVFF"; +const char word_26[] = "CBBA"; +const char word_27[] = "CBBC"; +const char word_28[] = "CBEA"; +const char word_29[] = "ENCR"; +const char word_30[] = "FUVG"; +const char word_31[] = "FZHG"; +const char word_32[] = "FCVP"; +const char word_33[] = "FYHG"; +const char word_34[] = "GVGF"; +const char word_35[] = "GHEQ"; +const char word_36[] = "GJNG"; +const char word_37[] = "JNAX"; + +#define BLACKLIST_SIZE 37 + +const char *flw_blacklist[] = +{ + word_0, word_1, word_2, word_3, word_4, word_5, word_6, word_7, word_8, word_9, + word_10, word_11, word_12, word_13, word_14, word_15, word_16, word_17, word_18, word_19, + word_20, word_21, word_22, word_23, word_24, word_25, word_26, word_27, word_28, word_29, + word_30, word_31, word_32, word_33, word_34, word_35, word_36, word_37 +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/font_7seg.cpp Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,214 @@ +/* + * 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 "mbed.h" + +uint8_t calculate_segments_7(uint8_t character); + +#define A 0 +#define B 1 +#define C 2 +#define D 3 +#define E 4 +#define F 5 +#define G 6 +#define DP 7 + +uint8_t calculate_segments_7(uint8_t character) +{ + uint8_t segments = 0; + + switch (character) + { + case 0: + segments = 0; + break; + case '0': + case 'O': + segments = (1<<A)|(1<<B)|(1<<C)|(1<<D)|(1<<E)|(1<<F); + break; + case 1: + case '1': + case 'l': + segments = (1<<B)|(1<<C); + break; + case 2: + case '2': + segments = (1<<A)|(1<<B)|(1<<D)|(1<<E)|(1<<G); + break; + case 3: + case '3': + segments = (1<<A)|(1<<B)|(1<<C)|(1<<D)|(1<<G); + break; + case 4: + case '4': + segments = (1<<B)|(1<<C)|(1<<F)|(1<<G); + break; + case 5: + case '5': + case 'S': + case 's': + segments = (1<<A)|(1<<C)|(1<<D)|(1<<F)|(1<<G); + break; + case 6: + case '6': + segments = (1<<A)|(1<<C)|(1<<D)|(1<<E)|(1<<F)|(1<<G); + break; + case 7: + case '7': + segments = (1<<A)|(1<<B)|(1<<C); + break; + case 8: + case '8': + segments = (1<<A)|(1<<B)|(1<<C)|(1<<D)|(1<<E)|(1<<F)|(1<<G); + break; + case 9: + case '9': + case 'g': + segments = (1<<A)|(1<<B)|(1<<C)|(1<<D)|(1<<F)|(1<<G); + break; + case 10: + case 'A': + case 'a': + segments = (1<<A)|(1<<B)|(1<<C)|(1<<E)|(1<<F)|(1<<G); + break; + case 11: + case 'B': + case 'b': + segments = (1<<C)|(1<<D)|(1<<E)|(1<<F)|(1<<G); + break; + case 12: + case 'C': + segments = (1<<A)|(1<<D)|(1<<E)|(1<<F); + break; + case 'c': + segments = (1<<D)|(1<<E)|(1<<G); + break; + case 13: + case 'D': + case 'd': + segments = (1<<B)|(1<<C)|(1<<D)|(1<<E)|(1<<G); + break; + case 14: + case 'E': + segments = (1<<A)|(1<<D)|(1<<E)|(1<<F)|(1<<G); + break; + case 'e': + segments = (1<<A)|(1<<B)|(1<<D)|(1<<E)|(1<<F)|(1<<G); + break; + case 15: + case 'F': + case 'f': + segments = (1<<A)|(1<<E)|(1<<F)|(1<<G); + break; + case 'G': + segments = (1<<A)|(1<<C)|(1<<D)|(1<<E)|(1<<F); + break; + case 'H': + segments = (1<<B)|(1<<C)|(1<<E)|(1<<F)|(1<<G); + break; + case 'h': + segments = (1<<C)|(1<<E)|(1<<F)|(1<<G); + break; + case 'I': + segments = (1<<B)|(1<<C); + break; + case 'i': + segments = (1<<C); + break; + case 'J': + case 'j': + segments = (1<<B)|(1<<C)|(1<<D)|(1<<E); + break; + case 'K': + case 'k': + segments = (1<<E)|(1<<F)|(1<<G); + break; + case 'L': + segments = (1<<D)|(1<<E)|(1<<F); + break; + case 'M': + case 'm': + segments = (1<<A)|(1<<C)|(1<<E)|(1<<G); + break; + case 'N': + case 'n': + segments = (1<<C)|(1<<E)|(1<<G); + break; + case 'o': + segments = (1<<C)|(1<<D)|(1<<E)|(1<<G); + break; + case 'P': + case 'p': + segments = (1<<A)|(1<<B)|(1<<E)|(1<<F)|(1<<G); + break; + case 'Q': + case 'q': + segments = (1<<A)|(1<<B)|(1<<C)|(1<<F)|(1<<G); + break; + case 'R': + case 'r': + segments = (1<<E)|(1<<G); + break; + case 'T': + case 't': + segments = (1<<D)|(1<<E)|(1<<F)|(1<<G); + break; + case 'U': + segments = (1<<B)|(1<<C)|(1<<D)|(1<<E)|(1<<F); + break; + case 'u': + segments = (1<<C)|(1<<D)|(1<<E); + break; + case 'V': + case 'v': + segments = (1<<C)|(1<<D)|(1<<E); + break; + case 'W': + case 'w': + segments = (1<<A)|(1<<C)|(1<<D)|(1<<E); + break; + case 'X': + case 'x': + segments = (1<<B)|(1<<C)|(1<<E)|(1<<F); + break; + case 'Y': + case 'y': + segments = (1<<B)|(1<<C)|(1<<D)|(1<<F)|(1<<G); + break; + case 'Z': + case 'z': + segments = (1<<A)|(1<<D)|(1<<G); + break; + case '-': + segments = (1<<G); + break; + case '"': + segments = (1<<B)|(1<<F); + break; + case 0x27: // "'" + segments = (1<<B); + break; + case '_': + segments = (1<<D); + break; + case ' ': + default: + segments = 0; + break; + } + + return segments; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/global.h Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,180 @@ +/* + * 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 "mbed.h" + +/// VFD Modular Clock - SMT mbed IV-18 +#if defined(TARGET_LPC11U24) || defined(TARGET_LPC1347) + +#define FEATURE_3BUTTON YES +#define FEATURE_GPS YES +#define FEATURE_DS1302 NO +#define FEATURE_DS3231M YES + +struct PinMap { + static const PinName data = P0_18; + static const PinName clock = P0_17; + static const PinName latch = P0_19; + static const PinName blank = P0_13; + + static const PinName button2 = P1_28; // button + static const PinName button1 = P0_7; // button + static const PinName button3 = P0_1; // button + + // RTC + static const PinName sda = P0_5; + static const PinName scl = P0_4; + + // Other + static const PinName piezo = P0_9; + static const PinName led = P1_16; + //static const PinName tx = P1_13; + //static const PinName rx = P1_14; + static const PinName ext1 = P1_19; + static const PinName ext2 = P1_20; +}; + +#endif + +/// VFD Modular Clock - mbed test board +#ifdef TARGET_LPC1114 + +#define FEATURE_3BUTTON NO +#define FEATURE_GPS YES +#define FEATURE_DS1302 NO +#define FEATURE_DS3231M YES + +struct PinMap { + // VFD Driver + static const PinName data = dp14; + static const PinName clock = dp10; + static const PinName latch = dp13; + static const PinName blank = dp1; + + // Buttons / switches + static const PinName button1 = dp26; // button + static const PinName button2 = dp24; // button + static const PinName button3 = dp28; // switch + + // Board signature + static const PinName sig0 = dp4; + static const PinName sig1 = dp2; + static const PinName sig2 = dp6; + + // Other + static const PinName piezo = dp18; + static const PinName led = dp25; + static const PinName sqw = dp17; + static const PinName tx = dp16; + static const PinName rx = dp16; + static const PinName ext1 = dp9; + static const PinName ext2 = dp11; +}; + +#endif + +/// VFD Modular Clock - mbed test board +#ifdef TARGET_LPC1549 + +#define FEATURE_3BUTTON NO +#define FEATURE_GPS NO +#define FEATURE_DS1302 NO +#define FEATURE_DS3231M YES + +struct PinMap { + // VFD Driver + static const PinName data = A5; + static const PinName clock = D13; // P0_16 + static const PinName latch = A4; + static const PinName blank = D5; + /* + static const PinName data = P0_22; // A5 + static const PinName clock = P0_16; // D13 + static const PinName latch = P0_23; // A4 + static const PinName blank = P0_16; // D5 + */ + + // Buttons / switches + static const PinName button1 = D8; + static const PinName button2 = D7; + static const PinName button3 = D2; + /* + static const PinName button1 = P0_24; // button D8 + static const PinName button2 = P0_0; // button D7 + static const PinName button3 = P0_29; // switch D2 + */ + + // Board signature + static const PinName sig0 = A0; //P0_8 + static const PinName sig1 = A1; //P0_7 + static const PinName sig2 = A2; //P0_6 + + // Other + static const PinName piezo = D4; // P0_10 + static const PinName led = D9; // P1_0 + //static const PinName sqw = P1_3; // D6 + //static const PinName tx = P0_18; // D1 + //static const PinName rx = P0_13; // D0 + static const PinName ext1 = A3; // P0_5 + static const PinName ext2 = D3; // P1_2 + + // I2C + //static const PinName sda = + //static const PinName scl = +}; + +#endif + + +/// VFD Modular Clock - BLE +#ifdef TARGET_NRF51822 + +#define FEATURE_3BUTTON NO +#define FEATURE_GPS NO +#define FEATURE_DS1302 NO +#define FEATURE_DS3231M YES + +struct PinMap { + static const PinName data = P0_15; + static const PinName clock = P0_12; + static const PinName latch = P0_13; + static const PinName blank = P0_13; + + static const PinName button1 = P0_1; + static const PinName button2 = P0_1; +}; + +#endif + +#include "features.h" + +// display state +typedef enum { + // basic states + STATE_CLOCK = 0, // shows hh-mm-ss / hh.mm.ss / hh.mm.ss.x depending on g_display_mode + STATE_SHOW_ALARM, // shows current alarm for a brief time + STATE_ALARMING, // alarm is going off + STATE_AUTO_DATE, // scroll date across the screen + STATE_AUTO_FLW, // show FLW briefly + STATE_AUTO_TEMP, // show temperature briefly + STATE_SET_ALARM_HH, // set alarm, hours + STATE_SET_ALARM_MM, // set alarm, minutes + STATE_SET_CLOCK_HH, // set clock, hours + STATE_SET_CLOCK_MM, // set clock, minutes + STATE_SET_CLOCK_SS, // set clock, seconds + STATE_FLW, // four letter word + STATE_TEMP, // temperature + STATE_MENU, // menu +} state_t;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gps.cpp Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,261 @@ +/* + * GPS support for VFD Modular Clock + * (C) 2012 William B Phelps + * + * mbed Port (C) 2014 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 "global.h" +#include "gps.h" + +#ifdef HAVE_GPS + +//Serial gps(P1_13, P1_14); +Serial* gps; + +bool g_gps_updating = false; +int g_gps_cks_errors = 0; +int g_gps_parse_errors = 0; +int g_gps_time_errors = 0; + +unsigned long tGPSupdate; + +// we double buffer: read into one line and leave one for the main program +//volatile char gpsBuffer1[GPSBUFFERSIZE]; +//volatile char gpsBuffer2[GPSBUFFERSIZE]; +volatile char* gpsBuffer1; +volatile char* gpsBuffer2; + +// our index into filling the current line +volatile uint8_t gpsBufferPtr; +// pointers to the double buffers +volatile char *gpsNextBuffer; +volatile char *gpsLastBuffer; +volatile uint8_t gpsDataReady_; + +time_t tLast = 0; // for checking GPS messages + +void GPSread() +{ + char c = gps->getc(); + + if (c == '$') { + gpsNextBuffer[gpsBufferPtr] = 0; + gpsBufferPtr = 0; + } + if (c == '\n') { // newline marks end of sentence + gpsNextBuffer[gpsBufferPtr] = 0; // terminate string + if (gpsNextBuffer == gpsBuffer1) { // switch buffers + gpsNextBuffer = gpsBuffer2; + gpsLastBuffer = gpsBuffer1; + } else { + gpsNextBuffer = gpsBuffer1; + gpsLastBuffer = gpsBuffer2; + } + gpsBufferPtr = 0; + gpsDataReady_ = true; // signal data ready + } + + gpsNextBuffer[gpsBufferPtr++] = c; // add char to current buffer, then increment index + if (gpsBufferPtr >= GPSBUFFERSIZE) // if buffer full + gpsBufferPtr = GPSBUFFERSIZE-1; // decrement index to make room (overrun) +} + +uint8_t gpsDataReady(void) { + return gpsDataReady_; +} + +char *gpsNMEA(void) { + gpsDataReady_ = false; + return (char *)gpsLastBuffer; +} + +uint32_t parsedecimal(char *str, uint8_t len) { + uint32_t d = 0; + for (uint8_t i=0; i<len; i++) { + if ((str[i] > '9') || (str[0] < '0')) + return d; // no more digits + d = (d*10) + (str[i] - '0'); + } + return d; +} + +int32_t _abs(int32_t a) { + if (a < 0) return -a; + return a; +} + +const char hex[17] = "0123456789ABCDEF"; + +uint8_t atoh(char x) { + return (strchr(hex, x) - hex); +} + +uint32_t hex2i(char *str, uint8_t len) { + uint32_t d = 0; + for (uint8_t i=0; i<len; i++) { + d = (d*10) + (strchr(hex, str[i]) - hex); + } + return d; +} + +// find next token in GPS string - find next comma, then point to following char +char * ntok ( char *ptr ) { + ptr = strchr(ptr, ','); // Find the next comma + if (ptr == NULL) return NULL; + ptr++; // point at next char after comma + return ptr; +} + +// 225446 Time of fix 22:54:46 UTC +// A Navigation receiver warning A = OK, V = warning +// 4916.45,N Latitude 49 deg. 16.45 min North +// 12311.12,W Longitude 123 deg. 11.12 min West +// 000.5 Speed over ground, Knots +// 054.7 Course Made Good, True +// 191194 Date of fix 19 November 1994 +// 020.3,E Magnetic variation 20.3 deg East +// *68 mandatory checksum + +//$GPRMC,225446.000,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68\r\n +// 0 1 2 3 4 5 6 7 +// 0123456789012345678901234567890123456789012345678901234567890123456789012 +// 0 1 2 3 4 5 6 7 8 9 10 11 12 +time_t parseGPSdata(char *gpsBuffer, bool& error, bool& fix, int8_t tzh, uint8_t tzm) { + time_t tNow; + struct tm tm; + uint8_t gpsCheck1, gpsCheck2; // checksums + + char gpsFixStat; // fix status +// char gpsLat[7]; // ddmm.ff (with decimal point) +// char gpsLatH; // hemisphere +// char gpsLong[8]; // dddmm.ff (with decimal point) +// char gpsLongH; // hemisphere +// char gpsSpeed[5]; // speed over ground +// char gpsCourse[5]; // Course +// char gpsDate[6]; // Date +// char gpsMagV[5]; // Magnetic variation +// char gpsMagD; // Mag var E/W +// char gpsCKS[2]; // Checksum without asterisk + + error = false; + fix = false; + + char *ptr; + uint32_t tmp; + if ( strncmp( gpsBuffer, "$GPRMC,", 7 ) == 0 ) { + //Calculate checksum from the received data + ptr = &gpsBuffer[1]; // start at the "G" + gpsCheck1 = 0; // init collector + + // Loop through entire string, XORing each character to the next + while (*ptr != '*') // count all the bytes up to the asterisk + { + gpsCheck1 ^= *ptr; + ptr++; + if (ptr>(gpsBuffer+GPSBUFFERSIZE)) goto GPSerrorP; // extra sanity check, can't hurt... + } + // now get the checksum from the string itself, which is in hex + gpsCheck2 = atoh(*(ptr+1)) * 16 + atoh(*(ptr+2)); + + if (gpsCheck1 == gpsCheck2) { // if checksums match, process the data + ptr = &gpsBuffer[1]; // start at beginning of buffer + ptr = ntok(ptr); // Find the time string + if (ptr == NULL) goto GPSerrorP; + char *p2 = strchr(ptr, ','); // find comma after Time + if (p2 == NULL) goto GPSerrorP; + if (p2 < (ptr+6)) goto GPSerrorP; // Time must be at least 6 chars + tmp = parsedecimal(ptr, 6); // parse integer portion + tm.tm_hour = tmp / 10000; + tm.tm_min = (tmp / 100) % 100; + tm.tm_sec = tmp % 100; + ptr = ntok(ptr); // Find the next token - Status + if (ptr == NULL) goto GPSerrorP; + gpsFixStat = ptr[0]; + if (gpsFixStat == 'A') { // if data valid, parse time & date + fix = true; + + for (uint8_t n=0; n<7; n++) { // skip 6 tokend, find date + ptr = ntok(ptr); // Find the next token + if (ptr == NULL) goto GPSerrorP; // error if not found + } + p2 = strchr(ptr, ','); // find comma after Date + if (p2 == NULL) goto GPSerrorP; + if (p2 != (ptr+6)) goto GPSerrorP; // check date length + tmp = parsedecimal(ptr, 6); + tm.tm_mday = tmp / 10000; + tm.tm_mon = ((tmp / 100) % 100) - 1; // zero offset for month + tm.tm_year = tmp % 100; + + ptr = strchr(ptr, '*'); // Find Checksum + if (ptr == NULL) goto GPSerrorP; + + tm.tm_year = y2kYearToTm(tm.tm_year); // convert yy year to (yyyy-1900) (add 100) + tNow = mktime(&tm); // convert to time_t - seconds since 0/0/1970 + + // If time jumps by more than a minute, complain about it. Either poor GPS signal or an error in the data + if ( (tLast>0) && (_abs(tNow - tLast)>60) ) // Beep if over 60 seconds since last GPRMC? + { + goto GPSerrorT; // it's probably an error + } + else { + tLast = tNow; + tNow = tNow + (long)(tzh) * SECS_PER_HOUR + (long)tzm; + + } + } // if fix status is A + } // if checksums match + else // checksums do not match + goto GPSerrorC; + + return tNow; + +GPSerrorC: + g_gps_cks_errors++; // increment error count + goto GPSerror2a; +GPSerrorP: + g_gps_parse_errors++; // increment error count + goto GPSerror2a; +GPSerrorT: +#ifdef HAVE_SERIAL_DEBUG + tDelta = tNow - tGPSupdate; + Serial.print("tNow="); Serial.print(tNow); Serial.print(", tLast="); Serial.print(tLast); Serial.print(", diff="); Serial.print(tNow-tLast); + Serial.print(", tDelta="); Serial.print(tDelta); + Serial.println(" "); +#endif + g_gps_time_errors++; // increment error count + tLast = tNow; // save new time + +GPSerror2a: + strcpy(gpsBuffer, ""); // wipe GPS buffer + } // if "$GPRMC" + + error = true; + return 0; +} + +void gps_init() { + gps = new Serial(P1_13, P1_14); + gps->attach(&GPSread); + + gpsBuffer1 = new char[GPSBUFFERSIZE]; + gpsBuffer2 = new char[GPSBUFFERSIZE]; + + tGPSupdate = 0; // reset GPS last update time + gpsDataReady_ = false; + gpsBufferPtr = 0; + gpsNextBuffer = gpsBuffer1; + gpsLastBuffer = gpsBuffer2; +} + +#endif // HAVE_GPS
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gps.h Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,58 @@ +/* + * GPS support for VFD Modular Clock + * (C) 2012 William B Phelps + * + * mbed Port (C) 2014 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. + * + */ + +#ifndef GPS_H_ +#define GPS_H_ + +#ifdef HAVE_GPS + +#include "mbed.h" + +//convenience macro to convert to and from tm years +#define tmYearToY2k(Y) ((Y) - 100) // offset is from 1900 +#define y2kYearToTm(Y) ((Y) + 100) + +// String buffer size: +#define GPSBUFFERSIZE 96 +//The year the clock was programmed, used for error checking +#define PROGRAMMING_YEAR 14 + +#define SECS_PER_HOUR (3600UL) + +extern unsigned long tGPSupdate; // really time_t + +// we double buffer: read into one line and leave one for the main program +//extern volatile char gpsBuffer1[GPSBUFFERSIZE]; +//extern volatile char gpsBuffer2[GPSBUFFERSIZE]; +// our index into filling the current line +//extern volatile uint8_t gpsBufferPtr; +// pointers to the double buffers +//extern volatile char *gpsNextBuffer; +//extern volatile char *gpsLastBuffer; +//extern volatile uint8_t gpsDataReady_; + +//GPS serial data handling functions: +uint8_t gpsDataReady(void); +void GPSread(char c); +char *gpsNMEA(void); +time_t parseGPSdata(char *gpsBuffer, bool& error, bool& fix, int8_t tzh, uint8_t tzm); + +uint8_t leapyear(uint16_t y); +void gps_init(); + +#endif // HAVE_GPS +#endif // GPS_H_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,650 @@ +/* + * 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 "global.h" +#include "mbed.h" + +#include "VFDDisplay.h" +#include "IV18Display.h" + +#include "prefs.h" +#include "gps.h" +#include "menu.h" +#include "button.h" +#include "rtc.h" +#include "ds3231m.h" +#include "beep.h" +#include "flw.h" + +IV18Display display(PinMap::data, PinMap::clock, PinMap::latch, PinMap::blank); + +Menu menu; + +I2C i2c(PinMap::sda, PinMap::scl); +DS3231M rtc(i2c); +//RTC rtc; + +DigitalOut led(PinMap::led); +Beep piezo(PinMap::piezo); + +FourLetterWord flw(&i2c); +char flwWord[5]; +int flwOffset; +int flwOffsetDirection = 1; +volatile bool haveEEPROM; + +Ticker blanker; +Ticker multiplexer; +Ticker button_ticker; +Ticker rtc_ticker; +Ticker tenth_ticker; + +volatile state_t g_clock_state = STATE_CLOCK; +uint32_t gps_last_update = 0xffff; + +uint8_t calculate_segments_7(uint8_t character); + +// Alarm +volatile bool g_alarm_on; +volatile bool g_alarming; + +void write_vfd_8bit(uint8_t data); +void write_vfd_iv18(uint8_t digit, uint8_t segments); +void write_vfd(uint8_t digit, uint8_t segments); +void demo_cycle(char* buf); + +void blank_tick() +{ + static uint32_t cnt = 0; + + if ((cnt%10) > (10-display.getBrightness())) { + display.blank(false); + } + else { + display.blank(true); + } + + cnt++; +} + +void multiplex_tick() +{ + display.multiplexTick(); +} + +void rtc_tick() +{ + if (haveEEPROM) + strncpy(flwWord, flw.getWord(), 4); + + flwOffset += flwOffsetDirection; + + if (flwOffset <= 0) { + flwOffset = 0; + flwOffsetDirection = 1; + } + else if (flwOffset > display.digits() -4) { + flwOffset = 3; + flwOffsetDirection = -1; + } + + rtc.tick(); +} + +void tenth_tick() +{ + rtc.tenth_tick(); +} + +void counterTest() +{ + display.cls(); + for (uint16_t i = 0; i < 200; i++) { + display.printf("cnt %3d", i); + wait(0.01); + } +} + +void timeAndDateTest() +{ + uint8_t hour = 15; + uint8_t min = 59; + uint8_t sec = 55; + + display.cls(); + for (uint8_t i = 0; i < 7; i++) { + display.printf("%02d-%02d-%02d", hour, min, sec); + sec++; + if (sec == 60) { sec = 0; min++; } + if (min == 60) { min = 0; hour++; } + wait(1.0); + } + + display.printf("%02d-%02d-%02d Monday 2014-05-12", hour, min, sec); + + while (!display.scrollFinished()) { + display.scroll(); + wait(0.25); + } + + display.resetScroll(); + + for (uint8_t i = 0; i < 5; i++) { + display.printf("%2d-%02d-%02d", hour, min, sec); + sec++; + if (sec == 60) { sec = 0; min++; } + if (min == 60) { min = 0; hour++; } + wait(1.0); + } + +} + +int dayOfWeek(int y, int m, int d) +{ + static const int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; + y -= m < 3; + return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7; +} + +void welcomeMessage() +{ + const char* buf = " Akafugu VFD Modular Clock"; + + display.cls(); + display.printf(buf); + + // scroll forward + while (!display.scrollFinished()) { + display.scroll(); + led = !led; + wait(0.20); + } + + display.cls(); +} + +// helper function for handling time/alarm setting +uint8_t handleTimeSetting(uint8_t setting, uint8_t min, uint8_t max, + bool backButton, bool nextButton) +{ + if (backButton) { + if (setting == 0) { + setting = max; + } + else { + setting--; + } + } + else if (nextButton) { + if (setting == max) { + setting = 0; + } + else { + setting++; + } + } + + return setting; +} + +const uint32_t MENU_TIMEOUT = 3 * 10; // each cycle 0.1s, 3 secs total +struct tm* tm_; + +int main() +{ + bool suppress_button_sound = false; + uint8_t button3_holdcounter = 0; + uint32_t menu_countdown = MENU_TIMEOUT; + + // Enable extra memory banks + LPC_SYSCON->SYSAHBCLKCTRL |= 0x1 << 26; // RAM1 + LPC_SYSCON->SYSAHBCLKCTRL |= 0x1 << 27; // USBSRAM + + // PWM + // See: http://developer.mbed.org/forum/mbed/topic/3276/ + /* + LPC_CT16B0->TCR = 2; + LPC_CT16B0->PR = 19; + LPC_CT16B0->MR0 = 48000; // 1ms + LPC_CT16B0->TCR = 1; + */ + + BUTTON_STATE buttons; + + rtc.begin(); + init_prefs(); + + // FLW initialization + tm_ = rtc.getTime(); + + flw.begin(tm_->tm_min * 60 + tm_->tm_sec); + flw.setCensored(true); + + memset(flwWord, 0, 5); + haveEEPROM = flw.hasEeprom(); + if (haveEEPROM) + strncpy(flwWord, flw.getWord(), 4); + else + memset(flwWord, 0, 4); + + led = 0; + + initialize_buttons(); + menu.setDigits(display.digits()); + + blanker.attach_us(&blank_tick, 100); + multiplexer.attach_us(&multiplex_tick, 2000); + button_ticker.attach_us(&button_tick, 5000); + rtc_ticker.attach(&rtc_tick, 1.0); + tenth_ticker.attach(&tenth_tick, 0.1); + + PrefsData* prefs = get_prefs(); + display.setBrightness(prefs->prefs.brightness); + + wait(1.0); + //welcomeMessage(); + led = 0; + +#ifdef HAVE_GPS + gps_init(); +#endif // HAVE_GPS + + /* + // button test + while (1) { + get_button_state(&buttons); + + display.printf("%d-%d-%d %d", buttons.b1_keydown, buttons.b2_keydown, buttons.b3_keydown, get_keystatus()); + wait(0.1); + } + */ + + while (1) { + get_button_state(&buttons); + prefs = get_prefs(); + + led = 0; + +#ifdef HAVE_GPS + // Read GPS and update RTC if needed + if (gpsDataReady()) { + char* nmea = gpsNMEA(); + bool error = false; + bool fix = false; + + if ( prefs->prefs.gps && strncmp( nmea, "$GPRMC,", 7 ) == 0 ) { + time_t t = parseGPSdata(nmea, error, fix, prefs->prefs.gps_tzh, prefs->prefs.gps_tzm); + time_t delta = t - gps_last_update; + + if (fix && !error && delta > 60) { + led = 1; + struct tm *tmp = localtime(&t); + rtc.setTime(tmp); + gps_last_update = t; + } + } + } +#endif // HAVE_GPS + + if (buttons.b1_keyup || buttons.b2_keyup || buttons.b3_keyup) { + if (suppress_button_sound || g_alarming) { + suppress_button_sound = false; + buttons.b1_keyup = buttons.b2_keyup = buttons.b3_keyup = 0; + } + else { + //piezo.play('g'); + } + + button3_holdcounter = 0; + g_alarming = false; + } + + switch (g_clock_state) { + case STATE_CLOCK: + { + tm_ = rtc.getTime(); + + // button 1 triggers menu + if (buttons.b1_keyup) { + //display.incBrightness(); + display.printf("%s ", menu.reset()); + display.setAlarmIndicator(false); + display.setGPSIndicator(false); + set_extra_prefs(tm_->tm_year+1900, tm_->tm_mon+1, tm_->tm_mday); + g_clock_state = STATE_MENU; + menu_countdown = MENU_TIMEOUT; + buttons.b1_keyup = 0; + break; + } + + // Button 2 cycles through display mode + if (buttons.b2_keyup) { + display.toggleTimeMode(); + buttons.b2_keyup = 0; + } + + // Button 3 toggles FLW mode + if (buttons.b3_keyup && haveEEPROM) { + buttons.b3_keyup = 0; + button3_holdcounter = 0; + g_clock_state = STATE_FLW; + } + + // Hold button 3 to set alarm + if (buttons.b3_repeat) { + button3_holdcounter++; + buttons.b3_repeat = 0; + suppress_button_sound = true; + + if (button3_holdcounter == 6) { + g_alarm_on = !g_alarm_on; + piezo.play('a'); + } + } + + // Enter auto date + if (prefs->prefs.auto_date && tm_->tm_sec == 50) { + display.cls(); + display.printTimeLong(tm_, rtc.getTenths()); + g_clock_state = STATE_AUTO_DATE; + } + else if (haveEEPROM && prefs->prefs.flw > 0 && tm_->tm_sec == 30) { + g_clock_state = STATE_AUTO_FLW; + } + else { + display.printTime(tm_, rtc.getTenths()); + } + } + break; + case STATE_MENU: + { + // button 1 goes to next menu item + if (buttons.b1_keyup) { + display.printf("%s ", menu.next()); + menu_countdown = MENU_TIMEOUT; + buttons.b1_keyup = 0; + } + + // Button 2 selects menu item + if (buttons.b2_keyup || buttons.b2_repeat) { + bool setTime, setAlarm; + + display.printf("%8s ", menu.select(setTime, setAlarm)); + + if (setTime) { + menu.leave(); + display.setBlinkMode(VFDDisplay::Hours); + display.blink(true); + tm_ = rtc.getTime(); // get time from RTC to use as basis for settings + tm_->tm_sec = 0; + g_clock_state = STATE_SET_CLOCK_HH; + } + else if (setAlarm) { + menu.leave(); + display.setBlinkMode(VFDDisplay::Minutes); + display.blink(true); + tm_ = rtc.getAlarm(); + g_clock_state = STATE_SET_ALARM_HH; + } + + menu_countdown = MENU_TIMEOUT; + buttons.b2_keyup = 0; + } + // Button 3 leaves menu + else if (buttons.b3_keyup) { + buttons.b3_keyup = 0; + menu.leave(); + g_clock_state = STATE_CLOCK; + } + + menu_countdown--; + + // exit menu if unused for preset time + if (menu_countdown == 0) { + menu.leave(); + g_clock_state = STATE_CLOCK; + } + + // If g_clock_state has changed, we are leaving the menu, update parameters + if (g_clock_state == STATE_CLOCK) { + display.setGPSIndicator(true); + + tm_ = rtc.getTime(); + int year, month, day; + + get_extra_prefs(year, month, day); + tm_->tm_year = year - 1900; + tm_->tm_mon = month-1; + tm_->tm_mday = day; + + tm_->tm_wday = dayOfWeek(year, month, day); + + rtc.setTime(tm_); + + wait(0.05); + display.setGPSIndicator(false); + } + } + break; + case STATE_AUTO_DATE: + { + // exit scroll if any button is pressed + if (buttons.b1_keyup || buttons.b2_keyup || buttons.b3_keyup) { + display.cls(); + g_clock_state = STATE_CLOCK; + + buttons.b1_keyup = 0; + buttons.b2_keyup = 0; + buttons.b3_keyup = 0; + } + + static uint8_t scroll_cnt = 0; + + if (display.scrollFinished()) { + display.cls(); + g_clock_state = STATE_CLOCK; + } + else { + if (++scroll_cnt == 2) { + display.scroll(); + scroll_cnt = 0; + } + } + } + break; + case STATE_SET_CLOCK_HH: + { + display.printTimeSet(tm_); + + if (buttons.b1_repeat || buttons.b2_repeat) { + display.blink(false); + tm_->tm_hour = handleTimeSetting(tm_->tm_hour, 0, 23, buttons.b1_repeat, buttons.b2_repeat); + buttons.b1_repeat = 0; + buttons.b2_repeat = 0; + } + if (buttons.b1_keyup) { + display.blink(true); + tm_->tm_hour = handleTimeSetting(tm_->tm_hour, 0, 23, true, false); + buttons.b1_keyup = 0; + } + else if (buttons.b2_keyup) { // Button 2 + display.blink(true); + tm_->tm_hour = handleTimeSetting(tm_->tm_hour, 0, 23, false, true); + buttons.b2_keyup = 0; + } + else if (buttons.b3_keyup) { // Button 3 moves to minute setting + display.setBlinkMode(VFDDisplay::Minutes); + g_clock_state = STATE_SET_CLOCK_MM; + buttons.b3_keyup = 0; + } + } + break; + case STATE_SET_CLOCK_MM: + { + display.printTimeSet(tm_); + + if (buttons.b1_repeat || buttons.b2_repeat) { + display.blink(false); + tm_->tm_min = handleTimeSetting(tm_->tm_min, 0, 59, buttons.b1_repeat, buttons.b2_repeat); + buttons.b1_repeat = 0; + buttons.b2_repeat = 0; + } + if (buttons.b1_keyup) { + display.blink(true); + tm_->tm_min = handleTimeSetting(tm_->tm_min, 0, 59, true, false); + buttons.b1_keyup = 0; + } + else if (buttons.b2_keyup) { // Button 2 + display.blink(true); + tm_->tm_min = handleTimeSetting(tm_->tm_min, 0, 59, false, true); + buttons.b2_keyup = 0; + } + else if (buttons.b3_keyup) { // Button 3 moves to second setting + display.setBlinkMode(VFDDisplay::Seconds); + g_clock_state = STATE_SET_CLOCK_SS; + buttons.b3_keyup = 0; + } + } + break; + case STATE_SET_CLOCK_SS: + { + display.printTimeSet(tm_); + + if (buttons.b1_repeat || buttons.b2_repeat) { + display.blink(false); + tm_->tm_sec = handleTimeSetting(tm_->tm_sec, 0, 59, buttons.b1_repeat, buttons.b2_repeat); + buttons.b1_repeat = 0; + buttons.b2_repeat = 0; + } + if (buttons.b1_keyup) { + display.blink(true); + tm_->tm_sec = handleTimeSetting(tm_->tm_sec, 0, 59, true, false); + buttons.b1_keyup = 0; + } + else if (buttons.b2_keyup) { // Button 2 + display.blink(true); + tm_->tm_sec = handleTimeSetting(tm_->tm_sec, 0, 59, false, true); + buttons.b2_keyup = 0; + } + else if (buttons.b3_keyup) { // Button 3 moves to minute setting + display.setBlinkMode(VFDDisplay::Full); + display.blink(false); + rtc.setTime(tm_); + g_clock_state = STATE_CLOCK; + buttons.b3_keyup = 0; + } + } + break; + case STATE_SET_ALARM_HH: + { + display.printTimeSet(tm_, false); + + if (buttons.b1_repeat || buttons.b2_repeat) { + display.blink(false); + tm_->tm_hour = handleTimeSetting(tm_->tm_hour, 0, 23, buttons.b1_repeat, buttons.b2_repeat); + buttons.b1_repeat = 0; + buttons.b2_repeat = 0; + } + if (buttons.b1_keyup) { + display.blink(true); + tm_->tm_hour = handleTimeSetting(tm_->tm_hour, 0, 23, true, false); + buttons.b1_keyup = 0; + } + else if (buttons.b2_keyup) { // Button 2 + display.blink(true); + tm_->tm_hour = handleTimeSetting(tm_->tm_hour, 0, 23, false, true); + buttons.b2_keyup = 0; + } + else if (buttons.b3_keyup) { // Button 3 moves to minute setting + display.setBlinkMode(VFDDisplay::Seconds); + g_clock_state = STATE_SET_ALARM_MM; + buttons.b3_keyup = 0; + } + } + break; + case STATE_SET_ALARM_MM: + { + display.printTimeSet(tm_, false); + + if (buttons.b1_repeat || buttons.b2_repeat) { + display.blink(false); + tm_->tm_min = handleTimeSetting(tm_->tm_min, 0, 59, buttons.b1_repeat, buttons.b2_repeat); + buttons.b1_repeat = 0; + buttons.b2_repeat = 0; + } + if (buttons.b1_keyup) { + display.blink(true); + tm_->tm_min = handleTimeSetting(tm_->tm_min, 0, 59, true, false); + buttons.b1_keyup = 0; + } + else if (buttons.b2_keyup) { // Button 2 + display.blink(true); + tm_->tm_min = handleTimeSetting(tm_->tm_min, 0, 59, false, true); + buttons.b2_keyup = 0; + } + else if (buttons.b3_keyup) { // Button 3 moves to minute setting + display.setBlinkMode(VFDDisplay::Full); + display.blink(false); + rtc.setAlarm(tm_->tm_hour, tm_->tm_min, 0); + g_clock_state = STATE_CLOCK; + buttons.b3_keyup = 0; + } + } + break; + case STATE_AUTO_FLW: + { + tm_ = rtc.getTime(); + + if (tm_->tm_sec >= 37) { + g_clock_state = STATE_CLOCK; + } + } + // fall-through + case STATE_FLW: + { + // exit if any button is pressed + if (buttons.b1_keyup || buttons.b2_keyup || buttons.b3_keyup) { + display.cls(); + g_clock_state = STATE_CLOCK; + + buttons.b1_keyup = 0; + buttons.b2_keyup = 0; + buttons.b3_keyup = 0; + } + + if (flwOffset == 0) + display.printf("%s ", flwWord); + else + display.printf("%*s" "%s ", flwOffset, " ", flwWord); + } + break; + default: + break; + } + + if (g_alarm_on && rtc.checkAlarm()) { + g_alarming = true; + } + + display.setAlarmIndicator(g_alarm_on); + display.setGPSIndicator(g_alarming); + + if (g_alarming) { + piezo.play('g'); + } + + wait(0.1); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/4fc01daae5a5 \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menu.cpp Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,215 @@ +/* + * 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 "global.h" +#include "menu.h" + +char menu_buf[MAX_BUF]; + +///////////////////////////////////////////////////////// +// MenuItemValue + +MenuItemValue::MenuItemValue(int32_t min, int32_t max) +: m_min(min) +, m_max(max) +, m_value(min) +, m_activated(false) +{ +} + +int32_t MenuItemValue::getValue() +{ + return m_value; +} + +int32_t MenuItemValue::incrementValue() +{ + if (m_activated) { + m_value++; + if (m_value > m_max) m_value = m_min; + } + else { + m_activated = true; + } + + return m_value; +} + +void MenuItemValue::resetActive() +{ + m_activated = false; +} + +///////////////////////////////////////////////////////// +// MenuItem + +MenuItem::MenuItem(const char* shortName, const char* longName, bool onOff, PREFS pref) +: m_onOff(onOff) +, m_pref(pref) +{ + strncpy(m_shortName, shortName, 4); + strncpy(m_longName, longName, 8); + m_menuItemValue = new MenuItemValue(0, 1); +} + +MenuItem::MenuItem(const char* shortName, bool onOff, PREFS pref) +: m_onOff(onOff) +, m_pref(pref) +{ + strncpy(m_shortName, shortName, 4); + m_longName[0] = 0; + m_menuItemValue = new MenuItemValue(0, 1); +} + +MenuItem::MenuItem(const char* shortName, const char* longName, int32_t min, int32_t max, PREFS pref) +: m_onOff(false) +, m_pref(pref) +{ + strncpy(m_shortName, shortName, 4); + strncpy(m_longName, longName, 8); + m_menuItemValue = new MenuItemValue(min, max); +} + +MenuItem::MenuItem(const char* shortName, int32_t min, int32_t max, PREFS pref) +: m_onOff(false) +, m_pref(pref) +{ + strncpy(m_shortName, shortName, 4); + m_longName[0] = 0; + m_menuItemValue = new MenuItemValue(min, max); +} + +const char* MenuItem::getName(uint8_t digits) const +{ + if (m_longName[0] == 0) return m_shortName; + return digits <= 4 ? m_shortName : m_longName; +} + +extern DigitalOut led; + +const char* MenuItem::selectValue(uint8_t digits) const +{ + uint32_t value = m_menuItemValue->incrementValue(); + + // special handling + if (m_pref == PREF_GPS_TZM) { + value *= 15; + } + + if (m_onOff) { + if (value == 1) + snprintf(menu_buf, MAX_BUF-1, "%s", "on"); + else + snprintf(menu_buf, MAX_BUF-1, "%s", "off"); + } + else if (m_pref == PREF_FLW) { + if (value == 0) + snprintf(menu_buf, MAX_BUF-1, "%s", "off"); + if (value == 1) + snprintf(menu_buf, MAX_BUF-1, "%s", "on"); + else if (value == 2) + snprintf(menu_buf, MAX_BUF-1, "%s", "full"); + } + else { + // special handling for year/month/day - these values are not stored in the eeprom + // but go directly to the RTC chip + if (m_pref == PREF_YEAR) { + set_year(value); + } + else if (m_pref == PREF_MONTH) { + set_month(value); + } + else if (m_pref == PREF_DAY) { + set_day(value); + } + + snprintf(menu_buf, MAX_BUF-1, "%d", value); + } + + // save to prefs + if (m_pref != PREF_NULL) { + set_pref(m_pref, value); + } + + return menu_buf; +} + +void MenuItem::resetActive() const +{ + m_menuItemValue->resetActive(); +} + +const MenuItem menu1("TIME", "SET TIME", true, PREF_SET_TIME); +const MenuItem menu2("ALRM", "SET ALR", true, PREF_SET_ALARM); +const MenuItem menu3("24H", true, PREF_24H); +const MenuItem menu4("BRIT", "BRITE", 2, 10, PREF_BRIGHTNESS); +const MenuItem menu5("YEAR", 2014, 2075, PREF_YEAR); +const MenuItem menu6("MNTH", "MONTH", 1, 12, PREF_MONTH); +const MenuItem menu7("DAY", 1, 31, PREF_DAY); +const MenuItem menu8("GPS", true, PREF_GPS); +const MenuItem menu9("TZH", "GPS TZH", -12, 14, PREF_GPS_TZH); +const MenuItem menu10("TZM", "GPS TZM", 0, 3, PREF_GPS_TZM); +const MenuItem menu11("ADTE", "AUTODATE", true, PREF_AUTODATE); +const MenuItem menu12("FLW", 0, 2, PREF_FLW); + +#ifdef HAVE_GPS +#define ITEMS 12 +const MenuItem* menuItems[] = { &menu1, &menu2, &menu3, &menu4, &menu5, &menu6, &menu7, &menu8, &menu9, &menu10, &menu11, &menu12 }; +#else +#define ITEMS 8 +const MenuItem* menuItems[] = { &menu1, &menu2, &menu3, &menu4, &menu5, &menu6, &menu7, &menu12 }; +#endif + +Menu::Menu() + : m_position(0) + , m_size(ITEMS) + , m_digits(8) +{ +} + +const char* Menu::reset() +{ + m_position = 0; + return menuItems[m_position]->getName(m_digits); +} + +const char* Menu::next() +{ + menuItems[m_position]->resetActive(); + + m_position++; + if (m_position >= ITEMS) m_position = 0; + + return menuItems[m_position]->getName(m_digits); +} + +const char* Menu::select(bool& enterSetTime, bool& enterSetAlarm) +{ + enterSetTime = enterSetAlarm = false; + + if (menuItems[m_position]->isSetTimeTrigger()) + enterSetTime = true; + + if (menuItems[m_position]->isSetAlarmTrigger()) + enterSetAlarm = true; + + return menuItems[m_position]->selectValue(m_digits); +} + +void Menu::leave() +{ + menuItems[m_position]->resetActive(); + save_prefs(); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menu.h Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,86 @@ +/* + * 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. + * + */ + +#ifndef MENU_H_ +#define MENU_H_ + +// menu type +// +// custom routine (set time, set alarm) +// on-off (24h on, off) +// array of possible values (flw: off, on, full) +// range (brite 1-10) +// +// values always stored as numbers + +#define MAX_BUF 9 + +#include "prefs.h" + +class MenuItemValue { +private: + int32_t m_min; + int32_t m_max; + int32_t m_value; + bool m_activated; +public: + MenuItemValue(int32_t min, int32_t max); + + int32_t getValue(); + int32_t incrementValue(); + void resetActive(); +}; + +class MenuItem { +private: + char m_shortName[5]; + char m_longName[MAX_BUF]; + bool m_onOff; + PREFS m_pref; + + MenuItemValue* m_menuItemValue; +public: + MenuItem(const char* shortName, const char* longName, bool onOff, PREFS pref); + MenuItem(const char* shortName, bool onOff, PREFS pref); + + MenuItem(const char* shortName, const char* longName, int32_t min, int32_t max, PREFS pref); + MenuItem(const char* shortName, int32_t min, int32_t max, PREFS pref); + + const char* getName(uint8_t digits) const; + const char* selectValue(uint8_t digits) const; + void resetActive() const; + + bool isSetTimeTrigger() const { return m_pref == PREF_SET_TIME; } + bool isSetAlarmTrigger() const { return m_pref == PREF_SET_ALARM; } +}; + +class Menu { +private: + uint8_t m_position; + uint8_t m_size; + uint8_t m_digits; + +public: + Menu(); + + void setDigits(uint8_t digits) { m_digits = digits; } + + const char* reset(); + const char* next(); + const char* select(bool& enterSetTime, bool& enterSetAlarm); + void leave(); +}; + +#endif // MENU_H_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/prefs.cpp Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,185 @@ +/* + * 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 "global.h" + +#include "prefs.h" +#include "DipCortex-EEprom.h" + +#include "VFDDisplay.h" +#include "IV18Display.h" +#include "flw.h" + +const uint8_t sig0 = 0x42; +const uint8_t sig1 = 0x66; + +PrefsData prefs_data; + +extern IV18Display display; +extern DigitalOut led; +extern FourLetterWord flw; + +static int s_pref_year; +static int s_pref_month; +static int s_pref_day; + +uint8_t crc8(const void *vptr, int len) +{ + const uint8_t *data = static_cast<const uint8_t *>(vptr); + unsigned crc = 0; + int i, j; + + for (j = len; j; j--, data++) { + crc ^= (*data << 8); + for(i = 8; i; i--) { + if (crc & 0x8000) + crc ^= (0x1070 << 3); + crc <<= 1; + } + } + + return (uint8_t)(crc >> 8); +} + +void init_prefs() +{ + IAP_Init(); + + IAP_Eeprom_Read(0, prefs_data.buf, PREFS_SIZE); + + bool initialized = false; + + // check if eeprom has been initialized + if (prefs_data.buf[0] == sig0 && prefs_data.buf[1] == sig1) { + // check crc + uint8_t calc_crc = crc8(prefs_data.buf, PREFS_SIZE-1); + + if (calc_crc == prefs_data.prefs.crc) + initialized = true; + } + + if (!initialized) { + memset(prefs_data.buf, 0, PREFS_SIZE); + prefs_data.prefs.sig0 = sig0; + prefs_data.prefs.sig1 = sig1; + prefs_data.prefs.disp_24h = 1; + prefs_data.prefs.brightness = 10; + prefs_data.prefs.dots = 1; + prefs_data.prefs.gps = 1; + prefs_data.prefs.gps_tzh = 9; // Tokyo, Japan + prefs_data.prefs.gps_tzm = 0; + prefs_data.prefs.auto_date = 1; + prefs_data.prefs.flw = 0; + prefs_data.prefs.crc = crc8(prefs_data.buf, PREFS_SIZE-1); + + IAP_Eeprom_Write(0, prefs_data.buf, PREFS_SIZE); + } +} + +void save_prefs() +{ + uint8_t calc_crc = crc8(prefs_data.buf, PREFS_SIZE-1); + + if (calc_crc != prefs_data.prefs.crc) { + prefs_data.prefs.crc = calc_crc; + IAP_Eeprom_Write(0, prefs_data.buf, PREFS_SIZE); + } +} + +PrefsData* get_prefs() +{ + if (prefs_data.prefs.flw == 2) + flw.setCensored(false); + else + flw.setCensored(true); + + return &prefs_data; +} + +void set_year(int year) +{ + s_pref_year = year; +} + +void set_month(int month) +{ + s_pref_month = month; +} + +void set_day(int day) +{ + s_pref_day = day; +} + + +void set_extra_prefs(int year, int month, int day) +{ + s_pref_year = year; + s_pref_month = month; + s_pref_day = day; +} + +void get_extra_prefs(int& year, int& month, int& day) +{ + year = s_pref_year; + month = s_pref_month; + day = s_pref_day; +} + +void set_pref(PREFS pref, uint32_t value) +{ + switch (pref) { + case PREF_24H: + prefs_data.prefs.disp_24h = value; + break; + case PREF_BRIGHTNESS: + prefs_data.prefs.brightness = value; + display.setBrightness(value); + break; + case PREF_ALARM: + prefs_data.prefs.alarm = value; + break; + case PREF_YEAR: + s_pref_year = value; + break; + case PREF_MONTH: + s_pref_month = value; + break; + case PREF_DAY: + s_pref_day = value; + break; + case PREF_DOTS: + prefs_data.prefs.dots = value; + break; + case PREF_GPS: + prefs_data.prefs.gps = value; + break; + case PREF_GPS_TZH: + prefs_data.prefs.gps_tzh = value; + break; + case PREF_GPS_TZM: + prefs_data.prefs.gps_tzm = value; + break; + case PREF_AUTODATE: + prefs_data.prefs.auto_date = value; + break; + case PREF_FLW: + prefs_data.prefs.flw = value; + break; + default: + break; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/prefs.h Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,74 @@ +/* + * 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. + * + */ + +#ifndef PREFS_H_ +#define PREFS_H_ + +const uint8_t PREFS_SIZE = 12; + +enum PREFS { + PREF_24H = 0, + PREF_BRIGHTNESS, + PREF_ALARM, + PREF_DOTS, + PREF_GPS, + PREF_GPS_TZH, + PREF_GPS_TZM, + PREF_AUTODATE, + PREF_FLW, + // Prefs that are not saved to eeprom + PREF_SET_TIME, + PREF_SET_ALARM, + PREF_YEAR, + PREF_MONTH, + PREF_DAY, + PREF_NULL // placeholder +}; + +struct prefs_t { + uint8_t sig0; // expected 0x42 + uint8_t sig1; // expected 0x66 + uint8_t disp_24h; + uint8_t brightness; + uint8_t alarm; + uint8_t dots; + uint8_t gps; + int8_t gps_tzh; + uint8_t gps_tzm; + uint8_t auto_date; + uint8_t flw; + uint8_t crc; +}; + +union PrefsData { + uint8_t buf[12]; + prefs_t prefs; +}; + +void init_prefs(); +void save_prefs(); +PrefsData* get_prefs(); + +// prefs that are not saved to EEPROM +void set_year(int year); +void set_month(int month); +void set_day(int day); + +void set_extra_prefs(int year, int month, int day); +void get_extra_prefs(int& year, int& month, int& day); + +void set_pref(PREFS pref, uint32_t value); + +#endif // PREFS_H_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vfd_modular_clock.uvopt Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,204 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no" ?> +<ProjectOpt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_opt.xsd"> + + <SchemaVersion>1.0</SchemaVersion> + + <Header>### uVision Project, (C) Keil Software</Header> + + <Extensions> + <cExt>*.c</cExt> + <aExt>*.s*; *.src; *.a*</aExt> + <oExt>*.obj</oExt> + <lExt>*.lib</lExt> + <tExt>*.txt; *.h; *.inc</tExt> + <pExt>*.plm</pExt> + <CppX>*.cpp</CppX> + </Extensions> + + <DaveTm> + <dwLowDateTime>0</dwLowDateTime> + <dwHighDateTime>0</dwHighDateTime> + </DaveTm> + + <Target> + <TargetName>LPC1347</TargetName> + <ToolsetNumber>0x4</ToolsetNumber> + <ToolsetName>ARM-ADS</ToolsetName> + <TargetOption> + <CLKADS>12000000</CLKADS> + <OPTTT> + <gFlags>1</gFlags> + <BeepAtEnd>1</BeepAtEnd> + <RunSim>1</RunSim> + <RunTarget>0</RunTarget> + </OPTTT> + <OPTHX> + <HexSelection>1</HexSelection> + <FlashByte>65535</FlashByte> + <HexRangeLowAddress>0</HexRangeLowAddress> + <HexRangeHighAddress>0</HexRangeHighAddress> + <HexOffset>0</HexOffset> + </OPTHX> + <OPTLEX> + <PageWidth>79</PageWidth> + <PageLength>66</PageLength> + <TabStop>8</TabStop> + <ListingPath>.\build\</ListingPath> + </OPTLEX> + <ListingPage> + <CreateCListing>1</CreateCListing> + <CreateAListing>1</CreateAListing> + <CreateLListing>1</CreateLListing> + <CreateIListing>0</CreateIListing> + <AsmCond>1</AsmCond> + <AsmSymb>1</AsmSymb> + <AsmXref>0</AsmXref> + <CCond>1</CCond> + <CCode>0</CCode> + <CListInc>0</CListInc> + <CSymb>0</CSymb> + <LinkerCodeListing>0</LinkerCodeListing> + </ListingPage> + <OPTXL> + <LMap>1</LMap> + <LComments>1</LComments> + <LGenerateSymbols>1</LGenerateSymbols> + <LLibSym>1</LLibSym> + <LLines>1</LLines> + <LLocSym>1</LLocSym> + <LPubSym>1</LPubSym> + <LXref>0</LXref> + <LExpSel>0</LExpSel> + </OPTXL> + <OPTFL> + <tvExp>1</tvExp> + <tvExpOptDlg>0</tvExpOptDlg> + <IsCurrentTarget>1</IsCurrentTarget> + </OPTFL> + <CpuCode>8</CpuCode> + <Books> + <Book> + <Number>0</Number> + <Title>User Manual</Title> + <Path>DATASHTS\PHILIPS\LPC13UXX_15_16_17_45_46_47_UM.pdf</Path> + </Book> + <Book> + <Number>1</Number> + <Title>Technical Reference Manual</Title> + <Path>datashts\arm\cortex_m3\r2p1\DDI0337I_CORTEXM3_R2P1_TRM.PDF</Path> + </Book> + <Book> + <Number>2</Number> + <Title>Generic User Guide</Title> + <Path>datashts\arm\cortex_m3\r2p1\DUI0552A_CORTEX_M3_DGUG.PDF</Path> + </Book> + </Books> + <DllOpt> + <SimDllName>SARMCM3.DLL</SimDllName> + <SimDllArguments></SimDllArguments> + <SimDlgDllName>DCM.DLL</SimDlgDllName> + <SimDlgDllArguments>-pCM3</SimDlgDllArguments> + <TargetDllName>SARMCM3.DLL</TargetDllName> + <TargetDllArguments></TargetDllArguments> + <TargetDlgDllName>TCM.DLL</TargetDlgDllName> + <TargetDlgDllArguments>-pCM3</TargetDlgDllArguments> + </DllOpt> + <DebugOpt> + <uSim>0</uSim> + <uTrg>1</uTrg> + <sLdApp>1</sLdApp> + <sGomain>1</sGomain> + <sRbreak>1</sRbreak> + <sRwatch>1</sRwatch> + <sRmem>1</sRmem> + <sRfunc>1</sRfunc> + <sRbox>1</sRbox> + <tLdApp>1</tLdApp> + <tGomain>1</tGomain> + <tRbreak>1</tRbreak> + <tRwatch>1</tRwatch> + <tRmem>1</tRmem> + <tRfunc>0</tRfunc> + <tRbox>1</tRbox> + <tRtrace>0</tRtrace> + <sRunDeb>0</sRunDeb> + <sLrtime>0</sLrtime> + <nTsel>9</nTsel> + <sDll></sDll> + <sDllPa></sDllPa> + <sDlgDll></sDlgDll> + <sDlgPa></sDlgPa> + <sIfile></sIfile> + <tDll></tDll> + <tDllPa></tDllPa> + <tDlgDll></tDlgDll> + <tDlgPa></tDlgPa> + <tIfile></tIfile> + <pMon>BIN\ULP2CM3.DLL</pMon> + </DebugOpt> + <TargetDriverDllRegistry> + <SetRegEntry> + <Number>0</Number> + <Key>ULP2CM3</Key> + <Name>-UP1048454 -O206 -S0 -C0 -P00 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO18 -TC10000000 -TP18 -TDX0 -TDD0 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO15 -FD10000000 -FC800 -FN1 -FF0LPC1xxx_64 -FS00 -FL010000</Name> + </SetRegEntry> + <SetRegEntry> + <Number>0</Number> + <Key>CMSIS_AGDI</Key> + <Name>-X"MBED CMSIS-DAP" -UA000000001 -O206 -S0 -C0 -N00("ARM CoreSight SW-DP") -D00(0BB11477) -L00(0) -FO15 -FD10000000 -FC800 -FN1 -FF0LPC1xxx_32 -FS00 -FL08000</Name> + </SetRegEntry> + </TargetDriverDllRegistry> + <Breakpoint/> + <DebugFlag> + <trace>0</trace> + <periodic>0</periodic> + <aLwin>0</aLwin> + <aCover>0</aCover> + <aSer1>0</aSer1> + <aSer2>0</aSer2> + <aPa>0</aPa> + <viewmode>0</viewmode> + <vrSel>0</vrSel> + <aSym>0</aSym> + <aTbox>0</aTbox> + <AscS1>0</AscS1> + <AscS2>0</AscS2> + <AscS3>0</AscS3> + <aSer3>0</aSer3> + <eProf>0</eProf> + <aLa>0</aLa> + <aPa1>0</aPa1> + <AscS4>0</AscS4> + <aSer4>0</aSer4> + <StkLoc>0</StkLoc> + <TrcWin>0</TrcWin> + <newCpu>0</newCpu> + <uProt>0</uProt> + </DebugFlag> + <LintExecutable></LintExecutable> + <LintConfigFile></LintConfigFile> + </TargetOption> + </Target> + + <Group> + <GroupName>src</GroupName> + <tvExp>1</tvExp> + <tvExpOptDlg>0</tvExpOptDlg> + <cbSel>0</cbSel> + <File> + <GroupNumber>1</GroupNumber> + <FileNumber>1</FileNumber> + <FileType>8</FileType> + <tvExp>0</tvExp> + <Focus>0</Focus> + <ColumnNumber>0</ColumnNumber> + <tvExpOptDlg>0</tvExpOptDlg> + <TopLine>1</TopLine> + <CurrentLine>2</CurrentLine> + <bDave2>0</bDave2> + <PathWithFileName>main.cpp</PathWithFileName> + <FilenameWithoutPath>main.cpp</FilenameWithoutPath> + </File> + </Group> + +</ProjectOpt> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vfd_modular_clock.uvproj Mon Feb 09 13:40:46 2015 +0000 @@ -0,0 +1,506 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no" ?> +<Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_proj.xsd"> + + <SchemaVersion>1.1</SchemaVersion> + + <Header>###This file was automagically generated by mbed.org. For more information, see http://mbed.org/handbook/Exporting-To-Uvision </Header> + + <Targets> + <Target> + <TargetName>LPC1347</TargetName> + <ToolsetNumber>0x4</ToolsetNumber> + <ToolsetName>ARM-ADS</ToolsetName> + <TargetOption> + <TargetCommonOption> + <Device>LPC1347</Device> + <Vendor>NXP (founded by Philips)</Vendor> + <Cpu>IRAM(0x10000000-0x10001FFF) IRAM2(0x20000000-0x200007FF) IROM(0-0xFFFF) CLOCK(12000000) CPUTYPE("Cortex-M3")</Cpu> + <FlashUtilSpec></FlashUtilSpec> + <StartupFile>"STARTUP\NXP\LPC13Uxx\startup_LPC13Uxx.s" ("NXP LPC13Uxx Startup Code")</StartupFile> + <FlashDriverDll>UL2CM3(-O4303 -S0 -C0 -FO7 -FD10000000 -FC800 -FN1 -FF0LPC1xxx_64 -FS00 -FL010000)</FlashDriverDll> + <DeviceId>6286</DeviceId> + <RegisterFile>LPC13Uxx.h</RegisterFile> + <MemoryEnv></MemoryEnv> + <Cmp></Cmp> + <Asm></Asm> + <Linker></Linker> + <OHString></OHString> + <InfinionOptionDll></InfinionOptionDll> + <SLE66CMisc></SLE66CMisc> + <SLE66AMisc></SLE66AMisc> + <SLE66LinkerMisc></SLE66LinkerMisc> + <SFDFile>SFD\NXP\LPC13Uxx\LPC13Uxx.sfr</SFDFile> + <UseEnv>0</UseEnv> + <BinPath></BinPath> + <IncludePath></IncludePath> + <LibPath></LibPath> + <RegisterFilePath>NXP\LPC13Uxx\</RegisterFilePath> + <DBRegisterFilePath>NXP\LPC13Uxx\</DBRegisterFilePath> + <TargetStatus> + <Error>0</Error> + <ExitCodeStop>0</ExitCodeStop> + <ButtonStop>0</ButtonStop> + <NotGenerated>0</NotGenerated> + <InvalidFlash>1</InvalidFlash> + </TargetStatus> + <OutputDirectory>.\build\</OutputDirectory> + <OutputName>vfd_modular_clock</OutputName> + <CreateExecutable>1</CreateExecutable> + <CreateLib>0</CreateLib> + <CreateHexFile>0</CreateHexFile> + <DebugInformation>1</DebugInformation> + <BrowseInformation>1</BrowseInformation> + <ListingPath>.\build\</ListingPath> + <HexFormatSelection>1</HexFormatSelection> + <Merge32K>0</Merge32K> + <CreateBatchFile>0</CreateBatchFile> + <BeforeCompile> + <RunUserProg1>0</RunUserProg1> + <RunUserProg2>0</RunUserProg2> + <UserProg1Name></UserProg1Name> + <UserProg2Name></UserProg2Name> + <UserProg1Dos16Mode>0</UserProg1Dos16Mode> + <UserProg2Dos16Mode>0</UserProg2Dos16Mode> + </BeforeCompile> + <BeforeMake> + <RunUserProg1>0</RunUserProg1> + <RunUserProg2>0</RunUserProg2> + <UserProg1Name></UserProg1Name> + <UserProg2Name></UserProg2Name> + <UserProg1Dos16Mode>0</UserProg1Dos16Mode> + <UserProg2Dos16Mode>0</UserProg2Dos16Mode> + </BeforeMake> + <AfterMake> + <RunUserProg1>1</RunUserProg1> + <RunUserProg2>0</RunUserProg2> + <UserProg1Name>fromelf --bin -o build\vfd_modular_clock_LPC1347.bin build\vfd_modular_clock.axf</UserProg1Name> + <UserProg2Name></UserProg2Name> + <UserProg1Dos16Mode>0</UserProg1Dos16Mode> + <UserProg2Dos16Mode>0</UserProg2Dos16Mode> + </AfterMake> + <SelectedForBatchBuild>0</SelectedForBatchBuild> + <SVCSIdString></SVCSIdString> + </TargetCommonOption> + <CommonProperty> + <UseCPPCompiler>0</UseCPPCompiler> + <RVCTCodeConst>0</RVCTCodeConst> + <RVCTZI>0</RVCTZI> + <RVCTOtherData>0</RVCTOtherData> + <ModuleSelection>0</ModuleSelection> + <IncludeInBuild>1</IncludeInBuild> + <AlwaysBuild>0</AlwaysBuild> + <GenerateAssemblyFile>0</GenerateAssemblyFile> + <AssembleAssemblyFile>0</AssembleAssemblyFile> + <PublicsOnly>0</PublicsOnly> + <StopOnExitCode>3</StopOnExitCode> + <CustomArgument></CustomArgument> + <IncludeLibraryModules></IncludeLibraryModules> + </CommonProperty> + <DllOption> + <SimDllName>SARMCM3.DLL</SimDllName> + <SimDllArguments></SimDllArguments> + <SimDlgDll>DCM.DLL</SimDlgDll> + <SimDlgDllArguments>-pCM3</SimDlgDllArguments> + <TargetDllName>SARMCM3.DLL</TargetDllName> + <TargetDllArguments></TargetDllArguments> + <TargetDlgDll>TCM.DLL</TargetDlgDll> + <TargetDlgDllArguments>-pCM3</TargetDlgDllArguments> + </DllOption> + <DebugOption> + <OPTHX> + <HexSelection>1</HexSelection> + <HexRangeLowAddress>0</HexRangeLowAddress> + <HexRangeHighAddress>0</HexRangeHighAddress> + <HexOffset>0</HexOffset> + <Oh166RecLen>16</Oh166RecLen> + </OPTHX> + <Simulator> + <UseSimulator>0</UseSimulator> + <LoadApplicationAtStartup>1</LoadApplicationAtStartup> + <RunToMain>1</RunToMain> + <RestoreBreakpoints>1</RestoreBreakpoints> + <RestoreWatchpoints>1</RestoreWatchpoints> + <RestoreMemoryDisplay>1</RestoreMemoryDisplay> + <RestoreFunctions>1</RestoreFunctions> + <RestoreToolbox>1</RestoreToolbox> + <LimitSpeedToRealTime>0</LimitSpeedToRealTime> + </Simulator> + <Target> + <UseTarget>1</UseTarget> + <LoadApplicationAtStartup>1</LoadApplicationAtStartup> + <RunToMain>1</RunToMain> + <RestoreBreakpoints>1</RestoreBreakpoints> + <RestoreWatchpoints>1</RestoreWatchpoints> + <RestoreMemoryDisplay>1</RestoreMemoryDisplay> + <RestoreFunctions>0</RestoreFunctions> + <RestoreToolbox>1</RestoreToolbox> + </Target> + <RunDebugAfterBuild>0</RunDebugAfterBuild> + <TargetSelection>9</TargetSelection> + <SimDlls> + <CpuDll></CpuDll> + <CpuDllArguments></CpuDllArguments> + <PeripheralDll></PeripheralDll> + <PeripheralDllArguments></PeripheralDllArguments> + <InitializationFile></InitializationFile> + </SimDlls> + <TargetDlls> + <CpuDll></CpuDll> + <CpuDllArguments></CpuDllArguments> + <PeripheralDll></PeripheralDll> + <PeripheralDllArguments></PeripheralDllArguments> + <InitializationFile></InitializationFile> + <Driver>BIN\ULP2CM3.DLL</Driver> + </TargetDlls> + </DebugOption> + <Utilities> + <Flash1> + <UseTargetDll>1</UseTargetDll> + <UseExternalTool>0</UseExternalTool> + <RunIndependent>0</RunIndependent> + <UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging> + <Capability>1</Capability> + <DriverSelection>4101</DriverSelection> + </Flash1> + <bUseTDR>0</bUseTDR> + <Flash2>BIN\ULP2CM3.DLL</Flash2> + <Flash3>"" ()</Flash3> + <Flash4></Flash4> + </Utilities> + <TargetArmAds> + <ArmAdsMisc> + <GenerateListings>0</GenerateListings> + <asHll>1</asHll> + <asAsm>1</asAsm> + <asMacX>1</asMacX> + <asSyms>1</asSyms> + <asFals>1</asFals> + <asDbgD>1</asDbgD> + <asForm>1</asForm> + <ldLst>0</ldLst> + <ldmm>1</ldmm> + <ldXref>1</ldXref> + <BigEnd>0</BigEnd> + <AdsALst>1</AdsALst> + <AdsACrf>1</AdsACrf> + <AdsANop>0</AdsANop> + <AdsANot>0</AdsANot> + <AdsLLst>1</AdsLLst> + <AdsLmap>1</AdsLmap> + <AdsLcgr>1</AdsLcgr> + <AdsLsym>1</AdsLsym> + <AdsLszi>1</AdsLszi> + <AdsLtoi>1</AdsLtoi> + <AdsLsun>1</AdsLsun> + <AdsLven>1</AdsLven> + <AdsLsxf>1</AdsLsxf> + <RvctClst>0</RvctClst> + <GenPPlst>0</GenPPlst> + <AdsCpuType>"Cortex-M3"</AdsCpuType> + <RvctDeviceName></RvctDeviceName> + <mOS>0</mOS> + <uocRom>0</uocRom> + <uocRam>0</uocRam> + <hadIROM>1</hadIROM> + <hadIRAM>1</hadIRAM> + <hadXRAM>0</hadXRAM> + <uocXRam>0</uocXRam> + <RvdsVP>0</RvdsVP> + <hadIRAM2>0</hadIRAM2> + <hadIROM2>0</hadIROM2> + <StupSel>8</StupSel> + <useUlib>0</useUlib> + <EndSel>0</EndSel> + <uLtcg>0</uLtcg> + <RoSelD>3</RoSelD> + <RwSelD>3</RwSelD> + <CodeSel>0</CodeSel> + <OptFeed>0</OptFeed> + <NoZi1>0</NoZi1> + <NoZi2>0</NoZi2> + <NoZi3>0</NoZi3> + <NoZi4>0</NoZi4> + <NoZi5>0</NoZi5> + <Ro1Chk>1</Ro1Chk> + <Ro2Chk>0</Ro2Chk> + <Ro3Chk>0</Ro3Chk> + <Ir1Chk>1</Ir1Chk> + <Ir2Chk>0</Ir2Chk> + <Ra1Chk>0</Ra1Chk> + <Ra2Chk>0</Ra2Chk> + <Ra3Chk>0</Ra3Chk> + <Im1Chk>1</Im1Chk> + <Im2Chk>0</Im2Chk> + <OnChipMemories> + <Ocm1> + <Type>0</Type> + <StartAddress>0x0</StartAddress> + <Size>0x0</Size> + </Ocm1> + <Ocm2> + <Type>0</Type> + <StartAddress>0x0</StartAddress> + <Size>0x0</Size> + </Ocm2> + <Ocm3> + <Type>0</Type> + <StartAddress>0x0</StartAddress> + <Size>0x0</Size> + </Ocm3> + <Ocm4> + <Type>0</Type> + <StartAddress>0x0</StartAddress> + <Size>0x0</Size> + </Ocm4> + <Ocm5> + <Type>0</Type> + <StartAddress>0x0</StartAddress> + <Size>0x0</Size> + </Ocm5> + <Ocm6> + <Type>0</Type> + <StartAddress>0x0</StartAddress> + <Size>0x0</Size> + </Ocm6> + <IRAM> + <Type>0</Type> + <StartAddress>0x10000000</StartAddress> + <Size>0x1000</Size> + </IRAM> + <IROM> + <Type>1</Type> + <StartAddress>0x0</StartAddress> + <Size>0x8000</Size> + </IROM> + <XRAM> + <Type>0</Type> + <StartAddress>0x0</StartAddress> + <Size>0x0</Size> + </XRAM> + <OCR_RVCT1> + <Type>0</Type> + <StartAddress>0x0</StartAddress> + <Size>0x0</Size> + </OCR_RVCT1> + <OCR_RVCT2> + <Type>0</Type> + <StartAddress>0x0</StartAddress> + <Size>0x0</Size> + </OCR_RVCT2> + <OCR_RVCT3> + <Type>0</Type> + <StartAddress>0x0</StartAddress> + <Size>0x0</Size> + </OCR_RVCT3> + <OCR_RVCT4> + <Type>1</Type> + <StartAddress>0x0</StartAddress> + <Size>0x8000</Size> + </OCR_RVCT4> + <OCR_RVCT5> + <Type>0</Type> + <StartAddress>0x0</StartAddress> + <Size>0x0</Size> + </OCR_RVCT5> + <OCR_RVCT6> + <Type>0</Type> + <StartAddress>0x0</StartAddress> + <Size>0x0</Size> + </OCR_RVCT6> + <OCR_RVCT7> + <Type>0</Type> + <StartAddress>0x0</StartAddress> + <Size>0x0</Size> + </OCR_RVCT7> + <OCR_RVCT8> + <Type>0</Type> + <StartAddress>0x0</StartAddress> + <Size>0x0</Size> + </OCR_RVCT8> + <OCR_RVCT9> + <Type>0</Type> + <StartAddress>0x10000000</StartAddress> + <Size>0x1000</Size> + </OCR_RVCT9> + <OCR_RVCT10> + <Type>0</Type> + <StartAddress>0x0</StartAddress> + <Size>0x0</Size> + </OCR_RVCT10> + </OnChipMemories> + <RvctStartVector></RvctStartVector> + </ArmAdsMisc> + <Cads> + <interw>1</interw> + <Optim>1</Optim> + <oTime>0</oTime> + <SplitLS>0</SplitLS> + <OneElfS>0</OneElfS> + <Strict>0</Strict> + <EnumInt>0</EnumInt> + <PlainCh>0</PlainCh> + <Ropi>0</Ropi> + <Rwpi>0</Rwpi> + <wLevel>0</wLevel> + <uThumb>0</uThumb> + <VariousControls> + <MiscControls>--gnu --no_rtti </MiscControls> + <Define> TARGET_LPC1347, TARGET_M3, TARGET_CORTEX_M, TARGET_NXP, TARGET_LPC13XX, TOOLCHAIN_ARM_STD, TOOLCHAIN_ARM, __CORTEX_M3, ARM_MATH_CM3, MBED_BUILD_TIMESTAMP=1421281797.28, __MBED__=1, __ASSERT_MSG, </Define> + <Undefine></Undefine> + <IncludePath> .; beep; DipCortex-EEprom; RTC; mbed; mbed/TARGET_LPC1347; mbed/TARGET_LPC1347/TOOLCHAIN_ARM_STD; mbed/TARGET_LPC1347/TARGET_NXP; mbed/TARGET_LPC1347/TARGET_NXP/TARGET_LPC13XX; </IncludePath> + </VariousControls> + </Cads> + <Aads> + <interw>1</interw> + <Ropi>0</Ropi> + <Rwpi>0</Rwpi> + <thumb>0</thumb> + <SplitLS>0</SplitLS> + <SwStkChk>0</SwStkChk> + <NoWarn>0</NoWarn> + <VariousControls> + <MiscControls></MiscControls> + <Define></Define> + <Undefine></Undefine> + <IncludePath></IncludePath> + </VariousControls> + </Aads> + <LDads> + <umfTarg>0</umfTarg> + <Ropi>0</Ropi> + <Rwpi>0</Rwpi> + <noStLib>0</noStLib> + <RepFail>1</RepFail> + <useFile>0</useFile> + <TextAddressRange>0x00000000</TextAddressRange> + <DataAddressRange>0x10000000</DataAddressRange> + <ScatterFile>mbed/TARGET_LPC1347/TOOLCHAIN_ARM_STD/LPC1347.sct</ScatterFile> + <IncludeLibs></IncludeLibs> + <IncludeLibsPath></IncludeLibsPath> + <Misc> + + mbed/TARGET_LPC1347/TOOLCHAIN_ARM_STD/retarget.o + + mbed/TARGET_LPC1347/TOOLCHAIN_ARM_STD/startup_LPC13xx.o + + mbed/TARGET_LPC1347/TOOLCHAIN_ARM_STD/board.o + + mbed/TARGET_LPC1347/TOOLCHAIN_ARM_STD/cmsis_nvic.o + + mbed/TARGET_LPC1347/TOOLCHAIN_ARM_STD/system_LPC13Uxx.o + + mbed/TARGET_LPC1347/TOOLCHAIN_ARM_STD/sys.o + + mbed/TARGET_LPC1347/TOOLCHAIN_ARM_STD/mbed.ar + + </Misc> + <LinkerInputFile></LinkerInputFile> + <DisabledWarnings></DisabledWarnings> + </LDads> + </TargetArmAds> + </TargetOption> + <Groups> + + <Group> + <GroupName>src</GroupName> + <Files> + + <File> + <FileName>button.cpp</FileName> + <FileType>8</FileType> + <FilePath>button.cpp</FilePath> + + </File> + + <File> + <FileName>prefs.cpp</FileName> + <FileType>8</FileType> + <FilePath>prefs.cpp</FilePath> + + </File> + + <File> + <FileName>main.cpp</FileName> + <FileType>8</FileType> + <FilePath>main.cpp</FilePath> + + </File> + + <File> + <FileName>gps.cpp</FileName> + <FileType>8</FileType> + <FilePath>gps.cpp</FilePath> + + </File> + + <File> + <FileName>VFDDisplay.cpp</FileName> + <FileType>8</FileType> + <FilePath>VFDDisplay.cpp</FilePath> + + </File> + + <File> + <FileName>menu.cpp</FileName> + <FileType>8</FileType> + <FilePath>menu.cpp</FilePath> + + </File> + + <File> + <FileName>font_7seg.cpp</FileName> + <FileType>8</FileType> + <FilePath>font_7seg.cpp</FilePath> + + </File> + + <File> + <FileName>IV18Display.cpp</FileName> + <FileType>8</FileType> + <FilePath>IV18Display.cpp</FilePath> + + </File> + + <File> + <FileName>beep.cpp</FileName> + <FileType>8</FileType> + <FilePath>beep/beep.cpp</FilePath> + + </File> + + <File> + <FileName>DipCortex-EEprom.cpp</FileName> + <FileType>8</FileType> + <FilePath>DipCortex-EEprom/DipCortex-EEprom.cpp</FilePath> + + </File> + + <File> + <FileName>rtc.cpp</FileName> + <FileType>8</FileType> + <FilePath>RTC/rtc.cpp</FilePath> + + </File> + + <File> + <FileName>ds3231m.cpp</FileName> + <FileType>8</FileType> + <FilePath>RTC/ds3231m.cpp</FilePath> + + </File> + + <File> + <FileName>ds1302.cpp</FileName> + <FileType>8</FileType> + <FilePath>RTC/ds1302.cpp</FilePath> + + </File> + + </Files> + </Group> + + </Groups> + </Target> + </Targets> + +</Project> \ No newline at end of file