aa3270aa371083e5c3c065a58b1551bfea58b4db
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

1) /*
2)  * FlexiPix library
3)  *
Stefan Schuermans removed version information...

Stefan Schuermans authored 13 years ago

4)  * Copyright 2010-2011 Stefan Schuermans <stefan schuermans info>
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

5)  *
6)  * This program is free software: you can redistribute it and/or modify
7)  * it under the terms of the GNU General Public License as published by
8)  * the Free Software Foundation, version 3 of the License.
9)  *
10)  *
11)  * This program is distributed in the hope that it will be useful,
12)  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13)  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14)  * GNU General Public License for more details.
15)  *
16)  * You should have received a copy of the GNU Lesser General Public License
17)  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18)  */
19) 
20) #include <sys/time.h>
21) #include <stdlib.h>
22) 
23) #include <flexipix/display.h>
24) #include <flexipix/displayer.h>
25) #include <flexipix/msg.h>
26) #include <flexipix/types.h>
27) #include <intern/displayer.h>
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

28) #include <intern/thread.h>
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

29) #include <intern/types.h>
30) 
31) /**
32)  * \brief create a new FlexiPix displayer
33)  *
34)  * A displayer manages a display and ensures that a the current
35)  * image data is sent often enough to the distributors so
36)  * that the pixels do detect a timeout and turn off automatically.
37)  * The displayer uses a thread to do this.
38)  * Initially, the new displayer is inactive and has to be activated
39)  * using flp_displayer_activate().
40)  *
41)  * \param[in] sz_config_file name of config file to read
42)  * \param[in] p_msg_func message callback function or NULL
43)  * \param[in] p_msg_ctx user context for message callback
44)  * \return pointer to new FlexiPix displayer on success
45)  *         or NULL on error
46)  */
47) flp_displayer_t *flp_displayer_create(const char *sz_config_file,
48)                                       flp_msg_func_p_t p_msg_func,
49)                                       void *p_msg_ctx)
50) {
51)   flp_displayer_t *p_displayer;
52) 
53)   /* set up basic structure and display */
54) 
55)   /* create displayer structure */
56)   p_displayer = (flp_displayer_t *)calloc(1, sizeof (flp_displayer_t));
57)   if (!p_displayer) {
58)     if (p_msg_func)
59)       p_msg_func(p_msg_ctx, flp_msg_type_err,
60)                  "out of memory\n");
61)     return NULL;
62)   }
63) 
64)   /* set up flags */
65)   p_displayer->active = 0; /* not sending data to distributors */
66)   p_displayer->send   = 1; /* send first data as soon as active */
67)   p_displayer->end    = 0; /* do not end yet */
68) 
69)   /* set up managed display */
70)   p_displayer->p_display = flp_display_create(sz_config_file,
71)                                               p_msg_func, p_msg_ctx);
72)   if (!p_displayer->p_display) {
73)     free(p_displayer);
74)     if (p_msg_func)
75)       p_msg_func(p_msg_ctx, flp_msg_type_err,
76)                  "could not create display\n");
77)     return NULL;
78)   }
79) 
80)   /* set up output thread */
81) 
82)   /* initialize mutex */
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

83)   if (!flp_thread_mutex_init(&p_displayer->mtx)) {
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

84)     flp_display_free(p_displayer->p_display);
85)     free(p_displayer);
86)     if (p_msg_func)
87)       p_msg_func(p_msg_ctx, flp_msg_type_err,
88)                  "could not initialize mutex\n");
89)     return NULL;
90)   }
91) 
92)   /* initialize condition */
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

93)   if (!flp_thread_cond_init(&p_displayer->cond)) {
94)     flp_thread_mutex_destroy(&p_displayer->mtx);
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

95)     flp_display_free(p_displayer->p_display);
96)     free(p_displayer);
97)     if (p_msg_func)
98)       p_msg_func(p_msg_ctx, flp_msg_type_err,
99)                  "could not initialize condition\n");
100)     return NULL;
101)   }
102) 
103)   /* create thread */
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

104)   if (!flp_thread_create(&p_displayer->tid, flp_displayer_thread,
105)                         (void *)p_displayer)) {
106)     flp_thread_cond_destroy(&p_displayer->cond);
107)     flp_thread_mutex_destroy(&p_displayer->mtx);
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

108)     flp_display_free(p_displayer->p_display);
109)     free(p_displayer);
110)     if (p_msg_func)
111)       p_msg_func(p_msg_ctx, flp_msg_type_err,
112)                  "could not create thread\n");
113)     return NULL;
114)   }
115) 
116)   return p_displayer;
117) }
118) 
119) /**
120)  * \brief free a FlexiPix displayer
121)  *
122)  * \param[in] p_displayer pointer to FlexiPix displayer
123)  */
124) void flp_displayer_free(flp_displayer_t *p_displayer)
125) {
126)   /* tear down thread */
127)   p_displayer->end = 1;
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

128)   flp_thread_cond_signal(&p_displayer->cond);
129)   flp_thread_join(p_displayer->tid);
130)   flp_thread_cond_destroy(&p_displayer->cond);
131)   flp_thread_mutex_destroy(&p_displayer->mtx);
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

132) 
133)   /* free managed display */
134)   flp_display_free(p_displayer->p_display);
135) 
136)   /* free basic structure */
137)   free(p_displayer);
138) }
139) 
140) /**
141)  * \brief get size of display managed by displayer
142)  *
143)  * \param[in] p_displayer pointer to FlexiPix displayer
144)  * \param[out] p_width width of display
145)  * \param[out] p_height height of display
146)  */
147) void flp_displayer_get_size(flp_displayer_t *p_displayer,
148)                             unsigned int *p_width, unsigned int *p_height)
149) {
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

150)   flp_thread_mutex_lock(&p_displayer->mtx);
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

151)   flp_display_get_size(p_displayer->p_display, p_width, p_height);
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

152)   flp_thread_mutex_unlock(&p_displayer->mtx);
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

153) }
154) 
155) /**
156)  * \brief activate the displayer
157)  *
158)  * set the displayer to active, i.e. make it send image data
159)  * to the distributors automatically,
160)  * this function might trigger sending of data if the last
161)  * sending time was too long ago
162)  *
163)  * \param[in] p_displayer pointer to FlexiPix displayer
164)  */
165) void flp_displayer_activate(flp_displayer_t *p_displayer)
166) {
167)   p_displayer->active = 1;
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

168)   flp_thread_cond_signal(&p_displayer->cond);
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

169) }
170) 
171) /**
172)  * \brief deactivate the displayer
173)  *
174)  * set the displayer to deactive, i.e. prevent it from sening image
175)  * data to the distributors automatically,
176)  *
177)  * \param[in] p_displayer pointer to FlexiPix displayer
178)  */
179) void flp_displayer_deactivate(flp_displayer_t *p_displayer)
180) {
181)   p_displayer->active = 0;
182)   /* no need to signal condition: thread does not need to do something yet */
183) }
184) 
185) /**
186)  * \brief clear image data to output on FlexiPix displayer
187)  *
188)  * clears the stored image data
189)  *
190)  * \param[in] p_displayer pointer to FlexiPix displayer
191)  */
192) void flp_displayer_data_clear(flp_displayer_t *p_displayer)
193) {
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

194)   flp_thread_mutex_lock(&p_displayer->mtx);
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

195)   flp_display_data_clear(p_displayer->p_display);
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

196)   flp_thread_mutex_unlock(&p_displayer->mtx);
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

197) }
198) 
199) /**
200)  * \brief set image data to output on FlexiPix display
201)  *
202)  * updates (part of) the stored image data
203)  *
204)  * \param[in] p_displayer pointer to FlexiPix displayer
205)  * \param[in] p_data pointer to rectangular section of image data,
206)  *                   pixels need to be in R8G8B8 format
207)  * \param[in] stride_x stride between two pixels in X direction
208)  * \param[in] stride_y stride between two pixels in Y direction
209)  * \param[in] x X coordinate of left side of rectangular area
210)  * \param[in] y Y coordinate of top side of rectangular area
211)  * \param[in] width with of rectangular area
212)  * \param[in] height height of rectangular area
213)  */
214) void flp_displayer_data(flp_displayer_t *p_displayer, flp_u8_t *p_data,
215)                         int stride_x, int stride_y,
216)                         unsigned int x, unsigned int y,
217)                         unsigned int width, unsigned int height)
218) {
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

219)   flp_thread_mutex_lock(&p_displayer->mtx);
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

220)   flp_display_data(p_displayer->p_display, p_data, stride_x, stride_y,
221)                    x, y, width, height);
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

222)   flp_thread_mutex_unlock(&p_displayer->mtx);
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

223) }
224) 
225) /**
226)  * \brief trigger immediate sending of new image data to distributors
227)  *
228)  * this only works if the displayer is active
229)  *
230)  * \param[in] p_displayer pointer to FlexiPix displayer
231)  */
232) void flp_displayer_send(flp_displayer_t *p_displayer)
233) {
234)   p_displayer->send = 1;
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

235)   flp_thread_cond_signal(&p_displayer->cond);
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

236) }
237) 
238) /**
239)  * \brief output thread of displayer object
240)  *
241)  * \param[in] vp_displayer pointer to displayer object
242)  * \return unused, always NULL
243)  */
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

244) FLP_THREAD_FUNC(flp_displayer_thread)
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

245) {
246)   flp_displayer_t *p_displayer = (flp_displayer_t *)vp_displayer;
247)   struct timeval last, now, delta;
248)   int timed_send;
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

249)   int interval_ms = FLP_MCUF_MAX_FRAME_INTERVAL_MS;
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

250) 
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

251)   flp_thread_mutex_lock(&p_displayer->mtx);
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

252) 
253)   gettimeofday(&last, NULL); /* initialize last to some valid time */
254) 
255)   /* while thread shall not end */
256)   while (!p_displayer->end) {
257) 
258)     /* active */
259)     if (p_displayer->active) {
260) 
261)       /* get current time */
262)       gettimeofday(&now, NULL);
263)       /* get time since sending last frame */
264)       delta.tv_sec = now.tv_sec - last.tv_sec;
265)       delta.tv_usec = now.tv_usec - last.tv_usec;
266)       if (delta.tv_usec < 0) {
267)         delta.tv_usec += 1000000;
268)         ++delta.tv_sec;
269)       }
270)       /* check if late enough for timed send */
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

271)       timed_send = delta.tv_sec > interval_ms / 1000
272)                  || (delta.tv_sec == interval_ms / 1000
273)                      && delta.tv_usec >= (interval_ms % 1000) * 1000);
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

274) 
275)       /* send if send requested or late enough */
276)       if (p_displayer->send || timed_send) {
277)         flp_display_send(p_displayer->p_display); /* send */
278)         last = now;                               /* remember last send time */
279)         p_displayer->send = 0;                    /* clear send request */
280)       }
281) 
282)       /* sleep until next frame has to be sent */
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

283)       flp_thread_cond_timedwait(&p_displayer->cond, &p_displayer->mtx,
284)                                 &last, interval_ms);
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

285) 
286)     } /* if (p_displayer->active) */
287) 
288)     /* inactive */
289)     else {
290) 
291)       /* sleep */
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

292)       flp_thread_cond_wait(&p_displayer->cond, &p_displayer->mtx);
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

293) 
294)     } /* if (p_displayer->active) ... else */
295) 
296)   } /* while(!p_displayer->end) */
297) 
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

298)   flp_thread_mutex_unlock(&p_displayer->mtx);
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

299) 
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

300)   FLP_THREAD_RETURN(NULL);