root/trunk/libffado/tests/test-ieee1394service.cpp

Revision 864, 11.3 kB (checked in by ppalmers, 14 years ago)

update license to GPLv2 or GPLv3 instead of GPLv2 or any later version. Update copyrights to reflect the new year

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <endian.h>
32
33 #include <signal.h>
34 #include "src/debugmodule/debugmodule.h"
35
36 #include <netinet/in.h>
37
38 #include "src/libieee1394/cycletimer.h"
39 #include "src/libieee1394/configrom.h"
40 #include "src/libieee1394/ieee1394service.h"
41 #include "src/libieee1394/ARMHandler.h"
42
43 #include "src/libutil/Thread.h"
44 #include "src/libutil/PosixThread.h"
45 #include <libraw1394/raw1394.h>
46 #include "libutil/Time.h"
47
48
49     #define NB_THREADS 1
50     #define THREAD_RT  true
51     #define THREAD_PRIO 51
52     #define THREAD_SLEEP_US 2000
53    
54 using namespace Util;
55
56 DECLARE_GLOBAL_DEBUG_MODULE;
57
58 #define DIFF_CONSIDERED_LARGE (3027/2)
59 int PORT_TO_USE = 1;
60
61 int max_diff=-99999;
62 int min_diff= 99999;
63
64 int run=1;
65 static void sighandler (int sig)
66 {
67     run = 0;
68 }
69
70 class MyFunctor : public Functor
71 {
72 public:
73     MyFunctor() {}
74     virtual ~MyFunctor() {}
75
76     void operator() () {
77         printf("hello from the functor (%p)\n", this);
78     };
79 };
80
81 class CtrThread : public Util::RunnableInterface
82 {
83     public:
84         CtrThread(Ieee1394Service *s)
85         : m_service(s)
86         {};
87         virtual ~CtrThread() {};
88         virtual bool Init()
89         {
90             debugOutput(DEBUG_LEVEL_NORMAL, "(%p) Execute\n", this);
91             ctr=0;
92             ctr_dll=0;
93        
94             ctr_prev=0;
95             ctr_dll_prev=0;
96             m_handle = raw1394_new_handle_on_port( PORT_TO_USE );
97             if ( !m_handle ) {
98                 if ( !errno ) {
99                     debugFatal("libraw1394 not compatible\n");
100                 } else {
101                     debugFatal("Ieee1394Service::initialize: Could not get 1394 handle: %s\n",
102                         strerror(errno) );
103                     debugFatal("Is ieee1394 and raw1394 driver loaded?\n");
104                 }
105                 return false;
106             }
107             return true;
108         }
109         virtual bool Execute();
110
111         Ieee1394Service *m_service;
112         raw1394handle_t m_handle;
113         uint64_t ctr;
114         uint64_t ctr_dll;
115
116         uint64_t ctr_prev;
117         uint64_t ctr_dll_prev;
118 };
119
120 bool CtrThread::Execute() {
121     debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) Execute\n", this);
122    
123     SleepRelativeUsec(THREAD_SLEEP_US);
124
125     uint32_t cycle_timer;
126     uint64_t local_time;
127     // read the CTR 'raw' from a handle
128     // and read it from the 1394 service, which uses a DLL
129     int err = raw1394_read_cycle_timer(m_handle, &cycle_timer, &local_time);
130    
131     ctr_prev = ctr;
132     ctr_dll_prev = ctr_dll;
133    
134     ctr = CYCLE_TIMER_TO_TICKS( cycle_timer );
135     ctr_dll = m_service->getCycleTimerTicks(local_time);
136
137     if(err) {
138         debugError("(%p) CTR read error\n", this);
139     }
140     debugOutput ( DEBUG_LEVEL_VERBOSE,
141                 "(%p) Cycle timer: %011llu (%03us %04ucy %04uticks)\n",
142                 this, ctr,
143                 (unsigned int)TICKS_TO_SECS( ctr ),
144                 (unsigned int)TICKS_TO_CYCLES( ctr ),
145                 (unsigned int)TICKS_TO_OFFSET( ctr ) );
146     debugOutput ( DEBUG_LEVEL_VERBOSE,
147                 "(%p)    from DLL: %011llu (%03us %04ucy %04uticks)\n",
148                 this, ctr_dll,
149                 (unsigned int)TICKS_TO_SECS( ctr_dll ),
150                 (unsigned int)TICKS_TO_CYCLES( ctr_dll ),
151                 (unsigned int)TICKS_TO_OFFSET( ctr_dll ) );
152     int64_t diff = diffTicks(ctr, ctr_dll);
153     uint64_t abs_diff;
154
155     // not 100% thread safe, but will do
156     if (diff > max_diff) max_diff = diff;
157     if (diff < min_diff) min_diff = diff;
158
159     if (diff < 0) {
160         abs_diff = -diff;
161     } else {
162         abs_diff = diff;
163     }
164     debugOutput ( DEBUG_LEVEL_VERBOSE,
165                 "(%p)       diff: %s%011llu (%03us %04ucy %04uticks)\n", this,
166                 ((int64_t)abs_diff==diff?" ":"-"), abs_diff, (unsigned int)TICKS_TO_SECS( abs_diff ),
167                 (unsigned int)TICKS_TO_CYCLES( abs_diff ), (unsigned int)TICKS_TO_OFFSET( abs_diff ) );
168     if (abs_diff > DIFF_CONSIDERED_LARGE) {
169         debugWarning("(%p) Alert, large diff: %lld\n", this, diff);
170         debugOutput ( DEBUG_LEVEL_NORMAL,
171                     "(%p)  Cycle timer: %011llu (%03us %04ucy %04uticks)\n",
172                     this, ctr,
173                     (unsigned int)TICKS_TO_SECS( ctr ),
174                     (unsigned int)TICKS_TO_CYCLES( ctr ),
175                     (unsigned int)TICKS_TO_OFFSET( ctr ) );
176         debugOutput ( DEBUG_LEVEL_NORMAL,
177                     "(%p)   from DLL: %011llu (%03us %04ucy %04uticks)\n",
178                     this, ctr_dll,
179                     (unsigned int)TICKS_TO_SECS( ctr_dll ),
180                     (unsigned int)TICKS_TO_CYCLES( ctr_dll ),
181                     (unsigned int)TICKS_TO_OFFSET( ctr_dll ) );
182     }
183    
184     diff = diffTicks(ctr, ctr_prev);
185     if (diff < 0) {
186         debugWarning("(%p) Alert, non-monotonic ctr (direct): %llu - %llu = %lld\n",
187                      this, ctr, ctr_prev, diff);
188         debugOutput ( DEBUG_LEVEL_NORMAL,
189                     "(%p)  Cycle timer now : %011llu (%03us %04ucy %04uticks)\n",
190                     this, ctr,
191                     (unsigned int)TICKS_TO_SECS( ctr ),
192                     (unsigned int)TICKS_TO_CYCLES( ctr ),
193                     (unsigned int)TICKS_TO_OFFSET( ctr ) );
194         debugOutput ( DEBUG_LEVEL_NORMAL,
195                     "(%p)  Cycle timer prev: %011llu (%03us %04ucy %04uticks)\n",
196                     this, ctr_prev,
197                     (unsigned int)TICKS_TO_SECS( ctr_prev ),
198                     (unsigned int)TICKS_TO_CYCLES( ctr_prev ),
199                     (unsigned int)TICKS_TO_OFFSET( ctr_prev ) );
200     }
201     diff = diffTicks(ctr_dll, ctr_dll_prev);
202     if (diff < 0) {
203         debugWarning("(%p) Alert, non-monotonic ctr (dll): %llu - %llu = %lld\n",
204                      this, ctr_dll, ctr_dll_prev, diff);
205         debugOutput ( DEBUG_LEVEL_NORMAL,
206                     "(%p)  Cycle timer now : %011llu (%03us %04ucy %04uticks)\n",
207                     this, ctr_dll,
208                     (unsigned int)TICKS_TO_SECS( ctr_dll ),
209                     (unsigned int)TICKS_TO_CYCLES( ctr_dll ),
210                     (unsigned int)TICKS_TO_OFFSET( ctr_dll ) );
211         debugOutput ( DEBUG_LEVEL_NORMAL,
212                     "(%p)  Cycle timer prev: %011llu (%03us %04ucy %04uticks)\n",
213                     this, ctr_dll_prev,
214                     (unsigned int)TICKS_TO_SECS( ctr_dll_prev ),
215                     (unsigned int)TICKS_TO_CYCLES( ctr_dll_prev ),
216                     (unsigned int)TICKS_TO_OFFSET( ctr_dll_prev ) );
217     }
218    
219     // check some calculations
220     uint32_t tmp_orig = m_service->getCycleTimer();
221     uint32_t tmp_ticks = CYCLE_TIMER_TO_TICKS(tmp_orig);
222     uint32_t tmp_ctr = TICKS_TO_CYCLE_TIMER(tmp_ticks);
223    
224     if (tmp_orig != tmp_ctr) {
225         debugError("CTR => TICKS => CTR failed\n");
226         debugOutput ( DEBUG_LEVEL_VERBOSE,
227                     "(%p) orig CTR : %08X (%03us %04ucy %04uticks)\n",
228                     this, (uint32_t)tmp_orig,
229                     (unsigned int)CYCLE_TIMER_GET_SECS( tmp_orig ),
230                     (unsigned int)CYCLE_TIMER_GET_CYCLES( tmp_orig ),
231                     (unsigned int)CYCLE_TIMER_GET_OFFSET( tmp_orig ) );
232         debugOutput ( DEBUG_LEVEL_VERBOSE,
233                     "(%p) TICKS: %011llu (%03us %04ucy %04uticks)\n",
234                     this, tmp_ticks,
235                     (unsigned int)TICKS_TO_SECS( tmp_ticks ),
236                     (unsigned int)TICKS_TO_CYCLES( tmp_ticks ),
237                     (unsigned int)TICKS_TO_OFFSET( tmp_ticks ) );
238         debugOutput ( DEBUG_LEVEL_VERBOSE,
239                     "(%p) new CTR : %08X (%03us %04ucy %04uticks)\n",
240                     this, (uint32_t)tmp_ctr,
241                     (unsigned int)CYCLE_TIMER_GET_SECS( tmp_ctr ),
242                     (unsigned int)CYCLE_TIMER_GET_CYCLES( tmp_ctr ),
243                     (unsigned int)CYCLE_TIMER_GET_OFFSET( tmp_ctr ) );
244     }
245    
246     debugOutput ( DEBUG_LEVEL_VERBOSE,
247                 "(%p)  wait...\n", this);
248     return true;
249 }
250
251 int main(int argc, char *argv[])
252 {
253     int i=0;
254     setDebugLevel(DEBUG_LEVEL_NORMAL);
255     signal (SIGINT, sighandler);
256     signal (SIGPIPE, sighandler);
257
258
259     printf("FFADO Ieee1394Service test application\n");
260
261     Ieee1394Service *m_service=NULL;
262
263     m_service = new Ieee1394Service();
264     m_service->setVerboseLevel(DEBUG_LEVEL_VERBOSE);
265     m_service->initialize(PORT_TO_USE);
266     m_service->setThreadParameters(true, 60);
267
268     MyFunctor *test_busreset=new MyFunctor();
269
270     printf(" adding (%p) as busreset handler\n", test_busreset);
271
272     m_service->addBusResetHandler(test_busreset);
273
274     nodeaddr_t addr =  m_service->findFreeARMBlock(0x0000FFFFE0000000ULL, 4, 4 );
275
276     ARMHandler *test_arm=new ARMHandler(addr,
277                          4,
278                          RAW1394_ARM_READ | RAW1394_ARM_WRITE | RAW1394_ARM_LOCK,
279                          RAW1394_ARM_READ | RAW1394_ARM_WRITE | RAW1394_ARM_LOCK,
280                          0);
281
282     printf(" adding (%p) as arm handler\n", test_arm);
283
284     if (!m_service->registerARMHandler(test_arm)) {
285         printf("  failed\n");
286     }
287
288     addr =  m_service->findFreeARMBlock(0x0000FFFFE0000000ULL, 4, 4 );
289
290     ARMHandler *test_arm2=new ARMHandler(addr,
291                          4,
292                          RAW1394_ARM_READ | RAW1394_ARM_WRITE | RAW1394_ARM_LOCK,
293                          RAW1394_ARM_READ | RAW1394_ARM_WRITE | RAW1394_ARM_LOCK,
294                          0);
295
296     printf(" adding (%p) as arm handler\n", test_arm2);
297
298     if (!m_service->registerARMHandler(test_arm2)) {
299         printf("  failed\n");
300     }
301
302     CtrThread *thread_runners[NB_THREADS];
303     Thread* threads[NB_THREADS];
304     for (i=0; i < NB_THREADS; i++) {
305         thread_runners[i] = new CtrThread(m_service);
306         if (thread_runners[i] == NULL) {
307             debugError("could not create thread runner %d\n", i);
308             exit(-1);
309         }
310         threads[i] = new PosixThread(thread_runners[i], THREAD_RT, THREAD_PRIO, PTHREAD_CANCEL_DEFERRED);
311         if (threads[i] == NULL) {
312             debugError("could not create thread %d\n", i);
313             exit(-1);
314         }
315     }
316    
317     for (i=0; i < NB_THREADS; i++) {
318         threads[i]->Start();
319     }
320
321     i=0;
322     while(run) {
323         i++;
324         debugOutput(DEBUG_LEVEL_NORMAL, "%08d: alive, (max: %6d, min: %6d)\n", i, max_diff, min_diff);
325         m_service->show();
326         sleep(5);
327     }
328
329     for (i=0; i < NB_THREADS; i++) {
330         threads[i]->Stop();
331     }
332
333     for (i=0; i < NB_THREADS; i++) {
334         delete threads[i];
335         delete thread_runners[i];
336     }
337
338     delete m_service;
339     delete test_busreset;
340     delete test_arm;
341     delete test_arm2;
342
343     printf("Bye...\n");
344
345     return EXIT_SUCCESS;
346 }
Note: See TracBrowser for help on using the browser.