/* FILE / DATE: dcf_sim_.c / 2010-05-03 DESCRIPTION: DCF Simulator MICRO-PROCESSOR: PIC16F886 COMPILER: B Knudsen Cc5x C-compiler - not ANSI-C EXTERNAL HW: LCD Display 4 pushbuttons with LED Rotating encoder 2 LEDs DESIGNER: Hans Sundgren CREDIT: William Sandqvist for rotary encoder reading RAM usage: 172 bytes (12 local), 196 bytes free CODE WORDS: 4450 code words (54 %) CHIP CONNECTIONS ******************************************** _________ ________ | \/ | | 16F886 | -|RE3 1 28 RB7|- Output.PULSE--<-|RA0 2 27 RB6|- LCD.backlight-<-|RA1 3 26 RB5|-<-Btn.START LED.SET------<-|RA2 4 25 RB4|-<-Btn.TRANSMIT LED.VIEW-----<-|RA3 5 24 RB3|-<-Btn.VIEW LED.TRANSMIT-<-|RA4 6 23 RB2|-<-Btn.SET LED.START----<-|RA5 7 22 RB1|-<-Encoder.A GND---|Vss 8 21 RB0|-<-Encoder.B LED.one-<-|RA7 9 20 Vdd|---+5V LED.null-<-|RA6 10 19 Vss|---GND XTAL 32,768 kHz---|OSO 11 18 RC7|->-LCD.D7 XTAL 32,768 kHz---|OSI 12 17 RC6|->-LCD.D6 LCD.RS-<-|RC2 13 16 RC5|->-LCD.D5 LCD.EN-<-|RC3 14 15 RC4|->-LCD.D4 |___________________| DISPLAY VIEWS, 1 -> 2 -> 3 -> 4 -> 1 -> ... _____________________________________________ | View | Shows | LCD backlight | |------|----------------------|---------------| | 1 | Time and bit display | No | | 2 | Time and bit display | Yes | | 3 | Bit overview | Yes | | 4 | Bit description | Yes | |______|______________________|_______________| PUSH-BUTTONS ____________________________________________________________ | Button | Color | Pin | Lamp, pin: lit | |------------|--------|-----|--------------------------------| | Start/Stop | Green | RB5 | RA5 | On during clock running | | Transmit | Red | RB4 | RA4 | Blink on output signal | | View | Blue | RB3 | RA3 | Blink when pressed | | Set | Yellow | RB2 | RA2 | On during set clock | |____________|________|_____|________________________________| LED INDICATORS ____________________________________________________________ | LED | Color | Pin | Lit during... | |------------|--------|-----|--------------------------------| | 0 | Yellow | RA7 | Output = 0 | | | | | Decrement during clock setting | | | | | | | 1 | Green | RA6 | Output = 1 | | | | | Increment during clock setting | |____________|________|_____|________________________________| ROTATING DIALS ____________________________________________________________ | Type | Function | Pin | |----------------|-------------------------------------------| | Rotary encoder | Increase/decrease clock setting | RB0/RB1 | |________________|_________________________________|_________| PROGRAM OVERVIEW ******************************************* Interrupt: 1 Hz ---------------------------------------- | If start_mode = 1 | | Update clock (step up one second) | | Output pulse-value | | Update display | | Check buttons | | If VIEW-button | | Step up display mode 0->1->2->3->0 | | If SET-button | | Setting > 0 | | Stop interrupt, jump out to setting sequence | -------------------------------------------------------- Interrupt: Rotary encoder, during "set clock" ---------- | Read encoder | | If increase | | up = 1 and blink LED0 | | If decrease | | down = 1 and blink LED1 | -------------------------------------------------------- Main --------------------------------------------------- | Initialization | | Read stored time from EEPROM | | Interrupt is active 1 Hz, but the clock is stopped | | Loop | | Check START-button | | If START-button | | Toggle start_mode | -------------------------------------------------------- Set clock sequence ------------------------------------ | Disable 1 Hz interrupt | | Enable rotary encoder interrupt | | Step through set sequence, read rotary encoder | | Update and display time values | | Store set time in EEPROM | | Enable 1 Hz interrupt | -------------------------------------------------------- */ /* _______________________________ INCLUDE __________________________ */ #include "16F886.h" #include "int16CXX.H" /* _______________________________ CONFIGURATION ____________________ */ #pragma config WDTE=0, FOSC=4, PWRTE=1 /* _______________________________ GLOBAL VARIABLES _________________ */ bit start_mode; // Clock running or not char display_mode; // Display alternatives: 1=clock, 2=overview, 3=details char set_mode; // Setting mode; 0=no set, 1=min, 2=hour, 3=day, etc. char tick_pos; // Current position in the bit stream char tick_pos_1; char tick_pos_10; char bit_val; char transit; // Store rotary encoder transitions bit up; bit down; bit tranmit_on; char stored_time[14]; // Time data stored in EEPROM char START_pressed; char SET_pressed; char no_of_ones; // Counter of total no. of ones for parity bit setting char first; bit trans_mode; //Transmitting on/off //#pragma rambank 1 #pragma rambank 1 char bit_value[60]; // The one-minute bit stream to output int sec1; // DCF77 clock, second units int sec10; // DCF77 clock, second tens int min1; // DCF77 clock, minute units int min10; // DCF77 clock, minute tens int hour1; // DCF77 clock, hour units int hour10; // DCF77 clock, hour tens int day1; // DCF77 clock, day units int day10; // DCF77 clock, day tens int month1; // DCF77 clock, month units int month10; // DCF77 clock, month tens int year1; // DCF77 clock, year units (200X) int year10; // DCF77 clock, year tens (20x0) char weekday; // DCF77 clock, day of week, starting Monday char dst; // DCF77 clock, Daylights saving time on/off #pragma rambank 2 char c_pos[60]; /* _______________________________ FUNCTIONS _____________ */ void delay(char millisec); void delay10(char n); void delay250us(char millisec); void get_bitvalue(); // Get the value of the current bit void output_bitvalue(); // Send the bitvalue to LED and output void set_bitvalue (void); // Set bit stream once per minute based on clock void pixel_def( void ); void lcd_init( void ); // Initalize the LCD display void lcd_putchar( char data ); // Display one character on LCD void lcd_putint( char value ); void lcd_strobe( void ); void lcd_startmsg(void); void lcd_string ( char * s ); void lcd_command ( char cmd ); void put_eedata( void ); void get_eedata( void ); void update_display_mode_3 (void); void update_display_mode_4 (void); char text1( char ); char text2( char ); char text3( char ); char text4( char ); char text5( char ); char text6( char ); char text11( char ); char text12( char ); char text13( char ); char text14( char ); char text15( char ); char text16( char ); char text17( char ); void blink_led (char id); void blink_null (void); void blink_one (void); void update_clock (void); void update_minutes (void); void set_clock (void); void blink_empty (char digits); void blink_digits (char dig1, char dig2); void check_btn (void); void display_time(void); void display_weekday (void); void display_dst (void); void display_3_pos (void); void display_4_pos (void); //void display_bit_range (char s1, char s2, char t1, char t2); interrupt int_server(void); #define CLEAR 0b0.0000001 #define POS_1_0 0b1.0000000 // LCD display line 1 #define POS_1_1 0b1.0000001 #define POS_1_4 0b1.0000100 #define POS_1_5 0b1.0000101 #define POS_1_6 0b1.0000110 #define POS_1_7 0b1.0000111 #define POS_1_8 0b1.0001000 #define POS_1_9 0b1.0001001 #define POS_1_10 0b1.0001010 #define POS_1_11 0b1.0001011 #define POS_1_12 0b1.0001100 #define POS_1_13 0b1.0001101 #define POS_1_14 0b1.0001110 #define POS_1_15 0b1.0001111 #define POS_1_16 0b1.0010000 #define POS_1_17 0b1.0010001 #define POS_1_18 0b1.0010010 #define POS_1_19 0b1.0010011 #define POS_2_0 0b1.1000000 // LCD display line 2 #define POS_2_1 0b1.1000001 #define POS_2_2 0b1.1000010 #define POS_2_3 0b1.1000011 #define POS_2_4 0b1.1000100 #define POS_2_5 0b1.1000101 #define POS_2_6 0b1.1000110 #define POS_2_7 0b1.1000111 #define POS_2_8 0b1.1001000 #define POS_2_9 0b1.1001001 #define POS_2_10 0b1.1001010 #define POS_2_11 0b1.1001011 #define POS_2_12 0b1.1001100 #define POS_2_13 0b1.1001101 #define POS_2_14 0b1.1001110 #define POS_2_15 0b1.1001111 #define POS_2_16 0b1.1010000 #define POS_2_17 0b1.1010001 #define POS_2_18 0b1.1010010 #define POS_2_19 0b1.1010011 #define POS_3_0 0b1.0010100 // LCD display line 3 #define POS_3_1 0b1.0010101 #define POS_3_2 0b1.0010110 #define POS_3_3 0b1.0010111 #define POS_3_4 0b1.0011000 #define POS_3_5 0b1.0011001 #define POS_3_6 0b1.0011010 #define POS_3_7 0b1.0011011 #define POS_3_8 0b1.0011100 #define POS_3_9 0b1.0011101 #define POS_3_10 0b1.0011110 #define POS_3_11 0b1.0011111 #define POS_3_12 0b1.0100000 #define POS_3_13 0b1.0100001 #define POS_3_14 0b1.0100010 #define POS_3_15 0b1.0100011 #define POS_3_16 0b1.0100100 #define POS_3_17 0b1.0100101 #define POS_3_18 0b1.0100110 #define POS_3_19 0b1.0100111 #define POS_4_0 0b1.1010100 // LCD display line 4 #define POS_4_1 0b1.1010101 #define POS_4_2 0b1.1010110 #define POS_4_3 0b1.1010111 #define POS_4_4 0b1.1011000 #define POS_4_5 0b1.1011001 #define POS_4_6 0b1.1011010 #define POS_4_7 0b1.1011011 #define POS_4_8 0b1.1011100 #define POS_4_9 0b1.1011101 #define POS_4_10 0b1.1011110 #define POS_4_11 0b1.1011111 #define POS_4_12 0b1.1100000 #define POS_4_13 0b1.1100001 #define POS_4_14 0b1.1100010 #define POS_4_15 0b1.1100011 #define POS_4_16 0b1.1100100 #define POS_4_17 0b1.1100101 #define POS_4_18 0b1.1100110 #define POS_4_19 0b1.1100111 /* _______________________________ I/O PIN DEFINITIONS ____ */ #pragma bit PULSE @ PORTA.0 // Output signal to transmitter #pragma bit T_ON @ PORTB.7 // Transmitter on/off #pragma bit LED0 @ PORTA.6 // LED indication "zero" #pragma bit LED1 @ PORTA.7 // LED indication "one" #pragma bit START @ PORTB.5 // Button START #pragma bit TRANS @ PORTB.4 // Button TRANMIT #pragma bit VIEW @ PORTB.3 // Button VIEW #pragma bit SET @ PORTB.2 // Button SET #pragma bit ROTA @ PORTB.0 // Rotating encoder A #pragma bit ROTB @ PORTB.1 // Rotating encoder B #pragma bit I_START @ PORTA.5 // Indicator START button #pragma bit I_TRANS @ PORTA.4 // Indicator TRANMIT button #pragma bit I_VIEW @ PORTA.3 // Indicator VIEW button #pragma bit I_SET @ PORTA.2 // Indicator SET button #pragma bit D4 @ PORTC.4 // LCD control #pragma bit D5 @ PORTC.5 // LCD control #pragma bit D6 @ PORTC.6 // LCD control #pragma bit D7 @ PORTC.7 // LCD control #pragma bit RS @ PORTC.2 // LCD control #pragma bit EN @ PORTC.3 // LCD control #pragma bit LCDLI @ PORTA.1 // LCD backlight //#pragma bit start_VIEW @ 0x20.7 #pragma origin 4 // Special interrupt instruction CC5x #pragma sharedAllocation // Special interrupt instruction CC5x /* _______________________________ INTERRUPT FUNCTION _______________________ */ interrupt int_server(void) { int_save_registers // W, STATUS (and PCLATH) char sv_FSR = FSR; if(RBIF==1) // Rotary encoder interrupt { char m; char k; for (m=0; m<2; m++) // debounce { for (k=0; k<250; k++) { nop(); nop(); } } transit.0=ROTB; // Read rotary encoder value transit.1=ROTA; if( transit==0b00.01 ) // Compare value { down=1; } if( transit==0b01.00 ) { up=1; } transit.2=transit.0; // Replace old with new transit.3=transit.1; RBIF = 0; // Reset interrupt flag } if (TMR1IF) // Timer 1 overflow interrupt { TMR1IF = 0; // Reset overflow flag TMR1H = 0x80; // Reset counter TMR1L = 0x00; if (start_mode == 0) { trans_mode=0; // Switch off transmitter I_TRANS=0; T_ON = 0; I_START=1; delay250us(10); I_START=0; delay250us(30); // Blink Start button (x3) I_START=1; delay250us(10); I_START=0; delay250us(30); I_START=1; delay250us(10); I_START=0; delay250us(30); } if (start_mode ==1) { I_START=1; tick_pos++; // Step up tick_pos one second (not needed ) sec1++; // Step up one second update_clock (); // Main clock updated every second if (tick_pos == 60) { tick_pos = 0; } if (tick_pos == 0) { set_bitvalue(); // Set all 60 bits with initial valu first=0; if (display_mode == 3) { update_display_mode_3 (); //Update bits } } output_bitvalue(); // Binary pulse on output } if (display_mode == 1 || display_mode == 2) { display_time (); } check_btn (); } FSR = sv_FSR; int_restore_registers // W, STATUS (and PCLATH) } /* _______________________________ MAIN FUNCTION start ________________________ */ void main(void) { ANSEL=0; // Initialisation to enable PORTC as digital I/O ANSELH=0; CM1CON0 = 0 ; // Behvös den?? CM2CON0 = 0 ; // Behvös den?? TRISA = 0b0000.0000; // Port A are all outputs TRISC= 0b0000.0000; // Port C are all outputs TRISB = 0b0011.1111; // Port B are mainly inputs OPTION.7 = 0; WPUB.0 = 1; // Weak pullup Encoder.B input WPUB.1 = 1; // Weak pullup Encoder.A input WPUB.2 = 1; // Weak pullup SET input WPUB.3 = 1; // Weak pullup VIEW input WPUB.4 = 1; // Weak pullup TRANSMIT input WPUB.5 = 1; // Weak pullup START input IOCB.0 = 1; // Enable interrupt on Encoder.B IOCB.1 = 1; // Enable interrupt on Encoder.A IOCB.4 = 1; // Enable interrupt on TRANSMIT input I_START = 0; I_TRANS = 0; I_VIEW = 0; I_SET = 0; LED0 = 0; LED1 = 0; RBIE = 1; /* local enable */ get_eedata (); // Get the string of time data from EEPROM ... hour10 =stored_time[0]; // ... and store in variables hour1 =stored_time[1]; min10 =stored_time[2]; min1 =stored_time[3]; dst =stored_time[6]; year10 =stored_time[7]; year1 =stored_time[8]; month10 =stored_time[9]; month1 =stored_time[10]; day10 =stored_time[11]; day1 =stored_time[12]; weekday =stored_time[13]; sec1 = 9; // Sec = 59 sec10 = 5; // Sec = 59 tick_pos = 59; display_mode = 1; // Show clock at start + bitvalue trans_mode = 0; // Transmitter off set_mode = 0; first=0; lcd_init(); // Initiate the LCD LCDLI=0; // No backlight to start with char i; lcd_command (POS_1_0); for(i=0; i<16; i++) lcd_putchar(text1(i)); // display start text 1 delay10(100); lcd_command (POS_2_0); for(i=0; i<16; i++) lcd_putchar(text2(i)); // display start text 2 delay10(100); lcd_command (CLEAR); // Clear display /* Definition of interrupt 1 Hz 00.xx.x.x.x.x -- xx.00.x.x.x.x Prescale 1/1 xx.xx.1.x.x.x TMR1-oscillator is on xx.xx.x.0.x.x - (clock input synchronization) xx.xx.x.x.1.x Use external clock 32.768 xx.xx.x.x.x.1 TIMER1 is ON */ T1CON = 0b00.00.1.1.1.1 ; /* CCPR = CLOSC * Timer1Period = 32768*1 = 32768 */ /* CCPR = 32768 = 0x8000 CCPR1H = 0x80, CCPR1L = 0x00 */ //TMR1IE = 0; //TMR1H = 0x00; //Short time to initial interrupt after Start //TMR1L = 0x11; /* Timer1Period is now 1 s */ //********************************************************* //lcd_command (0b0000.0000); // Clear display //next interrupt should start at 00 start_mode = 0; PULSE = 1; LED0 = 0; LED1 = 0; TMR1H = 0xEE; //Short time to initial interrupt after Start TMR1L = 0x00; TMR1IE = 1; // Enable TMR1 interrupt GIE = 1; // Interrupts allowed PEIE = 1; //display_time (); /* while (1) // Infinite loop, wait for button press { while( START == 0) ; // Button pressed { start_mode = ! start_VIEW; // Start/stop signal delay10 (1); if (display_mode == 1 || display_mode == 2) { //lcd_command (CLEAR); // Clear display } } while( START == 1 ) ; // Button up { delay10 (1); //lcd_command (CLEAR); // Clear display } } */ while (1) { if (START==0) { if (START_pressed==0) { start_mode = ! start_mode; // Start/stop signal delay10 (1); if (display_mode == 1 || display_mode == 2) { lcd_command (POS_1_0); for(i=0; i<20; i++) lcd_putchar(text5(i)); // display start text 1 lcd_command (POS_2_18); // move cursor to "line 2, position 18 lcd_putchar('='); } START_pressed=1; //if (start_mode == 1) //{ // TMR1IE = 1; // Enable TMR1 interrupt //} //else //{ // TMR1IE = 0; // Enable TMR1 interrupt //} } if (START==1) { delay10 (1); START_pressed=0; } } /* if (SET == 0) // Button pressed { if (SET_pressed==0) { set_mode = 1; // Step up display VIEW delay10 (1); lcd_command(0b0000.1100); /* display on, cursor off, blink off */ lcd_command (CLEAR); // Clear display' SET_pressed=1; if (set_VIEW==1) { set_clock (); } } //set_clock (); // Funkar inte if (SET==1) { delay10 (1); SET_pressed=0; } } */ } //} //if (VIEW==down) //{ } /* ________________________ TRANSMITTER OUTPUT FUNCTION start ________________________ */ void output_bitvalue(void) { char i; bit_val = bit_value[tick_pos]; if (display_mode == 1 || display_mode == 2) { tick_pos_1 = tick_pos%10; // Get the single digit for display tick_pos_10 = tick_pos/10; // Get the single digit for display lcd_command (0b1001.0010); // reposition to "line 2, position 18 lcd_putchar(48+tick_pos_10); lcd_putchar(48+tick_pos_1); } if (display_mode == 3) { update_display_mode_3 (); } if (display_mode == 4) // Endast markering tillsivdare { update_display_mode_4 (); } if (bit_val == 0) { if (display_mode == 1 || display_mode == 2) { lcd_command (0b1101.0011); // reposition to "line 1, position 19 lcd_putchar('0'); } LED0 = 1; if (trans_mode==1) { I_TRANS = 0; } PULSE = 0; delay10(10); LED0 = 0; if (trans_mode==1) { I_TRANS = 1; } PULSE = 1; } if (bit_val == 1) { if (display_mode == 1 || display_mode == 2) { lcd_command (0b1101.0011); // reposition to "line 1, position 19 //lcd_command (0b1000.0000); // reposition to "line 1, position 0 //RS = 1; // LCD in character-VIEW lcd_putchar('1'); } LED1 = 1; if (trans_mode==1) { I_TRANS = 0; } PULSE = 0; delay10(20); LED1 = 0; if (trans_mode==1) { I_TRANS = 1; } PULSE = 1; } if (bit_val == 9) //last second before new minute, no pulse { if (display_mode == 1 || display_mode == 2) { //RS = 0; // LCD in command-VIEW //lcd_putchar( 0b00000010 ); //Cursor hoME //RS = 1; // LCD in character-VIEW lcd_command (0b1101.0011); // reposition to "line 1, position 19 lcd_putchar('-'); } //PULSE2 = 0; } } void check_btn (void) { char i; if (VIEW == 0) // Button pressed { I_VIEW=1; delay250us(30); I_VIEW=0; // Blink Start button display_mode = display_mode+1; // Step up display VIEW //lcd_command (CLEAR); // Clear display first=0; if (display_mode==5) { display_mode = 1; } if (display_mode == 1 || display_mode == 2) { lcd_command (POS_1_0); for(i=0; i<20; i++) lcd_putchar(text5(i)); // display start text 1 lcd_command (POS_2_0); for(i=0; i<20; i++) lcd_putchar(text6(i)); // display start text 1 lcd_command (POS_2_18); // move cursor to "line 2, position 18 lcd_putchar('='); lcd_command(0b0000.1100); /* display on, cursor off, blink off */ //lcd_command (CLEAR); // Clear display' LCDLI=0; } if (display_mode == 2 || display_mode == 3 || display_mode == 4) { LCDLI=1; } if (display_mode==4) { //LCDLI=1; lcd_command(0b0000.1100); /* display on, cursor off, blink off */ lcd_command (CLEAR); // Clear display' } } if (SET == 0) // Button pressed { if (start_mode == 0) { set_mode = 1; // Step up display VIEW lcd_command(0b0000.1100); /* display on, cursor off, blink off */ lcd_command (CLEAR); // Clear display' //set_clock (); // Funkar inte if (set_mode==1) { set_clock (); } } } if (TRANS == 0) // Button pressed { if (start_mode == 1) // Transmit button active only during run { I_TRANS=1; delay250us(30); I_TRANS=0; // Blink Start button trans_mode = ! trans_mode; // Start/stop signal delay10 (1); if (trans_mode == 1) { I_TRANS=1; T_ON = 1; } if (trans_mode == 0) { I_TRANS=0; T_ON = 0; } } } /* if (SET == 0) // Button pressed { if (SET_pressed==0) { set_mode = 1; // Step up display VIEW delay10 (1); lcd_command(0b0000.1100); /* display on, cursor off, blink off */ lcd_command (CLEAR); // Clear display' SET_pressed=1; if (set_VIEW==1) { set_clock (); } } //set_clock (); // Funkar inte if (SET==1) { delay10 (1); SET_pressed=0; } } */ } void blink_empty (char digits) // Erases a number of LCD characters { char i; for (i=0; i<digits; i++) { lcd_putchar(' '); } delay10 (30); // Wait 500 ms } void blink_digits (char dig1, char dig2) // Erases a number of LCD characters { lcd_putchar(48+dig1); // 48 = 0011.0000 lcd_putchar(48+dig2); delay10(20); } /* ________________________ DCF77 CLOCK start ________________________ */ void update_clock (void) // Updates the clock data with one second { if (sec1>9) { sec1 = 0; sec10++; } if (sec10 > 5) { sec10 = 0; min1++; } update_minutes (); } void update_minutes (void) // Clock over minute > hour > day > month > year { if(min1>9) { min1 = 0; min10++; } if(min10>5) { min10 = 0; hour1++; } if(hour1>9) { hour1 = 0; hour10++; } if(hour10 >2){ hour10 = 0; } if(hour10 >=2 && hour1>3) { hour1 = 0; hour10 = 0; day1++; } if(day1>9){ day1 = 0; day10++; } if(day10 >=2 && day1>1) { day1 = 1; day10 = 0; month1++; } if(month1>9) { month1 = 0; month10++; } if(month10 >=1 && month1>2) { month1 = 1; month10 = 0; year1++; } if(year1>9) { year1 = 0; year10++; } } void display_time ( void ) { lcd_command (POS_3_0); // reposition to line 1 lcd_putint(hour10); lcd_putint(hour1); lcd_putchar(':'); lcd_putint(min10); lcd_putint(min1); lcd_putchar(':'); lcd_putint(sec10); lcd_putint(sec1); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar('D'); lcd_putchar('S'); lcd_putchar('T'); lcd_putchar('='); lcd_putint(dst); lcd_command (POS_4_0); // reposition to line 1 lcd_putchar('2'); lcd_putchar('0'); lcd_putint(year10); // 48 = 0011.0000 lcd_putint(year1); lcd_putchar('-'); lcd_putint(month10); lcd_putint(month1); lcd_putchar('-'); lcd_putint(day10); lcd_putint(day1); lcd_putchar(' '); if (weekday == 1) { lcd_putchar('M'); lcd_putchar('o'); lcd_putchar('n'); lcd_putchar('d'); lcd_putchar('a'); lcd_putchar('y'); lcd_putchar(' '); } if (weekday == 2) { lcd_putchar('T'); lcd_putchar('u'); lcd_putchar('e'); lcd_putchar('s'); lcd_putchar('d'); lcd_putchar('a'); lcd_putchar('y'); lcd_putchar(' '); lcd_putchar(' '); } if (weekday == 3) { lcd_putchar('W'); lcd_putchar('e'); lcd_putchar('d'); lcd_putchar('n'); lcd_putchar('e'); lcd_putchar('s'); lcd_putchar('d'); lcd_putchar('a'); lcd_putchar('y'); } if (weekday == 4) { lcd_putchar('T'); lcd_putchar('h'); lcd_putchar('u'); lcd_putchar('r'); lcd_putchar('s'); lcd_putchar('d'); lcd_putchar('a'); lcd_putchar('y'); lcd_putchar(' '); } if (weekday == 5) { lcd_putchar('F'); lcd_putchar('r'); lcd_putchar('i'); lcd_putchar('d'); lcd_putchar('a'); lcd_putchar('y'); lcd_putchar(' '); lcd_putchar(' '); } if (weekday == 6) { lcd_putchar('S'); lcd_putchar('a'); lcd_putchar('t'); lcd_putchar('u'); lcd_putchar('r'); lcd_putchar('d'); lcd_putchar('a'); lcd_putchar('y'); } if (weekday == 7) { lcd_putchar('S'); lcd_putchar('u'); lcd_putchar('n'); lcd_putchar('d'); lcd_putchar('a'); lcd_putchar('y'); lcd_putchar(' '); lcd_putchar(' '); } } /* ________________________ SET TRANSMIT BIT VALUES________________________ */ void set_bitvalue (void) // Set new bitvalues before a new minute { char i; min1 = min1 + 1; // Time to transmit = next minute update_clock (); bit_value[0] = 0; bit_value[1] = 0; bit_value[2] = 1; bit_value[3] = 0; bit_value[4] = 0; bit_value[5] = 0; bit_value[6] = 0; bit_value[7] = 0; bit_value[8] = 0; bit_value[9] = 0; bit_value[10] = 0; bit_value[11] = 0; bit_value[12] = 0; bit_value[13] = 0; bit_value[14] = 0; bit_value[15] = 0; // 0 = primary antenna in use bit_value[16] = 0; // 0 = No DST change in the next hour bit_value[17] = dst; // DST on/off bit_value[18] = !dst; // Timezone, usually opposite of bit 17 bit_value[19] = 0; // 0 = No leap second insertion bit_value[20] = 1; // Always 1 bit_value[21] = min1.0; // Minutes, BCD least significant first bit_value[22] = min1.1; bit_value[23] = min1.2; bit_value[24] = min1.3; bit_value[25] = min10.0; bit_value[26] = min10.1; bit_value[27] = min10.2; no_of_ones = 0; for (i=21; i<28; i++) { no_of_ones = no_of_ones+bit_value[i]; } bit_value[28] = no_of_ones%2; // Even parity bit, minute bits bit_value[29] = hour1.0; // Hours, BCD least significant first bit_value[30] = hour1.1; bit_value[31] = hour1.2; bit_value[32] = hour1.3; bit_value[33] = hour10.0; bit_value[34] = hour10.1; no_of_ones = 0; for (i=29; i<35; i++) // Calculate number of "ones" { no_of_ones = no_of_ones + bit_value[i]; } bit_value[35] = no_of_ones%2; // Even parity bit, hour bits bit_value[36] = day1.0; // Day of month, BCD least significant first bit_value[37] = day1.1; bit_value[38] = day1.2; bit_value[39] = day1.3; bit_value[40] = day10.0; bit_value[41] = day10.1; bit_value[42] = weekday.0; // Day of week, BCD least significant first, Mon=1 bit_value[43] = weekday.1; bit_value[44] = weekday.2; bit_value[45] = month1.0; // Month, BCD least significant first bit_value[46] = month1.1; bit_value[47] = month1.2; bit_value[48] = month1.3; bit_value[49] = month10.0; bit_value[50] = year1.0; // Year, BCD least significant first bit_value[51] = year1.1; bit_value[52] = year1.2; bit_value[53] = year1.3; bit_value[54] = year10.0; bit_value[55] = year10.1; bit_value[56] = year10.2; bit_value[57] = year10.3; no_of_ones = 0; for (i=36; i<58; i++) // Calculate number of "ones" { no_of_ones = no_of_ones + bit_value[i]; } bit_value[58] = no_of_ones%2; // Even parity bit, all transmitted bits bit_value[59] = 9; // No transmission min1 = min1-1; // Reset to real time if(min1<0) // For case "00.00" { min1 = 9; min10--; } if(min10 < 0) { min10 = 5; hour1--; } if(hour1 < 0) { hour1 = 3; hour10--; } if(hour10<0){ hour10 = 2; } // MORE FUNCTIONS required to correct day, month, year if (display_mode ==3) // Update bit overview display { update_display_mode_3 (); } } void put_eedata( void ) { /* Put global s[] -string in EEPROM-data */ char i, c; for(i = 0; i <14; i++) { c = stored_time[i]; /* Write EEPROM-data sequence */ EEADR = i; /* EEPROM-data adress 0x00 => 0x7F */ EEDATA = c; /* data to be written */ WREN = 1; /* write enable */ EECON2 = 0x55; /* first Byte in comandsequence */ EECON2 = 0xAA; /* second Byte in comandsequence */ WR = 1; /* write */ while( EEIF == 0) ; /* wait for done (EEIF=1) */ WREN = 0; /* write disable - safety first */ EEIF = 0; /* Reset EEIF bit in software */ /* End of write EEPROM-data sequence */ //if(stored_time == '\0') break; } } void get_eedata( void ) { /* Get EEPROM-data and put it in global s[] */ char i; for(i = 0; i <14; i++) { /* Start of read EEPROM-data sequence */ EEADR = i; /* EEPROM-data adress 0x00 => 0x7F */ RD = 1; /* Read */ stored_time[i] = EEDATA; /* data to be read */ /* End of read EEPROM-data sequence */ //if( s[i] == '\0') break; } } /* ________________________ LCD TEXT STORAGE________________________ */ char text1( char x) // this is the way to store a sentence { skip(x); /* internal function CC5x. */ #pragma return[] = "DCF77 Simulator " // 16-teckens rad } char text2( char x) // this is the way to store a sentence { skip(x); /* internal function CC5x. */ #pragma return[] = "Set clock, start" // 8 chars max! } char text3( char x) // this is the way to store a sentence { skip(x); /* internal function CC5x. */ #pragma return[] = "Set a fake time " // 8 chars max! } char text4( char x) // this is the way to store a sentence { skip(x); /* internal function CC5x. */ #pragma return[] = "Time is set. START " // 8 chars max! } char text5( char x) // this is the way to store a sentence { skip(x); /* internal function CC5x. */ #pragma return[] = "Transmitting bit: " // 8 chars max! } char text6( char x) // this is the way to store a sentence { skip(x); /* internal function CC5x. */ #pragma return[] = " " // 20 empty characters (erase) } char text7( char x) // this is the way to store a sentence { skip(x); /* internal function CC5x. */ #pragma return[] = "bit" // 20 empty characters (erase) } /* ________________________ LCD INITIALIZE________________________ */ void lcd_init( void ) // must be run once before using the display { delay(40); // give LCD time to settle RS = 0; // LCD in command-VIEW lcd_putchar(0b0011.0011); /* LCD starts in 8 bit VIEW */ lcd_putchar(0b0011.0010); /* change to 4 bit VIEW */ lcd_putchar(0b0010.1000); /* two line (8+8 chars in the row) */ lcd_putchar(0b0000.1100); /* display on, cursor off, blink off */ lcd_putchar(0b0000.0001); /* display clear */ lcd_putchar(0b0000.0110); /* ROTArement VIEW, shift off */ RS = 1; // LCD in character-VIEW } /* ________________________ LCD PUT CHARACTER________________________ */ void lcd_putchar( char data ) { // Must set LCD-VIEW before calling this function // RS = 1 LCD in character-VIEW // RS = 0 LCD in command-VIEW D7 = data.7; // upper Nibble D6 = data.6; D5 = data.5; D4 = data.4; EN = 0; nop(); nop(); EN = 1; delay(1); D7 = data.3; // lower Nibble D6 = data.2; D5 = data.1; D4 = data.0; EN = 0; nop(); nop(); EN = 1; delay(2); } void lcd_command ( char cmd ) // Write command to LCD { RS = 0; lcd_putchar( cmd ); RS = 1; // Back to character VIEW delay(2); } void lcd_string ( char * s ) // Write command to LCD { RS = 1; while (*s) lcd_putchar(*s++); delay(2); } void lcd_putint( char value ) { lcd_putchar(value+48); } /* ____ DELAY CAUSING PROBLEMS SOMETIMES ____ */ void delay ( char millisec) /* Delays a multiple of 1 milliseconds at 4 MHz using the TMR0 timer */ { OPTION = 2; /* prescaler divide by 8 */ do { TMR0 = 0; while ( TMR0 < 125) /* 125 * 8 = 1000 */ ; } while ( -- millisec > 0); } void delay250us ( char millisec) { char m; char k; for (m=0; m<millisec; m++) { for (k=0; k<250; k++) { nop(); nop(); } } } void delay10 ( char n) /* Delays a multiple of 10 milliseconds using the TMR0 timer Clock : 4 MHz => period T = 0.25 microseconds 1 IS = 1 Instruction Cycle = 1 microsecond error: 0.16 percent */ { char i; OPTION = 7; do { i = TMR0 + 39; /* 256 microsec * 39 = 10 ms */ while ( i != TMR0) ; } while ( --n > 0); } #pragma codepage 1 void display_3_pos (void) { c_pos[0] = POS_1_5; c_pos[1] = POS_1_6; c_pos[2] = POS_1_7; c_pos[3] = POS_1_8; c_pos[4] = POS_1_9; c_pos[5] = POS_1_10; c_pos[6] = POS_1_11; c_pos[7] = POS_1_12; c_pos[8] = POS_1_13; c_pos[9] = POS_1_14; c_pos[10] = POS_1_15; c_pos[11] = POS_1_16; c_pos[12] = POS_1_17; c_pos[13] = POS_1_18; c_pos[14] = POS_1_19; c_pos[15] = POS_2_5; c_pos[16] = POS_2_6; c_pos[17] = POS_2_7; c_pos[18] = POS_2_8; c_pos[19] = POS_2_9; c_pos[20] = POS_2_10; c_pos[21] = POS_2_11; c_pos[22] = POS_2_12; c_pos[23] = POS_2_13; c_pos[24] = POS_2_14; c_pos[25] = POS_2_15; c_pos[26] = POS_2_16; c_pos[27] = POS_2_17; c_pos[28] = POS_2_18; c_pos[29] = POS_2_19; c_pos[30] = POS_3_5; c_pos[31] = POS_3_6; c_pos[32] = POS_3_7; c_pos[33] = POS_3_8; c_pos[34] = POS_3_9; c_pos[35] = POS_3_10; c_pos[36] = POS_3_11; c_pos[37] = POS_3_12; c_pos[38] = POS_3_13; c_pos[39] = POS_3_14; c_pos[40] = POS_3_15; c_pos[41] = POS_3_16; c_pos[42] = POS_3_17; c_pos[43] = POS_3_18; c_pos[44] = POS_3_19; c_pos[45] = POS_4_5; c_pos[46] = POS_4_6; c_pos[47] = POS_4_7; c_pos[48] = POS_4_8; c_pos[49] = POS_4_9; c_pos[50] = POS_4_10; c_pos[51] = POS_4_11; c_pos[52] = POS_4_12; c_pos[53] = POS_4_13; c_pos[54] = POS_4_14; c_pos[55] = POS_4_15; c_pos[56] = POS_4_16; c_pos[57] = POS_4_17; c_pos[58] = POS_4_18; c_pos[59] = POS_4_19; } void display_4_pos (void) { c_pos[0] = POS_2_0; c_pos[1] = POS_2_1; c_pos[2] = POS_2_2; c_pos[3] = POS_2_3; c_pos[4] = POS_2_4; c_pos[5] = POS_2_5; c_pos[6] = POS_2_6; c_pos[7] = POS_2_7; c_pos[8] = POS_2_8; c_pos[9] = POS_2_9; c_pos[10] = POS_2_10; c_pos[11] = POS_2_11; c_pos[12] = POS_2_12; c_pos[13] = POS_2_13; c_pos[14] = POS_2_14; c_pos[15] = POS_1_1; c_pos[16] = POS_2_0; c_pos[17] = POS_2_1; c_pos[18] = POS_2_2; c_pos[19] = POS_2_3; c_pos[20] = POS_1_1; c_pos[21] = POS_2_0; c_pos[22] = POS_2_1; c_pos[23] = POS_2_2; c_pos[24] = POS_2_3; c_pos[25] = POS_2_4; c_pos[26] = POS_2_5; c_pos[27] = POS_2_6; c_pos[28] = POS_3_1; c_pos[29] = POS_2_0; c_pos[30] = POS_2_1; c_pos[31] = POS_2_2; c_pos[32] = POS_2_3; c_pos[33] = POS_2_4; c_pos[34] = POS_2_5; c_pos[35] = POS_3_1; c_pos[36] = POS_2_0; c_pos[37] = POS_2_1; c_pos[38] = POS_2_2; c_pos[39] = POS_2_3; c_pos[40] = POS_2_4; c_pos[41] = POS_2_5; c_pos[42] = POS_2_0; c_pos[43] = POS_2_1; c_pos[44] = POS_2_2; c_pos[45] = POS_2_0; c_pos[46] = POS_2_1; c_pos[47] = POS_2_2; c_pos[48] = POS_2_3; c_pos[49] = POS_2_4; c_pos[50] = POS_2_0; c_pos[51] = POS_2_1; c_pos[52] = POS_2_2; c_pos[53] = POS_2_3; c_pos[54] = POS_2_4; c_pos[55] = POS_2_5; c_pos[56] = POS_2_6; c_pos[57] = POS_2_7; c_pos[58] = POS_2_0; c_pos[59] = POS_2_0; } void update_display_mode_3 (void) { display_3_pos (); // load the cursor position for display 2 lcd_command (c_pos[tick_pos]); // move cursor to current bit position if(first==0) { lcd_command (0b0000.1110); // Cursor on, blink off lcd_command (0b0000.0110); // ROTArement, not shifted lcd_command (POS_1_0); // reposition to line 1 lcd_putchar('0'); lcd_putchar('0'); lcd_putchar('-'); lcd_putchar(':'); lcd_putchar(' '); char i; for(i=0; i<15; i++) // display binary values 1-14 { lcd_putint(bit_value[i]); } lcd_command (POS_2_0); lcd_putchar('1'); lcd_putchar('5'); lcd_putchar('-'); lcd_putchar(':'); lcd_putchar(' '); for(i=15; i<30; i++) // display binary values 15-29 { lcd_putint(bit_value[i]); } lcd_command (POS_3_0); lcd_putchar('3'); lcd_putchar('0'); lcd_putchar('-'); lcd_putchar(':'); lcd_putchar(' '); for(i=30; i<45; i++) // display binary values 30-44 { lcd_putint(bit_value[i]); } lcd_command (POS_4_0); lcd_putchar('4'); lcd_putchar('5'); lcd_putchar('-'); lcd_putchar(':'); lcd_putchar(' '); for(i=45; i<59; i++) // display binary values 45-58 { lcd_putint(bit_value[i]); } lcd_putchar('-'); // bit 59 always no signal first=1; } } void update_display_mode_4 (void) { display_4_pos (); // Update cursor positions for this display char i; lcd_command (0b0000.1110); // Cursor on, blink off lcd_command (0b0000.0110); // ROTArement, not shifted lcd_command (POS_1_11); lcd_putchar('b'); lcd_putchar('i'); lcd_putchar('t'); if(tick_pos > 0 && tick_pos < 15) { lcd_command (POS_3_0); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); lcd_command (POS_1_0); lcd_putchar('W'); lcd_putchar('e'); lcd_putchar('a'); lcd_putchar('t'); lcd_putchar('h'); lcd_putchar('e'); lcd_putchar('r'); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); lcd_command (POS_1_14); lcd_putchar(' '); lcd_putchar('0'); lcd_putchar('1'); lcd_putchar('-'); lcd_putchar('1'); lcd_putchar('4'); lcd_command (POS_2_0); for(i=0; i<15; i++) { lcd_putint(bit_value[i]); } } if (tick_pos > 15 && tick_pos < 20) { lcd_command (POS_1_0); lcd_putchar('D'); lcd_putchar('S'); lcd_putchar('T'); lcd_putchar('+'); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); lcd_command (POS_1_15); lcd_putchar('1'); lcd_putchar('6'); lcd_putchar('-'); lcd_putchar('1'); lcd_putchar('9'); lcd_command (POS_2_0); for(i=16; i<20; i++) { lcd_putint(bit_value[i]); } for(i=0; i<11; i++) { lcd_putchar(' '); } } if (tick_pos == 21) { lcd_command (POS_1_0); lcd_putchar('M'); lcd_putchar('i'); lcd_putchar('n'); lcd_putchar('u'); lcd_putchar('t'); lcd_putchar('e'); lcd_command (POS_1_15); lcd_putchar('2'); lcd_putchar('1'); lcd_putchar('-'); lcd_putchar('2'); lcd_putchar('7'); lcd_command (POS_2_0); for(i=21; i<28; i++) { lcd_putint(bit_value[i]); } lcd_command (POS_2_8); lcd_putchar('='); lcd_putchar(' '); lcd_putint(min10); lcd_putint(min1); lcd_putchar(' '); } if(tick_pos == 29) { lcd_command (POS_1_0); lcd_putchar('H'); lcd_putchar('o'); lcd_putchar('u'); lcd_putchar('r'); lcd_putchar(' '); lcd_putchar(' '); lcd_command (POS_1_15); lcd_putchar('2'); lcd_putchar('9'); lcd_putchar('-'); lcd_putchar('3'); lcd_putchar('4'); lcd_command (POS_2_0); for(i=29; i<35; i++) { lcd_putint(bit_value[i]); } lcd_putchar(' '); lcd_command (POS_2_7); lcd_putchar('='); lcd_putchar(' '); lcd_putint(hour10); lcd_putint(hour1); lcd_putchar(' '); } if(tick_pos == 36) { lcd_command (POS_1_0); lcd_putchar('D'); lcd_putchar('a'); lcd_putchar('y'); lcd_putchar(' '); lcd_command (POS_1_15); lcd_putchar('3'); lcd_putchar('6'); lcd_putchar('-'); lcd_putchar('4'); lcd_putchar('1'); lcd_command (POS_2_0); for(i=36; i<42; i++) { lcd_putint(bit_value[i]); } lcd_putchar(' '); lcd_command (POS_2_7); lcd_putchar('='); lcd_putchar(' '); lcd_putint(day10); lcd_putint(day1); } if(tick_pos == 42) { lcd_command (POS_1_0); lcd_putchar('W'); lcd_putchar('e'); lcd_putchar('e'); lcd_putchar('k'); lcd_putchar('d'); lcd_putchar('a'); lcd_putchar('y'); lcd_command (POS_1_15); lcd_putchar('4'); lcd_putchar('2'); lcd_putchar('-'); lcd_putchar('4'); lcd_putchar('4'); lcd_command (POS_2_0); lcd_putint(bit_value[42]); lcd_putint(bit_value[43]); lcd_putint(bit_value[44]); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); lcd_command (POS_2_4); lcd_putchar('='); lcd_putchar(' '); lcd_putchar('D'); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); } if(tick_pos ==45) { lcd_command (POS_1_0); lcd_putchar('M'); lcd_putchar('o'); lcd_putchar('n'); lcd_putchar('t'); lcd_putchar('h'); lcd_putchar(' '); lcd_putchar(' '); lcd_command (POS_1_15); lcd_putchar('4'); lcd_putchar('5'); lcd_putchar('-'); lcd_putchar('4'); lcd_putchar('9'); lcd_command (POS_2_0); for(i=45; i<50; i++) { lcd_putint(bit_value[i]); } lcd_command (POS_2_6); lcd_putchar('='); lcd_putchar(' '); lcd_putint(month10); lcd_putint(month1); } if(tick_pos == 50) { lcd_command (POS_1_0); lcd_putchar('Y'); lcd_putchar('e'); lcd_putchar('a'); lcd_putchar('r'); lcd_putchar(' '); lcd_command (POS_1_15); lcd_putchar('5'); lcd_putchar('0'); lcd_putchar('-'); lcd_putchar('5'); lcd_putchar('7'); lcd_command (POS_2_0); for(i=50; i<58; i++) { lcd_putint(bit_value[i]); } lcd_command (POS_2_9); lcd_putchar('='); lcd_putchar(' '); lcd_putchar('('); lcd_putchar('2'); lcd_putchar('0'); lcd_putchar(')'); lcd_putint(year10); lcd_putint(year1); } if(tick_pos > 58 || tick_pos < 01) { lcd_command (POS_1_0); lcd_putchar('M'); lcd_putchar('i'); lcd_putchar('n'); lcd_putchar('u'); lcd_putchar('t'); lcd_putchar('e'); lcd_putchar('M'); lcd_putchar('a'); lcd_putchar('r'); lcd_putchar('k'); lcd_command (POS_1_15); lcd_putchar(' '); lcd_putchar('5'); lcd_putchar('9'); lcd_command (POS_2_0); lcd_putchar('['); lcd_putchar('N'); lcd_putchar('o'); lcd_putchar(' '); lcd_putchar('p'); lcd_putchar('u'); lcd_putchar('l'); lcd_putchar('s'); lcd_putchar('e'); lcd_putchar(']'); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); lcd_putchar(' '); } lcd_command (c_pos[tick_pos]); // move cursor to current bit position } #pragma codepage 2 /* ________________________ SET CLOCK start ________________________ */ void set_clock (void) { I_SET=1; // SET button indicator on I_START=0; // START button off I_TRANS=0; // TRANS button indicator on LED0 = 0; LED1 = 0; T_ON = 0; // Switch off transmitter trans_mode=0; transit = 0; up = 0; down = 0; start_mode = 0; TMR1IE = 0; // Disable TMR1 interrupt T1CON.0 = 0 ; // Stop the oscillator TMR1IF = 0; RBIE = 1; /* local enable */ GIE = 1; /* global enable */ char i; lcd_command (0b00000010); // Cursor home lcd_command (0b0000.1110); // Cursor on, blink off for(i=0; i<16; i++) lcd_putchar(text3(i)); // display start text 1 display_time(); delay10(9); lcd_command (POS_3_0); // Reposition to hours position blink_empty (2) ; // Blink hours while (set_mode ==1) { if (up ==1) { up = 0; blink_one (); hour1++; if(hour1>9) { hour1 = 0; hour10++; } if(hour10 >= 2 && hour1 > 3) { hour1=0; hour10=0; } } if (down ==1) { down = 0; blink_null (); hour1--; if(hour1<0) { hour1 = 9; hour10--; } if(hour10<0) { hour10 = 2; hour1 = 3; } } lcd_command (POS_3_0); // reposition to hour position ... lcd_putint(hour10); // ... and display hours lcd_putint(hour1); if (SET == 0) // If SET-button is pressed { set_mode = 2; // Move to minutes VIEW lcd_command (POS_3_3); // Reposition to minutes position blink_empty (2); // Blink minutes } } while (set_mode ==2) { if (up ==1) { up = 0; blink_one (); min1++; if(min1>9) { min1=0; min10++; } if(min10>5) { min10=0; } } if (down ==1) { down = 0; blink_null (); min1--; if(min1<0) { min1=9; min10--; } if(min10<0) { min10=5; } } lcd_command (POS_3_3); // reposition to line 1 lcd_putint(min10); lcd_putint(min1); if (SET == 0) { set_mode = 3; // Move to seconds VIEW lcd_command (POS_3_6); // Goto seconds position blink_empty (2) ; // Blink seconds } } while (set_mode ==3) { if (up ==1) { up = 0; blink_one (); sec1++; if(sec1>9) { sec1 = 0; sec10++; } if(sec10>5) { sec10=0; } tick_pos = sec10*10 + sec1; } if (down ==1) { down = 0; blink_null (); sec1--; if(sec1<0) { sec1=9; sec10--; } if(sec10<0) { sec10=5; } } tick_pos = sec10*10 + sec1; lcd_command (POS_3_6); // reposition to line 1 lcd_putint(sec10); lcd_putint(sec1); if (SET == 0) { set_mode = 4; // Move to seconds VIEW lcd_command (POS_3_15); // Goto seconds position blink_empty (1) ; // Blink seconds } } while (set_mode ==4) { if ((up ==1) || (down == 1)) { up = 0; blink_one (); blink_null (); down = 0; //dst = ! dst; dst++; if(dst>1) { dst = 0; } } lcd_command (POS_3_15); // reposition to line 1 lcd_putint(dst); if (SET == 0) { set_mode = 5; // Move to minutes VIEW lcd_command (POS_4_0); // Reposition to minutes position blink_empty (4) ; } } while (set_mode ==5) { if (up ==1) { up = 0; blink_one (); year1++; if(year1>9) { year1 = 0; year10++; } if(year10>9) { year10=0; } } if (down ==1) { down = 0; blink_null (); year1--; if(year1<0) { year1 = 9; year10--; } if(year10<0) { year10=9; } } lcd_command (POS_4_0); // reposition to line 1 lcd_putchar('2'); lcd_putchar('0'); lcd_putint(year10); lcd_putint(year1); if (SET == 0) { set_mode = 6; // Move to minutes VIEW lcd_command (POS_4_5); // Reposition to minutes position blink_empty (2) ; } } while (set_mode ==6) { if (up ==1) { up = 0; blink_one (); month1++; if(month1>9) { month1 = 0; month10++; } if(month10==1 && month1>2) { month10 = 0; month1 = 1; } } if (down ==1) { down = 0; blink_null (); month1--; if(month1<0) { month1 = 9; month10--; } if(month10<1 && month1<1) { month10 = 1; month1 = 2; } } lcd_command (POS_4_5); // reposition to line 1 lcd_putint(month10); lcd_putint(month1); if (SET == 0) { set_mode = 7; // Move to minutes VIEW lcd_command (POS_4_8); // Reposition to minutes position blink_empty (2) ; } } while (set_mode ==7) { if (up ==1) { up = 0; blink_one (); day1++; if(day1>9) { day1 = 0; day10++; } if(day10 >2 && day1>1) { day1 = 1; day10 = 0; } } if (down ==1) { down = 0; blink_null (); day1--; if(day1<0) { day1 = 9; day10--; } if(day10<1 && day1<1) { day1 = 1; day10 = 3; // Måste justeras } } lcd_command (POS_4_8); // reposition to line 1 lcd_putint(day10); lcd_putint(day1); if (SET == 0) { set_mode = 8; // Move to minutes VIEW lcd_command (POS_4_11); // Reposition to weekday position blink_empty (9) ; } } while (set_mode ==8) { if (up ==1) { up = 0; blink_one (); weekday++; if (weekday > 7) { weekday = 1; } } if (down ==1) { down = 0; blink_null (); weekday--; if (weekday <1) { weekday = 7; } } lcd_command (POS_4_11); if (weekday == 1) { lcd_putchar('M'); lcd_putchar('o'); lcd_putchar('n'); lcd_putchar('d'); lcd_putchar('a'); lcd_putchar('y'); lcd_putchar(' '); } if (weekday == 2) { lcd_putchar('T'); lcd_putchar('u'); lcd_putchar('e'); lcd_putchar('s'); lcd_putchar('d'); lcd_putchar('a'); lcd_putchar('y'); lcd_putchar(' '); lcd_putchar(' '); } if (weekday == 3) { lcd_putchar('W'); lcd_putchar('e'); lcd_putchar('d'); lcd_putchar('n'); lcd_putchar('e'); lcd_putchar('s'); lcd_putchar('d'); lcd_putchar('a'); lcd_putchar('y'); } if (weekday == 4) { lcd_putchar('T'); lcd_putchar('h'); lcd_putchar('u'); lcd_putchar('r'); lcd_putchar('s'); lcd_putchar('d'); lcd_putchar('a'); lcd_putchar('y'); lcd_putchar(' '); } if (weekday == 5) { lcd_putchar('F'); lcd_putchar('r'); lcd_putchar('i'); lcd_putchar('d'); lcd_putchar('a'); lcd_putchar('y'); lcd_putchar(' '); lcd_putchar(' '); } if (weekday == 6) { lcd_putchar('S'); lcd_putchar('a'); lcd_putchar('t'); lcd_putchar('u'); lcd_putchar('r'); lcd_putchar('d'); lcd_putchar('a'); lcd_putchar('y'); } if (weekday == 7) { lcd_putchar('S'); lcd_putchar('u'); lcd_putchar('n'); lcd_putchar('d'); lcd_putchar('a'); lcd_putchar('y'); lcd_putchar(' '); lcd_putchar(' '); } if (SET == 0) { delay10 (10); // Debounce set_mode=0; } } stored_time[0]=hour10; // Update string with set time stored_time[1]=hour1; stored_time[2]=min10; stored_time[3]=min1; stored_time[4]=sec10; stored_time[5]=sec1; stored_time[6]=dst; stored_time[7]=year10; stored_time[8]=year1; stored_time[9]=month10; stored_time[10]=month1; stored_time[11]=day10; stored_time[12]=day1; stored_time[13]=weekday; put_eedata (); // Store set time in EEPROM lcd_command (0b0000.0001); // Cursor hoME for(i=0; i<20; i++) lcd_putchar(text4(i)); // display text 4 display_mode = 1; // display VIEW should be 1 again lcd_command(0b0000.1100); // display on, cursor off, blink off */ //Lägg in senast använd display mode här GIE = 0; // Interrupts llowed RBIE = 0; /* local enable */ TMR1H = 0x80; // Reset counter TMR1L = 0x00; TMR1IF = 0; // Enable interrupt T1CON.0 = 1 ; // Start the oscillator TMR1IE = 1; // Enable interrupt PEIE = 1; // Interrupts llowed GIE = 1; // Interrupts llowed I_SET=0; } void blink_one (void) { LED1=1; delay250us(1); LED1=0; } void blink_null (void) { LED0=1; delay250us(1); LED0=0; }