Root/
| 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 | |
| 27 | class 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 | |
| 123 | unsigned const DevKbd::COLS[NUM_COLS] = { 10, 11, 12, 13, 14, 15, 16, 17 } |
| 124 | unsigned const DevKbd::ROWS[NUM_ROWS] = { 18, 19, 20, 21, 22, 23, 24, 26 } |
| 125 | unsigned 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 | } |
| 146 | unsigned 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 | |
| 168 | class 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 | |
| 197 | enum codes: |
| 198 | KBD_DEV = 1 |
| 199 | PWR |
| 200 | SDMMC |
| 201 | |
| 202 | Iris::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 |
Branches:
master
