1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-11-17 01:06:15 +02:00
iris/userspace/nanonote/gpio.ccp
2013-05-14 18:30:50 -04:00

300 lines
9.5 KiB
COBOL

#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/nanonote-gpio.ccp: gpio devices on the nanonote.
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "devices.hh"
#define ARCH
#include "arch.hh"
#include "keys.hh"
#define QI
#define SCAN_INTERVAL HZ / 50
class DevKbd:
static unsigned const NUM_COLS = 8
static unsigned const NUM_ROWS = 8
static unsigned const COLS_PORT = 2
static unsigned const ROWS_PORT = 3
static unsigned const ALL_COLS = 0x0003fc00
static unsigned const ALL_ROWS = 0x05fc0000
static unsigned const COLS[NUM_COLS]
static unsigned const ROWS[NUM_ROWS]
static unsigned const encode[NUM_ROWS][NUM_COLS]
static unsigned const NUM_KEYS = 58
static unsigned const keys[NUM_KEYS]
unsigned state[NUM_COLS]
Iris::Cap event
bool is_active
bool is_scanning
public:
unsigned size ():
return NUM_KEYS
void send_keys (unsigned first, Iris::Cap target):
unsigned d[4]
unsigned i
for i = 0; first + i < NUM_KEYS && i < 4; ++i:
d[i] = keys[first + i]
for ; i < 4; ++i:
d[i] = ~0
target.invoke (Iris::Num (d[0], d[1]), Iris::Num (d[2], d[3]))
bool scanning ():
return is_scanning
void inactive ():
if is_active:
Iris::free_cap (event)
is_active = false
void check (unsigned col, unsigned rowdata):
for unsigned r = 0; r < NUM_ROWS; ++r:
if !((rowdata ^ state[col]) & (1 << ROWS[r])):
continue
unsigned code = encode[r][col]
if rowdata & (1 << ROWS[r]):
code |= Iris::Keyboard::RELEASE
if is_active:
event.invoke (code)
state[col] = rowdata
void delay ():
for unsigned i = 0; i < 10000; ++i:
gpio_set (0, 0)
void scan ():
unsigned r
gpio_mask_irq (ROWS_PORT, ALL_ROWS)
is_scanning = false
if !is_active:
return
for unsigned c = 0; c < NUM_COLS; ++c:
gpio_as_input (COLS_PORT, ALL_COLS & ~(1 << COLS[c]))
gpio_as_output (COLS_PORT, 1 << COLS[c])
if c > 0:
check (c - 1, r)
delay ()
else:
check (0, state[0])
delay ()
r = gpio_get_port (ROWS_PORT) & ALL_ROWS
if r != ALL_ROWS:
is_scanning = true
gpio_as_output (COLS_PORT, ALL_COLS)
check (NUM_COLS - 1, r)
delay ()
r = gpio_get_port (ROWS_PORT) & ALL_ROWS
unsigned high = 0, low = 0
for unsigned i = 0; i < NUM_ROWS; ++i:
if r & (1 << ROWS[i]):
low |= 1 << ROWS[i]
else:
high |= 1 << ROWS[i]
gpio_as_interrupt (ROWS_PORT, high, true, true)
gpio_as_interrupt (ROWS_PORT, low, false, true)
gpio_unmask_irq (ROWS_PORT, ALL_ROWS)
void active (Iris::Cap cb):
inactive ()
event = cb
is_active = true
for unsigned c = 0; c < NUM_COLS; ++c:
state[c] = ALL_ROWS
scan ()
DevKbd ():
is_active = false
gpio_as_gpio (COLS_PORT, ALL_COLS)
gpio_as_gpio (ROWS_PORT, ALL_ROWS)
gpio_clear (COLS_PORT, ALL_COLS)
gpio_as_output (COLS_PORT, ALL_COLS)
gpio_as_input (ROWS_PORT, ALL_ROWS)
gpio_enable_pull (ROWS_PORT, ALL_ROWS)
for unsigned i = 0; i < NUM_COLS; ++i:
state[i] = ALL_ROWS
scan ()
unsigned const DevKbd::COLS[NUM_COLS] = { 10, 11, 12, 13, 14, 15, 16, 17 }
unsigned const DevKbd::ROWS[NUM_ROWS] = { 18, 19, 20, 21, 22, 23, 24, 26 }
unsigned const DevKbd::encode[NUM_ROWS][NUM_COLS] = {
#ifdef QI
{ Key::F1, Key::F2, Key::F3, Key::F4, Key::F5, Key::F6, Key::F7, ~0 },
{ Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I },
{ Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K },
{ Key::ESCAPE, Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M },
{ Key::TAB, Key::CAPS_LOCK, Key::BACKSLASH, Key::QUOTE, Key::COMMA, Key::PERIOD, Key::SLASH, Key::UP },
{ Key::O, Key::L, Key::EQUALS, Key::SPECIAL + 0, Key::SPACE, Key::RIGHT_LOGO, Key::RIGHT_CONTROL, Key::LEFT },
{ Key::F8, Key::P, Key::BACKSPACE, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT },
{ Key::LEFT_SHIFT, Key::LEFT_ALT, Key::FN, ~0, ~0, ~0, ~0, ~0 }
#else
{ Key::ESCAPE, Key::TAB, Key::F1, Key::F2, Key::F3, Key::F4, Key::SPECIAL + 0, ~0 },
{ Key::N1, Key::N2, Key::N3, Key::N4, Key::N5, Key::N6, Key::N7, Key::N8 },
{ Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I },
{ Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K },
{ Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M, Key::UP },
{ Key::N9, Key::O, Key::L, Key::LEFT_ALT, Key::CAPS_LOCK, Key::SPACE, Key::EQUALS, Key::LEFT },
{ Key::BACKSPACE, Key::N0, Key::P, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT },
{ Key::FN, Key::LEFT_SHIFT, Key::LEFT_CONTROL, ~0, ~0, ~0, ~0, ~0 }
#endif
}
unsigned const DevKbd::keys[NUM_KEYS] = {
#ifdef QI
Key::F1, Key::F2, Key::F3, Key::F4, Key::F5, Key::F6, Key::F7,
Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I,
Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K,
Key::ESCAPE, Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M,
Key::TAB, Key::CAPS_LOCK, Key::BACKSLASH, Key::QUOTE, Key::COMMA, Key::PERIOD, Key::SLASH, Key::UP,
Key::O, Key::L, Key::EQUALS, Key::SPECIAL + 0, Key::SPACE, Key::RIGHT_LOGO, Key::RIGHT_CONTROL, Key::LEFT,
Key::F8, Key::P, Key::BACKSPACE, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT,
Key::LEFT_SHIFT, Key::LEFT_ALT, Key::FN
#else
Key::ESCAPE, Key::TAB, Key::F1, Key::F2, Key::F3, Key::F4, Key::SPECIAL + 0,
Key::N1, Key::N2, Key::N3, Key::N4, Key::N5, Key::N6, Key::N7, Key::N8,
Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I,
Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K,
Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M, Key::UP,
Key::N9, Key::O, Key::L, Key::LEFT_ALT, Key::CAPS_LOCK, Key::SPACE, Key::EQUALS, Key::LEFT,
Key::BACKSPACE, Key::N0, Key::P, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT,
Key::FN, Key::LEFT_SHIFT, Key::LEFT_CONTROL
#endif
}
class Event:
bool state, started
unsigned pin
Iris::Cap cb
public:
void scan ():
if !started:
return
gpio_mask_irq (3, 1 << pin)
bool s = gpio_get_port (3) & (1 << pin)
if s != state:
state = s
cb.invoke (state ? Iris::Keyboard::RELEASE : 0)
gpio_as_interrupt (3, 1 << pin, !state, true)
gpio_unmask_irq (3, 1 << pin)
Event (unsigned p):
pin = p
gpio_as_gpio (3, pin)
state = true
started = false
void set_cb (Iris::Cap c):
if started:
Iris::free_cap (cb)
else:
started = true
cb = c
state = true
scan ()
enum codes:
KBD_DEV = 1
PWR
SDMMC
Iris::Num start ():
map_gpio ()
DevKbd kbd
Event pwr (29)
Event sdmmc (0)
Iris::Keyboard dev = Iris::my_receiver.create_capability (KBD_DEV)
Iris::Keyboard pw = Iris::my_receiver.create_capability (PWR)
Iris::Event sm = Iris::my_receiver.create_capability (SDMMC)
Iris::my_parent.provide_capability <Iris::Keyboard> (dev.copy (), 0)
Iris::my_parent.provide_capability <Iris::Keyboard> (pw.copy (), 1)
Iris::my_parent.provide_capability <Iris::Event> (sm.copy ())
Iris::free_cap (dev)
Iris::free_cap (pw)
Iris::free_cap (sm)
Iris::my_parent.init_done ()
if kbd.scanning ():
Iris::my_receiver.set_alarm (SCAN_INTERVAL)
Iris::register_interrupt (IRQ_GPIO3)
while true:
Iris::wait ()
if Iris::recv.protected_data.h == ~0:
// Alarm.
kbd.scan ()
if kbd.scanning ():
Iris::my_receiver.set_alarm (SCAN_INTERVAL)
continue
switch Iris::recv.protected_data.l:
case 0:
// Interrupt.
pwr.scan ()
kbd.scan ()
sdmmc.scan ()
if kbd.scanning ():
Iris::my_receiver.set_alarm (SCAN_INTERVAL)
Iris::register_interrupt (IRQ_GPIO3)
break
case KBD_DEV:
// Keyboard device user request.
switch Iris::recv.data[0].l:
case Iris::Device::RESET:
Iris::recv.reply.invoke ()
break
case Iris::Event::SET_CB:
Iris::Cap reply = Iris::get_reply ()
kbd.active (Iris::get_arg ())
reply.invoke ()
Iris::free_cap (reply)
break
case Iris::Keyboard::GET_NUM_KEYS:
Iris::recv.reply.invoke (kbd.size ())
break
case Iris::Keyboard::GET_KEYS:
kbd.send_keys (Iris::recv.data[0].l, Iris::recv.reply)
break
default:
kdebug ("keyboard other\n")
break
break
case PWR:
switch Iris::recv.data[0].l:
case Iris::Device::RESET:
Iris::recv.reply.invoke ()
break
case Iris::Event::SET_CB:
Iris::Cap reply = Iris::get_reply ()
pwr.set_cb (Iris::get_arg ())
reply.invoke ()
Iris::free_cap (reply)
break
default:
kdebug ("Power button invalid request\n")
kdebug_num (Iris::recv.data[0].l)
kdebug ("\n")
break
break
case SDMMC:
switch Iris::recv.data[0].l:
case Iris::Device::RESET:
Iris::recv.reply.invoke ()
break
case Iris::Event::SET_CB:
Iris::Cap reply = Iris::get_reply ()
sdmmc.set_cb (Iris::get_arg ())
reply.invoke ()
Iris::free_cap (reply)
break
default:
kdebug ("SdMmc gpio invalid request\n")
kdebug_num (Iris::recv.data[0].l)
kdebug ("\n")
break
break
default:
kdebug ("keyboard unknown num: ")
kdebug_num (Iris::recv.protected_data.h)
kdebug ("\n")