e2a21a2a7d8bad7a082a53134837a15c1bea740d
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

1) /*
2)  * FlexiPix library
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

3)  * !version: 1.0.6! !date: 2010-12-30!
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

245) FLP_THREAD_FUNC(flp_displayer_thread)
Stefan Schuermans v1.0.0

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

251) 
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

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

Stefan Schuermans authored 13 years ago

300) 
Stefan Schuermans v1.0.6

Stefan Schuermans authored 13 years ago

301)   FLP_THREAD_RETURN(NULL);