1 /*----------------------------------------------------------------------------+
2 | |
3 | HEYU Support for External Power Line Sync |
4 | Copyright 2005,2006 Charles W. Sullivan |
5 | |
6 | |
7 | As used herein, HEYU is a trademark of Daniel B. Suthers. |
8 | X10, CM11A, and ActiveHome are trademarks of X-10 (USA) Inc. |
9 | The author is not affiliated with either entity. |
10 | |
11 | Charles W. Sullivan |
12 | Co-author and Maintainer |
13 | Greensboro, North Carolina |
14 | Email ID: cwsulliv01 |
15 | Email domain: -at- heyu -dot- org |
16 | |
17 +----------------------------------------------------------------------------*/
18
19 /*
20 * This program is free software: you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation, either version 3 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32 *
33 */
34
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <ctype.h>
39 #if 0
40 #include "x10.h"
41 #include "process.h"
42 #endif
43
44 #ifdef SCO
45 #define _SVID3 /* required for correct termio handling */
46 #undef _IBCS2 /* conflicts with SVID3 */
47 #endif
48
49 #include <time.h>
50 #include <unistd.h>
51 #include <signal.h>
52
53 #ifdef LINUX
54 #include <asm/ioctls.h>
55 # ifdef OLDLINUX
56 #include <linux/serial_reg.h>
57 # endif
58 #include <linux/serial.h>
59 #include <sys/ioctl.h>
60 #include <unistd.h>
61 #include <syslog.h>
62 #else
63 # if (defined(POSIX) || defined(FREEBSD) || defined(OPENBSD))
64 #include <sys/ttycom.h>
65 # else
66 # ifdef SCO
67 #include <sys/ttycom.h>
68 # else
69 # ifdef DARWIN
70 #include <sys/ttycom.h>
71 # else
72 #include <sys/ttycom.h>
73 # endif
74 # endif
75 # endif
76 #endif
77
78 #if (defined(OSF) || defined(DARWIN) || defined(NETBSD))
79 #include <sys/ioctl.h>
80 #endif
81
82 #ifdef HASSELECT
83 #include <sys/time.h>
84 #include <sys/types.h>
85 #endif
86
87 #include "x10.h"
88 #include "process.h"
89
90 #ifdef pid_t
91 #define PID_T pid_t
92 #else
93 #define PID_T long
94 #endif
95
96 extern int verbose;
97 extern int sptty;
98 extern int tty;
99 extern int ttylock(), munlock();
100 extern PID_T lockpid( char * );
101 extern int i_am_relay;
102
103 extern CONFIG config;
104 extern CONFIG *configp;
105
106 static volatile unsigned long trigger_loopcount;
107 static volatile unsigned long countdown;
108 static volatile int dummy = 1;
109
110 /*----------------------------------------------------------------------------+
111 | Millisecond timer using timing loop. |
112 +----------------------------------------------------------------------------*/
msec_timer(unsigned long loopcount)113 static void msec_timer ( unsigned long loopcount )
114 {
115 countdown = loopcount;
116 while (dummy && countdown--);
117 return;
118 }
119
120
121 /*---------------------------------------------------------------+
122 | Optional wait for external sync trigger for dims/brights. |
123 | A one millisec timing loop must be configured and additional |
124 | hardware is required as follows: |
125 | |
126 | The output of a 4 to 8 VAC (RMS) transformer connected from |
127 | the Carrier Detect to Signal Ground pins of the serial port |
128 | (DB9 pins 1 and 5 respectively) allows Heyu to distinguish |
129 | between the positive and negative half-cycles of the AC power |
130 | line and trigger the command to begin exclusively on either |
131 | the rising or falling zero crossing, depending on the |
132 | relative phase of the voltages on the CD pin and the AC line. |
133 +---------------------------------------------------------------*/
wait_external_trigger(int mode)134 int wait_external_trigger ( int mode )
135 {
136 int j, status, retcode, jmax = 20;
137
138 if ( mode == NO_SYNC )
139 return 0;
140
141 if ( configp->timer_loopcount == 0 ) {
142 fprintf(stderr, "No timing loop has been configured - trigger ignored.\n");
143 return 1;
144 }
145
146 /* Timing loopcount for 1 millisecond */
147 trigger_loopcount = configp->timer_loopcount / 1000L;
148
149 if ( mode == RISE_SYNC ) {
150 /* Rising zero-crossing triggering */
151 /* Wait until the Carrier Detect line becomes active */
152 for ( j = 0; j < jmax; j++ ) {
153 retcode = ioctl(tty, TIOCMGET, &status);
154 if ( status & TIOCM_CD )
155 break;
156 msec_timer(trigger_loopcount);
157 }
158 if ( j >= jmax ) {
159 fprintf(stderr, "No trigger detected.\n");
160 return 1;
161 }
162
163 /* Now wait until it just becomes inactive */
164 for ( j = 0; j < jmax; j++ ) {
165 retcode = ioctl(tty, TIOCMGET, &status);
166 if ( !(status & TIOCM_CD) )
167 break;
168 msec_timer(trigger_loopcount);
169 }
170 }
171 else {
172 /* Falling zero-crossing triggering */
173 /* Wait until the Carrier Detect line becomes inactive */
174 for ( j = 0; j < jmax; j++ ) {
175 retcode = ioctl(tty, TIOCMGET, &status);
176 if ( !(status & TIOCM_CD) )
177 break;
178 msec_timer(trigger_loopcount);
179 }
180 /* Now wait until it just becomes active */
181 for ( j = 0; j < jmax; j++ ) {
182 retcode = ioctl(tty, TIOCMGET, &status);
183 if ( status & TIOCM_CD )
184 break;
185 msec_timer(trigger_loopcount);
186 }
187 if ( j >= jmax ) {
188 fprintf(stderr, "No trigger detected.\n");
189 return 1;
190 }
191 }
192
193 /* Wait an additional few milliconds to make */
194 /* sure we're out of the zero crossing region */
195 msec_timer(2 * trigger_loopcount);
196
197 return 0;
198 }
199
200