root/branches/streaming-rework/tests/SytMonitor.cpp

Revision 360, 6.1 kB (checked in by pieterpalmers, 16 years ago)

- temporary commit to backup some work

- Started a framework to synchronize IsoHandlers? to

any generic TimeSource?. The idea is to introduce
one overall time reference, and resynchronize all
other timed events to this time source.
This will, on the long run, allow:

  • combining devices on multiple FW busses together,
    as these are not synched by hardware.
  • synchronizing to the system clock
  • synchronizing to any other time source (e.g.
    when implementing a jackd client, i.e. using
    the freebob devices as jackd clients).

- Implemented a realtime safe way to read the cycle

timer for an IsoHandler?. (+ test application)

- Implemented tests/test-sytmonitor:

Monitors 2 or more channels and reports the average
SYT timestamp difference between both.

- Messed around with SYT timestamping for AMDTP. Doesn't

work (yet).

Line 
1 /* $Id$ */
2
3 /*
4  *   FreeBob Streaming API
5  *   FreeBob = Firewire (pro-)audio for linux
6  *
7  *   http://freebob.sf.net
8  *
9  *   Copyright (C) 2005,2006,2007 Pieter Palmers <pieterpalmers@users.sourceforge.net>
10  *
11  *   This program is free software {} you can redistribute it and/or modify
12  *   it under the terms of the GNU General Public License as published by
13  *   the Free Software Foundation {} either version 2 of the License, or
14  *   (at your option) any later version.
15  *
16  *   This program is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY {} without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with this program {} if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  *
26  *
27  */
28
29 #include "SytMonitor.h"
30 #include "src/libstreaming/IsoStream.h"
31
32 #include <netinet/in.h>
33 #include <assert.h>
34
35
36 IMPL_DEBUG_MODULE( SytMonitor, SytMonitor, DEBUG_LEVEL_NORMAL );
37
38
39 /* --------------------- RECEIVE ----------------------- */
40
41 SytMonitor::SytMonitor(int port)
42     : IsoStream(IsoStream::EST_Receive, port) {
43     m_cinfo_buffer=freebob_ringbuffer_create(16384*sizeof(struct cycle_info));
44
45 }
46
47 SytMonitor::~SytMonitor() {
48         freebob_ringbuffer_free(m_cinfo_buffer);
49
50 }
51
52 enum raw1394_iso_disposition
53 SytMonitor::putPacket(unsigned char *data, unsigned int length,
54                   unsigned char channel, unsigned char tag, unsigned char sy,
55                   unsigned int cycle, unsigned int dropped) {
56     enum raw1394_iso_disposition retval=RAW1394_ISO_OK;
57    
58     struct iec61883_packet *packet = (struct iec61883_packet *) data;
59     unsigned int syt_timestamp=ntohs(packet->syt);
60     unsigned int m_full_timestamp;
61    
62     bool wraparound_occurred=false;
63     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"%2u,%2u: CY=%4u, SYT=%08X (%3u secs + %4u cycles + %04u ticks)\n",
64         m_port,channel,
65         cycle,syt_timestamp,
66         CYCLE_COUNTER_GET_SECS(syt_timestamp),
67         CYCLE_COUNTER_GET_CYCLES(syt_timestamp),
68         CYCLE_COUNTER_GET_OFFSET(syt_timestamp)
69        
70         );
71    
72     // reconstruct the full cycle
73     unsigned int cc_ticks=m_handler->getCycleCounter();
74     unsigned int cc_cycles=TICKS_TO_CYCLES(cc_ticks);
75    
76     unsigned int cc_seconds=TICKS_TO_SECS(cc_ticks);
77    
78     // the cyclecounter has wrapped since this packet was received
79     // we want cc_seconds to reflect the 'seconds' at the point this
80     // was received
81     if (cycle>cc_cycles) cc_seconds--;
82
83      // reconstruct the top part of the timestamp using the current cycle number
84     unsigned int now_cycle_masked=cycle & 0xF;
85     unsigned int syt_cycle=CYCLE_COUNTER_GET_CYCLES(syt_timestamp);
86    
87     // if this is true, wraparound has occurred, undo this wraparound
88     if(syt_cycle<now_cycle_masked) syt_cycle += 0x10;
89    
90     // this is the difference in cycles wrt the cycle the
91     // timestamp was received
92     unsigned int delta_cycles=syt_cycle-now_cycle_masked;
93    
94     // reconstruct the cycle part of the timestamp
95     unsigned int new_cycles=cycle + delta_cycles;
96    
97     // if the cycles cause a wraparound of the cycle counter,
98     // perform this wraparound
99     if(new_cycles>7999) {
100         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
101             "Detected wraparound: %d + %d = %d\n",
102             cycle,delta_cycles,new_cycles);
103        
104         new_cycles-=8000; // wrap around
105         wraparound_occurred=true;
106        
107     }
108    
109     m_full_timestamp = (new_cycles) << 12;
110    
111     // now add the offset part on top of that
112     m_full_timestamp |= (syt_timestamp & 0xFFF);
113    
114     // and the seconds part
115     // if the timestamp causes a wraparound of the cycle counter,
116     // the timestamp lies in the next second
117     // if it didn't, the timestamp lies in this second
118     if (wraparound_occurred) {
119         m_full_timestamp |= ((cc_seconds+1 << 25) & 0xFE000000);
120     } else {
121         m_full_timestamp |= ((cc_seconds << 25) & 0xFE000000);
122     }
123
124     struct cycle_info cif;
125     cif.cycle=cycle;
126     cif.seconds=cc_seconds;
127    
128     cif.syt=packet->syt;
129     cif.full_syt=m_full_timestamp;
130    
131     // now we reconstruct the presentation time
132     cif.pres_seconds = CYCLE_COUNTER_GET_SECS(m_full_timestamp);
133     cif.pres_cycle   = CYCLE_COUNTER_GET_CYCLES(m_full_timestamp);
134     cif.pres_offset  = CYCLE_COUNTER_GET_OFFSET(m_full_timestamp);
135     cif.pres_ticks   = CYCLE_COUNTER_TO_TICKS(m_full_timestamp);
136    
137     if (wraparound_occurred) {
138         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"    (P: %08X, R: %08X)\n",
139             m_full_timestamp, syt_timestamp);
140     }
141    
142     if (cif.pres_offset != (syt_timestamp & 0xFFF)) {
143         debugOutput(DEBUG_LEVEL_NORMAL,"P-offset error: %04X != %04X (P: %08X, R: %08X)\n",
144         cif.pres_offset, syt_timestamp & 0xFFF, m_full_timestamp, syt_timestamp);
145     }
146     if ((cif.pres_cycle & 0xF) != ((syt_timestamp & 0xF000)>>12)) {
147         debugOutput(DEBUG_LEVEL_NORMAL,"P-cycle error: %01X != %01X (P: %08X, R: %08X)\n",
148             cif.pres_cycle &0xF, (syt_timestamp & 0xF000)>>12, m_full_timestamp, syt_timestamp);
149     }
150    
151     putCycleInfo(&cif);
152
153     return retval;
154 }
155
156 bool SytMonitor::putCycleInfo(struct cycle_info *cif) {
157     if(freebob_ringbuffer_write(m_cinfo_buffer,(char *)cif,sizeof(struct cycle_info))
158         !=sizeof(struct cycle_info)) {
159         return false;
160     }
161     return true;   
162 }
163
164 bool SytMonitor::readNextCycleInfo(struct cycle_info *cif) {
165     if(freebob_ringbuffer_peek(m_cinfo_buffer,(char *)cif,sizeof(struct cycle_info))
166         !=sizeof(struct cycle_info)) {
167         return false;
168     }
169     return true;
170    
171 }
172
173 bool SytMonitor::consumeNextCycleInfo() {
174     struct cycle_info cif;
175     if(freebob_ringbuffer_read(m_cinfo_buffer,(char *)&cif,sizeof(struct cycle_info))
176         !=sizeof(struct cycle_info)) {
177         return false;
178     }
179     return true;
180 }
181
182 void SytMonitor::dumpInfo()
183 {
184     IsoStream::dumpInfo();
185         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Ringbuffer fill: %d\n",
186            freebob_ringbuffer_read_space(m_cinfo_buffer)/sizeof(struct cycle_info));
187 };
Note: See TracBrowser for help on using the browser.