File: remote.c

package info (click to toggle)
brickos 0.9.0-1
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 1,700 kB
  • ctags: 1,727
  • sloc: ansic: 9,139; cpp: 860; makefile: 717; asm: 693; sh: 123; perl: 61
file content (170 lines) | stat: -rw-r--r-- 4,240 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*! \file   remote.c
    \brief  Implementation: LEGO Infrared Remote Control and data structures
    \author Ross Crawford <rcrawford@csi.com>
*/

/*
 * Copyright (c) 2001 Ross Crawford
 *
 *  The contents of this file are subject to the Mozilla Public License
 *  Version 1.0 (the "License"); you may not use this file except in
 *  compliance with the License. You may obtain a copy of the License at
 *  http://www.mozilla.org/MPL/
 *
 *  Software distributed under the License is distributed on an "AS IS"
 *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 *  License for the specific language governing rights and limitations
 *  under the License.
 */

/*
 *  2002.04.23 - Ted Hess <thess@kitschensync.net>
 *
 *  - Integrated into legOS 0.2.6. Added lr_startup(), lr_shutdown()
 *    Release input buffer while processing keys
 *
 */

#include <remote.h>

#if defined(CONF_LR_HANDLER)

#include <sys/lcd.h>
#include <unistd.h>
#include <lnp/lnp.h>
#include <time.h>
#include <dmotor.h>
#include <dsound.h>
#include <conio.h>
#include <tm.h>

///////////////////////////////////////////////////////////////////////////////
//
// Internal Variables
//
///////////////////////////////////////////////////////////////////////////////

time_t lr_timeoff;         // all keys off if no data received before...
unsigned int lr_curkeys;   // mask of keys currently "ON"

unsigned int lr_data;      // lnp data byte
int lr_dataready = 0;      // lr_data valid?

lr_handler_t lr_handler;   // the user event handler
tid_t lr_tid;     // Button dispatch thread

///////////////////////////////////////////////////////////////////////////////
//
// Functions
//
///////////////////////////////////////////////////////////////////////////////

//! Called from LNP when key data available
void lr_getdata(unsigned int x)
{
  // If previous data hasn't been processed yet, this will be lost
  if (lr_dataready == 0)
  {
    lr_data = x;
    lr_dataready = 1;
  }

  // Reset timeout
  lr_timeoff = get_system_up_time() + LR_TIMEOUT;
}


//! Key state dispatcher (keyup / keydown)
void lr_process(unsigned int lr_keys)
{
  unsigned int keys_on, keys_off, common_keys, k;

  // If keys pressed has changed
  if (lr_keys != lr_curkeys) {

    // Get mask of keys pressed & released since last event
    common_keys = (lr_keys & lr_curkeys);
    keys_on = lr_keys & ~common_keys;
    keys_off = lr_curkeys & ~common_keys;

    // send event to user handler for each change
    if (lr_handler) {
      for (k=1; k; k<<=1) {
        if (keys_on & k)
          lr_handler(LREVT_KEYON,k);
        if (keys_off & k)
          lr_handler(LREVT_KEYOFF,k);
      }
    }

    // store key mask for next time
    lr_curkeys = lr_keys;
  }
  return;
}
 
wakeup_t lr_waitdata(wakeup_t data)
{
  // if time runs out, fake "all keys off"
  if (get_system_up_time() > lr_timeoff && lr_curkeys != 0) {
    lr_data = 0;
    lr_dataready = 1;
  }

  // tell lr_thread whether there's any data available
  return lr_dataready;
}

//! lr_thread just sits waiting for data, processing it as it arrives
int lr_thread(int argc, char *argv[]) {
  unsigned int lr_keys;
  while(!shutdown_requested()) {
    if (wait_event(&lr_waitdata, 0) != 0) {
      // Snatch input before calling user handler
      lr_keys = lr_data;
      // Have local copy of input data, allow buffer to refill
      lr_dataready = 0;
      // Call user handler
      lr_process(lr_keys);
    }
  }
  return 0;
}

//! Init remote key dispatcher
void lr_init()
{
  lnp_remote_set_handler(lr_getdata);
  return;
}


//! Startup lr_thread and init protocol handler.
void lr_startup()
{
  // start with all keys off, set initial timeout, clear user handler
  lr_curkeys = 0;
  lr_timeoff = get_system_up_time() + LR_TIMEOUT;
  lr_handler = NULL;

  // Start watcher thread, then tell lnp where we want remote data to go
  lr_tid = execi(&lr_thread,0,0,PRIO_HIGHEST,DEFAULT_STACK_SIZE);
  lr_init();

  return;
}

//! Shutdown protocol handler and terminate thread?
void lr_shutdown()
{
  // Disconnect protocol handler
  lnp_remote_set_handler(LNP_DUMMY_REMOTE);
  lr_set_handler(LR_DUMMY_HANDLER);

  // terminate thread
  kill(lr_tid);

  return;
}

#endif  // CONF_LR_HANDLER