| CODE |
/* DCF77 Simulator for RTAI 3.2 A DCF77 time signal is produced on the parallel port data pins Data on pins 2-9 (D0-D7) GND on pins 18-25 Very handy for testing embedded hardware which needs DCF77 (C) 2005 www.captain.at */ #include <stdio.h> #include <sys/mman.h> #include <stdlib.h> #include <signal.h> #include <time.h> #include <rtai_lxrt.h> #include <rtai_sem.h> #include <rtai_usi.h> #include <sys/io.h> #define BASEPORT 0x378 static SEM *dspsem; static volatile int end_dcf77 = 1; static volatile int end = 0; #define PERIOD 100000000 // 100ms void sendone(void) { int t; outb_p(255, BASEPORT); rt_task_wait_period(); // 1 = 200ms rt_task_wait_period(); outb_p(0, BASEPORT); for (t = 1; t <= 8; t++) { rt_task_wait_period(); } } void sendzero(void) { int t; outb_p(255, BASEPORT); rt_task_wait_period(); // 0 = 100ms outb_p(0, BASEPORT); for (t = 1; t <= 9; t++) { rt_task_wait_period(); } } unsigned int Convert2PacketBCD(unsigned int value) { unsigned int result; result = value % 10; result += (value - result) / 10 * 0x10; return result; } static void *dcf77_generator(void *args) { RT_TASK *handler; RTIME period; int i, min, hour, day, wday, month, year; int now_min, now_hour, now_day, now_wday, now_month, now_year; time_t now; struct tm *now_tm; unsigned int parity_min, parity_hour, parity_date; if (!(handler = rt_task_init_schmod(nam2num("DCFHLR"), 0, 0, 0, SCHED_FIFO, 0xF))) { printf("CANNOT INIT HANDLER TASK > DCFHLR <\n"); exit(1); } // Get the current date/time before we go to hard real time // Those are SYSCALLs and would break hard real time now = time (NULL); now_tm = localtime (&now); now_min = now_tm->tm_min; now_hour = now_tm->tm_hour; now_day = now_tm->tm_mday; now_wday = now_tm->tm_wday; now_month = now_tm->tm_mon + 1; now_year = now_tm->tm_year - 100; min = Convert2PacketBCD(now_min); hour = Convert2PacketBCD(now_hour); day = Convert2PacketBCD(now_day); wday = Convert2PacketBCD(now_wday); month = Convert2PacketBCD(now_month); year = Convert2PacketBCD(now_year); rt_allow_nonroot_hrt(); mlockall(MCL_CURRENT | MCL_FUTURE); rt_make_hard_real_time(); end_dcf77 = 0; rt_set_oneshot_mode(); start_rt_timer(0); period = nano2count(PERIOD); rt_task_make_periodic(handler, rt_get_time() + period, period); while ( !end_dcf77 ) { rt_sem_signal(dspsem); outb_p(0, BASEPORT); // generate 20 zeros for (i = 1; i <= 20; i++ ) { sendzero(); if (end_dcf77) break; } // send one start bit sendone(); // minute parity_min = 0; for (i = 1; i <= 7; i++) { if (min & 1) { sendone(); parity_min = parity_min ^ 1; } else sendzero(); min = min >> 1; } if (end_dcf77) break; // minute_parity if (parity_min) { sendone(); } else { sendzero(); } // hour parity_hour = 0; for (i = 1; i <= 6; i++) { if (hour & 1) { sendone(); parity_hour = parity_hour ^ 1; } else sendzero(); hour = hour >> 1; } // hour_parity if (parity_hour) { sendone(); } else { sendzero(); } if (end_dcf77) break; parity_date = 0; // day for (i = 1; i <= 6; i++) { if (day & 1) { sendone(); parity_date = parity_date ^ 1; } else sendzero(); day = day >> 1; } if (end_dcf77) break; // weekday for (i = 1; i <= 3; i++) { if (wday & 1) { sendone(); parity_date = parity_date ^ 1; } else sendzero(); wday = wday >> 1; } if (end_dcf77) break; // month for (i = 1; i <= 5; i++) { if (month & 1) { sendone(); parity_date = parity_date ^ 1; } else sendzero(); month = month >> 1; } if (end_dcf77) break; // year for (i = 1; i <= 8; i++) { if (year & 1) { sendone(); parity_date = parity_date ^ 1; } else sendzero(); year = year >> 1; } if (end_dcf77) break; // date_parity if (parity_date) { sendone(); } else { sendzero(); } // wait a second if (end_dcf77) break; for (i = 0; i < 10; i++) { rt_task_wait_period(); if (end_dcf77) break; } // increment minute now_min++; if (now_min > 59) { now_min = 0; now_hour++; if (now_hour > 23) { now_hour = 0; now_day++; // etc... } } min = Convert2PacketBCD(now_min); hour = Convert2PacketBCD(now_hour); day = Convert2PacketBCD(now_day); wday = Convert2PacketBCD(now_wday); month = Convert2PacketBCD(now_month); year = Convert2PacketBCD(now_year); } stop_rt_timer(); rt_make_soft_real_time(); rt_task_delete(handler); return 0; } void clean_exit(int dummy) { end = 1; end_dcf77 = 1; } int main(void) { RT_TASK *maint; int dcf77thread; signal(SIGTERM, clean_exit); signal(SIGINT, clean_exit); if (!(maint = rt_task_init(nam2num("MAIN"), 1, 0, 0))) { printf("CANNOT INIT MAIN TASK > MAIN <\n"); exit(1); } // create semaphore to notify main() when interrupt occurs if (!(dspsem = rt_sem_init(nam2num("DSPSEM"), 0))) { printf("CANNOT INIT SEMAPHORE > DSPSEM <\n"); exit(1); } // ask for permission to access the parallel port from user-space if (iopl(3)) { printf("iopl err\n"); rt_task_delete(maint); rt_sem_delete(dspsem); exit(1); } outb_p(0x10, BASEPORT + 2); //set port to interrupt mode; pins are output // interrupt mode is not used here // create thread dcf77thread = rt_thread_create(dcf77_generator, NULL, 10000); while (end_dcf77) { // wait until thread went to hard real time usleep(100000); } while (!end) { rt_sem_wait(dspsem); printf("New minute starts now [use CTRL-C to end]\n"); } printf("WAIT FOR COMPLETION\n"); rt_thread_join(dcf77thread); rt_sem_delete(dspsem); rt_task_delete(maint); printf("DCF77SIM HAS ENDED\n"); return 0; } |
| CODE |
prefix := $(shell rtai-config --prefix) ifeq ($(prefix),) $(error Please add <rtai-install>/bin to your PATH variable) endif CC = $(shell rtai-config --cc) LXRT_CFLAGS = $(shell rtai-config --lxrt-cflags) LXRT_LDFLAGS = $(shell rtai-config --lxrt-ldflags) all: dcf77 dcf77: dcf77.c $(CC) $(LXRT_CFLAGS) -o $@ $< $(LXRT_LDFLAGS) clean: rm -f *.o dcf77 .PHONY: clean run.sh #!/bin/sh TMP=$PWD cd /usr/realtime/modules/ insmod ./rtai_hal.ko insmod ./rtai_lxrt.ko insmod ./rtai_sem.ko cd $TMP ./dcf77 rmmod rtai_sem rmmod rtai_lxrt rmmod rtai_hal |
| CODE |
/* DCF77 Simulator - Non-Realtime-version A DCF77 time signal is produced on the parallel port data pins Data on pins 2-9 (D0-D7) GND on pins 18-25 Very handy for testing embedded hardware which needs DCF77 (C) 2005 www.captain.at */ #include <stdio.h> #include <sys/mman.h> #include <stdlib.h> #include <signal.h> #include <time.h> #include <sys/io.h> #define BASEPORT 0x378 static volatile int end_dcf77 = 1; void sendone(void) { int t; outb_p(255, BASEPORT); usleep(200000); // 1 = 200ms outb_p(0, BASEPORT); for (t = 1; t <= 8; t++) { usleep(100000); } } void sendzero(void) { int t; outb_p(255, BASEPORT); usleep(100000); // 0 = 100ms outb_p(0, BASEPORT); for (t = 1; t <= 9; t++) { usleep(100000); } } unsigned int Convert2PacketBCD(unsigned int value) { unsigned int result; result = value % 10; result += (value - result) / 10 * 0x10; return result; } void dcf77_generator(void) { int i, min, hour, day, wday, month, year; int now_min, now_hour, now_day, now_wday, now_month, now_year; time_t now; struct tm *now_tm; unsigned int parity_min, parity_hour, parity_date; // Get the current date/time now = time (NULL); now_tm = localtime (&now); now_min = now_tm->tm_min; now_hour = now_tm->tm_hour; now_day = now_tm->tm_mday; now_wday = now_tm->tm_wday; now_month = now_tm->tm_mon + 1; now_year = now_tm->tm_year - 100; min = Convert2PacketBCD(now_min); hour = Convert2PacketBCD(now_hour); day = Convert2PacketBCD(now_day); wday = Convert2PacketBCD(now_wday); month = Convert2PacketBCD(now_month); year = Convert2PacketBCD(now_year); end_dcf77 = 0; while ( !end_dcf77 ) { printf("New minute starts now [use CTRL-C to end]\n"); outb_p(0, BASEPORT); // generate 20 zeros for (i = 1; i <= 20; i++ ) { sendzero(); if (end_dcf77) break; } // send one start bit sendone(); // minute parity_min = 0; for (i = 1; i <= 7; i++) { if (min & 1) { sendone(); parity_min = parity_min ^ 1; } else sendzero(); min = min >> 1; } if (end_dcf77) break; // minute_parity if (parity_min) { sendone(); } else { sendzero(); } // hour parity_hour = 0; for (i = 1; i <= 6; i++) { if (hour & 1) { sendone(); parity_hour = parity_hour ^ 1; } else sendzero(); hour = hour >> 1; } // hour_parity if (parity_hour) { sendone(); } else { sendzero(); } if (end_dcf77) break; parity_date = 0; // day for (i = 1; i <= 6; i++) { if (day & 1) { sendone(); parity_date = parity_date ^ 1; } else sendzero(); day = day >> 1; } if (end_dcf77) break; // weekday for (i = 1; i <= 3; i++) { if (wday & 1) { sendone(); parity_date = parity_date ^ 1; } else sendzero(); wday = wday >> 1; } if (end_dcf77) break; // month for (i = 1; i <= 5; i++) { if (month & 1) { sendone(); parity_date = parity_date ^ 1; } else sendzero(); month = month >> 1; } if (end_dcf77) break; // year for (i = 1; i <= 8; i++) { if (year & 1) { sendone(); parity_date = parity_date ^ 1; } else sendzero(); year = year >> 1; } if (end_dcf77) break; // date_parity if (parity_date) { sendone(); } else { sendzero(); } // wait a second if (end_dcf77) break; for (i = 0; i < 10; i++) { usleep(100000); if (end_dcf77) break; } // increment minute now_min++; if (now_min > 59) { now_min = 0; now_hour++; if (now_hour > 23) { now_hour = 0; now_day++; // etc... } } min = Convert2PacketBCD(now_min); hour = Convert2PacketBCD(now_hour); day = Convert2PacketBCD(now_day); wday = Convert2PacketBCD(now_wday); month = Convert2PacketBCD(now_month); year = Convert2PacketBCD(now_year); } } void clean_exit(int dummy) { end_dcf77 = 1; printf("WAIT FOR COMPLETION\n"); } int main(void) { signal(SIGTERM, clean_exit); signal(SIGINT, clean_exit); // ask for permission to access the parallel port from user-space if (iopl(3)) { printf("iopl err\n"); exit(1); } outb_p(0x10, BASEPORT + 2); //set port to interrupt mode; pins are output // interrupt mode is not used here dcf77_generator(); printf("DCF77SIM HAS ENDED\n"); return 0; } |