Root/userspace/nanonote/gpio.ccp

1#pypp 0
2// Iris: micro-kernel for a capability-based operating system.
3// boot-programs/nanonote-gpio.ccp: gpio devices on the nanonote.
4// Copyright 2009 Bas Wijnen <wijnen@debian.org>
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, either version 3 of the License, or
9// (at your option) any later version.
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 General Public License
17// along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19#include "devices.hh"
20#define ARCH
21#include "arch.hh"
22#include "keys.hh"
23
24#define QI
25#define SCAN_INTERVAL HZ / 50
26
27class DevKbd:
28    static unsigned const NUM_COLS = 8
29    static unsigned const NUM_ROWS = 8
30    static unsigned const COLS_PORT = 2
31    static unsigned const ROWS_PORT = 3
32    static unsigned const ALL_COLS = 0x0003fc00
33    static unsigned const ALL_ROWS = 0x05fc0000
34    static unsigned const COLS[NUM_COLS]
35    static unsigned const ROWS[NUM_ROWS]
36    static unsigned const encode[NUM_ROWS][NUM_COLS]
37    static unsigned const NUM_KEYS = 58
38    static unsigned const keys[NUM_KEYS]
39    unsigned state[NUM_COLS]
40    Iris::Cap event
41    bool is_active
42    bool is_scanning
43    public:
44    unsigned size ():
45        return NUM_KEYS
46    void send_keys (unsigned first, Iris::Cap target):
47        unsigned d[4]
48        unsigned i
49        for i = 0; first + i < NUM_KEYS && i < 4; ++i:
50            d[i] = keys[first + i]
51        for ; i < 4; ++i:
52            d[i] = ~0
53        target.invoke (Iris::Num (d[0], d[1]), Iris::Num (d[2], d[3]))
54    bool scanning ():
55        return is_scanning
56    void inactive ():
57        if is_active:
58            Iris::free_cap (event)
59        is_active = false
60    void check (unsigned col, unsigned rowdata):
61        for unsigned r = 0; r < NUM_ROWS; ++r:
62            if !((rowdata ^ state[col]) & (1 << ROWS[r])):
63                continue
64            unsigned code = encode[r][col]
65            if rowdata & (1 << ROWS[r]):
66                code |= Iris::Keyboard::RELEASE
67            if is_active:
68                event.invoke (code)
69        state[col] = rowdata
70    void delay ():
71        for unsigned i = 0; i < 10000; ++i:
72            gpio_set (0, 0)
73    void scan ():
74        unsigned r
75        gpio_mask_irq (ROWS_PORT, ALL_ROWS)
76        is_scanning = false
77        if !is_active:
78            return
79        for unsigned c = 0; c < NUM_COLS; ++c:
80            gpio_as_input (COLS_PORT, ALL_COLS & ~(1 << COLS[c]))
81            gpio_as_output (COLS_PORT, 1 << COLS[c])
82            if c > 0:
83                check (c - 1, r)
84                delay ()
85            else:
86                check (0, state[0])
87                delay ()
88            r = gpio_get_port (ROWS_PORT) & ALL_ROWS
89            if r != ALL_ROWS:
90                is_scanning = true
91        gpio_as_output (COLS_PORT, ALL_COLS)
92        check (NUM_COLS - 1, r)
93        delay ()
94        r = gpio_get_port (ROWS_PORT) & ALL_ROWS
95        unsigned high = 0, low = 0
96        for unsigned i = 0; i < NUM_ROWS; ++i:
97            if r & (1 << ROWS[i]):
98                low |= 1 << ROWS[i]
99            else:
100                high |= 1 << ROWS[i]
101        gpio_as_interrupt (ROWS_PORT, high, true, true)
102        gpio_as_interrupt (ROWS_PORT, low, false, true)
103        gpio_unmask_irq (ROWS_PORT, ALL_ROWS)
104    void active (Iris::Cap cb):
105        inactive ()
106        event = cb
107        is_active = true
108        for unsigned c = 0; c < NUM_COLS; ++c:
109            state[c] = ALL_ROWS
110        scan ()
111    DevKbd ():
112        is_active = false
113        gpio_as_gpio (COLS_PORT, ALL_COLS)
114        gpio_as_gpio (ROWS_PORT, ALL_ROWS)
115        gpio_clear (COLS_PORT, ALL_COLS)
116        gpio_as_output (COLS_PORT, ALL_COLS)
117        gpio_as_input (ROWS_PORT, ALL_ROWS)
118        gpio_enable_pull (ROWS_PORT, ALL_ROWS)
119        for unsigned i = 0; i < NUM_COLS; ++i:
120            state[i] = ALL_ROWS
121        scan ()
122
123unsigned const DevKbd::COLS[NUM_COLS] = { 10, 11, 12, 13, 14, 15, 16, 17 }
124unsigned const DevKbd::ROWS[NUM_ROWS] = { 18, 19, 20, 21, 22, 23, 24, 26 }
125unsigned const DevKbd::encode[NUM_ROWS][NUM_COLS] = {
126    #ifdef QI
127    { Key::F1, Key::F2, Key::F3, Key::F4, Key::F5, Key::F6, Key::F7, ~0 },
128    { Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I },
129    { Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K },
130    { Key::ESCAPE, Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M },
131    { Key::TAB, Key::CAPS_LOCK, Key::BACKSLASH, Key::QUOTE, Key::COMMA, Key::PERIOD, Key::SLASH, Key::UP },
132    { Key::O, Key::L, Key::EQUALS, Key::SPECIAL + 0, Key::SPACE, Key::RIGHT_LOGO, Key::RIGHT_CONTROL, Key::LEFT },
133    { Key::F8, Key::P, Key::BACKSPACE, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT },
134    { Key::LEFT_SHIFT, Key::LEFT_ALT, Key::FN, ~0, ~0, ~0, ~0, ~0 }
135    #else
136    { Key::ESCAPE, Key::TAB, Key::F1, Key::F2, Key::F3, Key::F4, Key::SPECIAL + 0, ~0 },
137    { Key::N1, Key::N2, Key::N3, Key::N4, Key::N5, Key::N6, Key::N7, Key::N8 },
138    { Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I },
139    { Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K },
140    { Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M, Key::UP },
141    { Key::N9, Key::O, Key::L, Key::LEFT_ALT, Key::CAPS_LOCK, Key::SPACE, Key::EQUALS, Key::LEFT },
142    { Key::BACKSPACE, Key::N0, Key::P, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT },
143    { Key::FN, Key::LEFT_SHIFT, Key::LEFT_CONTROL, ~0, ~0, ~0, ~0, ~0 }
144    #endif
145    }
146unsigned const DevKbd::keys[NUM_KEYS] = {
147    #ifdef QI
148    Key::F1, Key::F2, Key::F3, Key::F4, Key::F5, Key::F6, Key::F7,
149    Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I,
150    Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K,
151    Key::ESCAPE, Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M,
152    Key::TAB, Key::CAPS_LOCK, Key::BACKSLASH, Key::QUOTE, Key::COMMA, Key::PERIOD, Key::SLASH, Key::UP,
153    Key::O, Key::L, Key::EQUALS, Key::SPECIAL + 0, Key::SPACE, Key::RIGHT_LOGO, Key::RIGHT_CONTROL, Key::LEFT,
154    Key::F8, Key::P, Key::BACKSPACE, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT,
155    Key::LEFT_SHIFT, Key::LEFT_ALT, Key::FN
156    #else
157    Key::ESCAPE, Key::TAB, Key::F1, Key::F2, Key::F3, Key::F4, Key::SPECIAL + 0,
158    Key::N1, Key::N2, Key::N3, Key::N4, Key::N5, Key::N6, Key::N7, Key::N8,
159    Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I,
160    Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K,
161    Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M, Key::UP,
162    Key::N9, Key::O, Key::L, Key::LEFT_ALT, Key::CAPS_LOCK, Key::SPACE, Key::EQUALS, Key::LEFT,
163    Key::BACKSPACE, Key::N0, Key::P, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT,
164    Key::FN, Key::LEFT_SHIFT, Key::LEFT_CONTROL
165    #endif
166    }
167
168class Event:
169    bool state, started
170    unsigned pin
171    Iris::Cap cb
172    public:
173    void scan ():
174        if !started:
175            return
176        gpio_mask_irq (3, 1 << pin)
177        bool s = gpio_get_port (3) & (1 << pin)
178        if s != state:
179            state = s
180            cb.invoke (state ? Iris::Keyboard::RELEASE : 0)
181        gpio_as_interrupt (3, 1 << pin, !state, true)
182        gpio_unmask_irq (3, 1 << pin)
183    Event (unsigned p):
184        pin = p
185        gpio_as_gpio (3, pin)
186        state = true
187        started = false
188    void set_cb (Iris::Cap c):
189        if started:
190            Iris::free_cap (cb)
191        else:
192            started = true
193        cb = c
194        state = true
195        scan ()
196
197enum codes:
198    KBD_DEV = 1
199    PWR
200    SDMMC
201
202Iris::Num start ():
203    map_gpio ()
204
205    DevKbd kbd
206    Event pwr (29)
207    Event sdmmc (0)
208
209    Iris::Keyboard dev = Iris::my_receiver.create_capability (KBD_DEV)
210    Iris::Keyboard pw = Iris::my_receiver.create_capability (PWR)
211    Iris::Event sm = Iris::my_receiver.create_capability (SDMMC)
212    Iris::my_parent.provide_capability <Iris::Keyboard> (dev.copy (), 0)
213    Iris::my_parent.provide_capability <Iris::Keyboard> (pw.copy (), 1)
214    Iris::my_parent.provide_capability <Iris::Event> (sm.copy ())
215    Iris::free_cap (dev)
216    Iris::free_cap (pw)
217    Iris::free_cap (sm)
218    Iris::my_parent.init_done ()
219    if kbd.scanning ():
220        Iris::my_receiver.set_alarm (SCAN_INTERVAL)
221    Iris::register_interrupt (IRQ_GPIO3)
222    while true:
223        Iris::wait ()
224        if Iris::recv.protected_data.h == ~0:
225            // Alarm.
226            kbd.scan ()
227            if kbd.scanning ():
228                Iris::my_receiver.set_alarm (SCAN_INTERVAL)
229            continue
230        switch Iris::recv.protected_data.l:
231            case 0:
232                // Interrupt.
233                pwr.scan ()
234                kbd.scan ()
235                sdmmc.scan ()
236                if kbd.scanning ():
237                    Iris::my_receiver.set_alarm (SCAN_INTERVAL)
238                Iris::register_interrupt (IRQ_GPIO3)
239                break
240            case KBD_DEV:
241                // Keyboard device user request.
242                switch Iris::recv.data[0].l:
243                    case Iris::Device::RESET:
244                        Iris::recv.reply.invoke ()
245                        break
246                    case Iris::Event::SET_CB:
247                        Iris::Cap reply = Iris::get_reply ()
248                        kbd.active (Iris::get_arg ())
249                        reply.invoke ()
250                        Iris::free_cap (reply)
251                        break
252                    case Iris::Keyboard::GET_NUM_KEYS:
253                        Iris::recv.reply.invoke (kbd.size ())
254                        break
255                    case Iris::Keyboard::GET_KEYS:
256                        kbd.send_keys (Iris::recv.data[0].l, Iris::recv.reply)
257                        break
258                    default:
259                        kdebug ("keyboard other\n")
260                        break
261                break
262            case PWR:
263                switch Iris::recv.data[0].l:
264                    case Iris::Device::RESET:
265                        Iris::recv.reply.invoke ()
266                        break
267                    case Iris::Event::SET_CB:
268                        Iris::Cap reply = Iris::get_reply ()
269                        pwr.set_cb (Iris::get_arg ())
270                        reply.invoke ()
271                        Iris::free_cap (reply)
272                        break
273                    default:
274                        kdebug ("Power button invalid request\n")
275                        kdebug_num (Iris::recv.data[0].l)
276                        kdebug ("\n")
277                        break
278                break
279            case SDMMC:
280                switch Iris::recv.data[0].l:
281                    case Iris::Device::RESET:
282                        Iris::recv.reply.invoke ()
283                        break
284                    case Iris::Event::SET_CB:
285                        Iris::Cap reply = Iris::get_reply ()
286                        sdmmc.set_cb (Iris::get_arg ())
287                        reply.invoke ()
288                        Iris::free_cap (reply)
289                        break
290                    default:
291                        kdebug ("SdMmc gpio invalid request\n")
292                        kdebug_num (Iris::recv.data[0].l)
293                        kdebug ("\n")
294                        break
295                break
296            default:
297                kdebug ("keyboard unknown num: ")
298                kdebug_num (Iris::recv.protected_data.h)
299                kdebug ("\n")
300

Archive Download this file

Branches:
master



interactive