1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2025-04-21 12:27:27 +03:00

towards a usb file system

This commit is contained in:
Bas Wijnen
2010-01-14 18:14:37 +01:00
parent 3debf99082
commit 0c1dfe719b
20 changed files with 690 additions and 507 deletions

134
source/buzzer.ccp Normal file
View File

@@ -0,0 +1,134 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/buzzer.ccp: Piezo buzzer driver.
// 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"
class DevBuzzer:
static unsigned const pwm = 4
Kernel::Cap event
bool is_beeping
public:
DevBuzzer ():
is_beeping = false
tcu_stop_counter (pwm)
tcu_select_extalclk (pwm)
tcu_select_clk_div64 (pwm)
tcu_enable_pwm_output (pwm)
void stop ():
if !is_beeping:
return
tcu_stop_counter (pwm)
event.invoke ()
Kernel::free_cap (event)
is_beeping = false
void beep (unsigned freq, unsigned ms, Kernel::Cap cb):
stop ()
event = cb
unsigned full = JZ_EXTAL / 64 / freq
tcu_set_full_data (pwm, full)
tcu_set_half_data (pwm, full / 2)
tcu_set_count (pwm, 0)
tcu_start_counter (pwm)
Kernel::my_receiver.set_alarm (ms * HZ / 1000)
is_beeping = true
enum codes:
BUZZER = 32
Kernel::Num start ():
Kernel::schedule ()
map_tcu ()
DevBuzzer buzzer
Device dev = Kernel::my_receiver.create_capability (BUZZER)
Kernel::my_parent.provide_device <Buzzer> (dev.copy ())
Kernel::free_cap (dev)
unsigned user (~0)
unsigned next_user (0)
while true:
Kernel::wait ()
switch Kernel::recv.protected_data.h:
case ~0:
// Alarm.
buzzer.stop ()
break
case 0:
switch Kernel::recv.protected_data.l:
case BUZZER:
// Buzzer device control request.
switch Kernel::recv.data[0].l:
case Device::CREATE_USER:
Kernel::Cap reply = Kernel::get_reply ()
Keyboard cap = Kernel::my_receiver.create_capability (Kernel::Num (next_user++, BUZZER))
reply.invoke (0, 0, cap.copy ())
Kernel::free_cap (cap)
Kernel::free_cap (reply)
break
case Device::DESTROY_USER:
Kernel::recv.reply.invoke ()
break
case Device::UNUSE:
buzzer.stop ()
Kernel::recv.reply.invoke ()
break
case Device::USE:
Kernel::Cap reply = Kernel::get_reply ()
user = Kernel::my_receiver.get_protected (Kernel::recv.arg).l
reply.invoke ()
Kernel::free_cap (reply)
break
default:
kdebug ("invalid buzzer control command: ")
kdebug_num (Kernel::recv.data[0].l)
kdebug ("\n")
break
break
default:
kdebug ("invalid buzzer request\n")
break
break
case BUZZER:
// Buzzer device user request.
if Kernel::recv.protected_data.l != user:
kdebug ("invalid user requesting buzzer\n")
Kernel::recv.reply.invoke ()
break
switch Kernel::recv.data[0].l:
case Buzzer::BEEP:
// Volume is not used by this buzzer.
Kernel::Cap arg = Kernel::get_arg ()
Kernel::Cap reply = Kernel::get_reply ()
buzzer.beep (Kernel::recv.data[1].l, Kernel::recv.data[1].h, arg)
reply.invoke ()
Kernel::free_cap (reply)
break
case Buzzer::STOP:
buzzer.stop ()
Kernel::recv.reply.invoke ()
break
default:
kdebug ("Buzzer: other\n")
break
break
default:
kdebug ("Buzzer: unknown num: ")
kdebug_num (Kernel::recv.protected_data.h)
kdebug ("\n")

887
source/charset Executable file
View File

@@ -0,0 +1,887 @@
#!/usr/bin/env python
data = """
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . # .
. . . . # .
. . . # . .
. . . # . .
. . # . . .
. . . . . .
. # . . . .
. . . . . .
. # # . # #
. . # . . #
+ # . + # .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . # . # .
. # # # # #
. # . # . .
# # # # # .
# . # . . .
. . . . . .
. . . . # .
. . # # # #
. # . # . .
. . # # # .
. . # . # .
. # # # # .
. # . . . .
. . . . . .
. . . . . .
. # # . # .
. # . # . .
. . . # . .
. . # . . .
. . # . # .
. # . # # .
. . . . . .
. # # . . .
. # . # . .
. # # . . .
. . # . . .
. # # . # .
. # . # # .
. # # # # .
. . . . . .
. . # # . .
. . . # . .
. + # . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . + # #
. . . # . .
. . # . . .
. . # . . .
. # . . . .
. . # . . .
. . # # . .
. . . . . .
. . # # . .
. . . . # .
. . . . # .
. . . . # .
. . . # . .
. . . # . .
# # + . . .
. . . . . .
. # . . # .
. . # . # .
. . # # . .
. # # # # #
. . # # . .
. . # . # .
. # . . # .
. . . . . .
. . . . . .
. . . . . .
. . . # . .
. . . # . .
# # # # # .
. . # . . .
. # . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . # # . .
. . # . . .
. + # . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. # # # # .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . # . .
. . # # . .
. . . . . .
. . . . . .
. . . . # .
. . . # . .
. . . # . .
. . # . . .
. . # . . .
. # . . . .
. . . . . .
. . . . . .
. . + # # .
. # + . # .
. # . . # .
# . . # . .
# . + # . .
# # + . . .
. . . . . .
. . . . . .
. . . . # .
. . # # . .
. . . # . .
. . # . . .
. . # . . .
# # # . . .
. . . . . .
. . . . . .
. . + # # .
. + + . # .
. . . . # .
. + # . . .
. # . . . .
# # # # . .
. . . . . .
. . . . . .
. . # # # .
. . . . # .
. . . + # .
. + # . . .
. . . # . .
# # # . . .
. . . . . .
. . . . . .
. . # . . #
. # . . # .
. # # # # .
. . . # . .
. . . # . .
. . # . . .
. . . . . .
. . . . . .
. . # # # #
. # . . . .
. # # # . .
. . . # . .
. . . . # .
# # # # . .
. . . . . .
. . . + # .
. . . # . .
. . # . . .
. . # # # .
. # . . # .
. # . . # .
. # # # . .
. . . . . .
. . . . . .
. . # # # #
. . . . # .
. . . . # .
. . + + . .
. . + + . .
. # . . . .
. . . . . .
. . . . . .
. . + # # .
. # . . # .
. + # # + .
# . . # . .
# . . # . .
# # + . . .
. . . . . .
. . . . . .
. . + # # .
. # . . # .
. # . + # .
. # + # . .
. . . # . .
# # # . . .
. . . . . .
. . . . . .
. . . # . .
. . # # . .
. . . . . .
. . . . . .
. # # . . .
. # . . . .
. . . . . .
. . . . . .
. . . # . .
. . # # . .
. . . . . .
. . . . . .
. # # . . .
. # . . . .
+ # . . . .
. . . . . .
. . . # + .
. + + . . .
. # . . . .
. # . . . .
. . # . . .
. . # . . .
. . . . . .
. . . . . .
. . . . . .
. # # # # .
. . . . . .
. . . . . .
# # # # . .
. . . . . .
. . . . . .
. . . . . .
. . # . . .
. . # . . .
. . . # . .
. . . # . .
. . + + . .
+ # . . . .
. . . . . .
. . # # . .
. . # . # .
. . . . # .
. . . + # .
. . # . . .
. . . . . .
. # . . . .
. . . . . .
. . # # # .
. . # . . #
. # . # . #
. # . # + #
# . # # # .
. # . . . .
. # # # . .
. . . . . .
. . . + # .
. . . # . #
. . # . . #
. . # # # #
. # . . # .
. # . . # .
# . . # . .
. . . . . .
. . . # # .
. . . # . #
. . # . # .
. . # # # .
. # . . # .
. # . + # .
# # # + . .
. . . . . .
. . + # # .
. . # + . #
. # . . . .
. # . . . .
# . . . . .
+ + . + + .
# # # . . .
. . . . . .
. . . # # .
. . . # . #
. . # . . #
. . # . . #
. # . . # .
. # . + # .
# # # + . .
. . . . . .
. . . # # #
. . . # . .
. . # . . .
. . # # . .
. # . . . .
. # . . . .
# # # . . .
. . . . . .
. . . # # #
. . . # . .
. . # . . .
. . # # . .
. # . . . .
. # . . . .
# . . . . .
. . . . . .
. . + # # .
. . # + . #
. # . . . .
. # . . . .
# . # # . .
+ + . # . .
+ # # . . .
. . . . . .
. . . # . #
. . . # . #
. . # . # .
. . # # # .
. # . # . .
. # . # . .
# . # . . .
. . . . . .
. . . # # #
. . . . # .
. . . # . .
. . . # . .
. . # . . .
. . # . . .
# # # . . .
. . . . . .
. . . # # #
. . . . # .
. . . # . .
. . . # . .
. . # . . .
# . # . . .
# # . . . .
. . . . . .
. . . # . #
. . . # . #
. . # . # .
. . # # + .
. # + . . .
. # . # . .
# . . # . .
. . . . . .
. . . # . .
. . . # . .
. . # . . .
. . # . . .
. # . . . .
. # . . . .
# # # # . .
. . . . . .
. . # . # #
. . # + # +
. # . # . #
. # . . . #
# . . . # .
# . . . # .
+ . . # . .
. . . . . .
. . # . . #
. . # # . +
. # + + . #
. # . # . #
# . + + # .
# . . # # .
+ . . # . .
. . . . . .
. . . # # .
. . # + . #
. # . . . #
. # . . . #
# . . . # .
# . . + # .
# # # . . .
. . . . . .
. . . # # .
. . . # . #
. . # . . #
. . # . + #
. # # # + .
. # . . . .
# . . . . .
. . . . . .
. . . # # .
. . # + . #
. # . . . #
. # . . . #
# . . # # .
# . . . # .
# # # . # .
. . . . . .
. . . # # .
. . . # . #
. . # . . #
. . # . + #
. # # # + .
. # . # . .
# . . # . .
. . . . . .
. . + # # #
. . # + . .
. # . . . .
. . # # . .
. . . # . .
. . . . # .
# # # # . .
. . . . . .
. # # # # #
. . . # . .
. . # . . .
. . # . . .
. # . . . .
. # . . . .
# . . . . .
. . . . . .
. . # . . #
. . # . . #
. # . . # .
. # . . # .
# . . # . .
# . + # . .
# # + . . .
. . . . . .
. + . . . #
. # . . . #
+ . . . # .
. # . . # .
+ . . # . .
. # + + . .
. # . . . .
. . . . . .
. . # . . +
. . # . . +
. # . . . #
. # . . . #
# . # . # .
# + # . # .
# + # # . .
. . . . . .
. # . . . #
. . # . . #
. . # # + .
. . . # . .
. + # # . .
. # . . # .
# . . . # .
. . . . . .
. # . . . #
. . # . . #
. . # # + .
. . . # . .
. + # . . .
. # . . . .
# . . . . .
. . . . . .
. . # # # #
. . . . . #
. . . # + .
. . . # . .
. + # . . .
. # . . . .
# # # # . .
. . . . . .
. . . # # #
. . . # . .
. . # . . .
. . # . . .
. # . . . .
. # . . . .
# # # . . .
. . . . . .
. # . . . .
. . # . . .
. . # . . .
. . . # . .
. . . # . .
. . . . # .
. . . . # .
. . . . . .
. . . # # #
. . . . . #
. . . . # .
. . . . # .
. . . # . .
. . . # . .
# # # . . .
. . . . . .
. . . + # .
. . + # . #
. # . . . #
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
# # # # # .
. . . . . .
. . # # . .
. . . # . .
. . + # . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . # # + #
. # . # # .
. # . . # .
# . . # . .
. # + # . .
. # # . . .
. . . . . .
. . . # . .
. . . # . .
. . # . . .
. . # # # .
. # . . # .
. # . . # .
# # # # . .
. . . . . .
. . . . . .
. . . # # .
. # + . # .
. # . . . .
# . . . . .
. # . # . .
. # + . . .
. . . . . .
. . . . . #
. . . . . #
. . # # # .
. # + . # .
# . . # . .
# . . # . .
# # # . . .
. . . . . .
. . . . . .
. . + # # .
. # . . # .
. # # # + .
# . . . . .
. # . . . .
. # # . . .
. . . . . .
. . . # # .
. . . # . #
. . # . . .
. # # # . .
. # . . . .
. # . . . .
# . . . . .
. . . . . .
. . . . . .
. . . # # #
. . # . . #
. . . # # #
. . . . # .
. . . + # .
. # # . . .
. . . . . .
. . . # . .
. . . # . .
. . # . . .
. . # . . .
. # # # . .
. # . . # .
# . . # . .
. . . . . .
. . . . # .
. . . . . .
. . . # . .
. . . # . .
. . # . . .
. . # . . .
. # . . . .
. . . . . .
. . . . # .
. . . . . .
. . . # . .
. . . # . .
. . # . . .
. . # . . .
. # . . . .
# # . . . .
. . . # . .
. . . # . .
. . # . . .
. . # . . .
. # + # . .
. # # + . .
# . # + . .
. . . . . .
. . . . # .
. . . . # .
. . . # . .
. . . # . .
. . # . . .
. . # . . .
. # . . . .
. . . . . .
. . . . . .
. . . # # #
. . # + + #
. . # + + #
. # + + # .
. # + + # .
# + + # . .
. . . . . .
. . . . . .
. . . # + #
. . # # + #
. . # . . #
. # . . # .
. # . . # .
# . . # . .
. . . # . .
. . . . . .
. . + # # .
. # + . # .
. # . . . #
# . . . # .
. # . + # .
. # # + . .
. . . . . .
. . . . . .
. . . # # #
. . # . . #
. . # . . #
. # # # + .
. # . . . .
# . . . . .
. . . . . .
. . . . . .
. . + # # #
. # . . # .
. # . . # .
. # # # . .
. . . # . .
. . # . . .
. . # . . .
. . . . . .
. . . # + #
. . # # . #
. . # . . .
. # . . . .
. # . . . .
# . . . . .
. . . . . .
. . . . . .
. . # # # #
. # . . . .
. . # # . .
. . . # . .
. . . . # .
# # # # . .
. . . . . .
. . . . . .
. . . # . .
. # # # . .
. . # . . .
. # . . . .
. # . # . .
. # + . . .
. . . . . .
. . . . . .
. . # . . #
. # . . # .
. # . . # .
# . . # . .
# . + # . .
# # + . . .
. . . . . .
. . . . . .
. + # . . +
. # . . . #
. + + . + #
. # . # + .
. # . # . .
. # . . . .
. . . . . .
. . . . . .
. . # . . +
. # . . . #
. # . # . #
# . # . # .
# . # . # .
# # # + . .
. . . . . .
. . . . . .
. . # . . #
. . # . # .
. . + # + .
. + # + . .
. # . # . .
# . . # . .
. . . . . .
. . . . . .
. . # . . #
. # . . # .
. . # # # .
. . . # . .
. . + # . .
# # + . . .
. . . . . .
. . . . . .
. . # # # #
. . . . # .
. . . # + .
. + # . . .
. # . . . .
# # # # . .
. . . . . .
. . . + # #
. . . # . .
. . # . . .
. # + . . .
. # . . . .
. # . . . .
+ # # . . .
. . . . . .
. . . . # .
. . . . # .
. . . # . .
. . . # . .
. . # . . .
. . # . . .
. # . . . .
. . . . . .
. . . # # +
. . . . . #
. . . . # .
. . . . + #
. . . # . .
. . . # . .
# # + . . .
. . . . . .
. # # . . .
. # . # . #
. . . # # .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. # + # + .
. # + # + .
. + # + # .
. + # + # .
. # + # + .
. # + # + .
. . . . . .
"""
# """ # add quotes, because vim thinks the qotes on the previous line start a string.
import sys
charsize = 25 * 4 + 1
for c in range (128 - 32):
line = []
for l in range (8):
offset = 2 + c * charsize + 25 * (l >> 1) + 12 * (l & 1)
ln = ""
for x in range (6):
char = data[offset + x * 2]
if char == '.':
sys.stdout.write (chr (0))
elif char == '+':
sys.stdout.write (chr (128))
elif char == '#':
sys.stdout.write (chr (255))
else:
raise "invalid character in " + str (c)

143
source/crt0.ccp Normal file
View File

@@ -0,0 +1,143 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/init.S: Startup code for initial Threads.
// 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 "iris.hh"
#include "devices.hh"
// For some unknown reason, gcc needs this to be defined.
unsigned __gxx_personality_v0
struct list:
list *prev, *next
static unsigned __slots, __caps
static list *__slot_admin, *__cap_admin
static list *__first_free_slot, *__first_free_cap
namespace Kernel:
Receiver my_receiver
Thread my_thread
Memory my_memory
Cap my_call
Parent my_parent
__recv_data_t recv
void print_caps ():
// Assume __caps to be 16.
bool used[16]
for unsigned i = 0; i < 16; ++i:
used[i] = true
unsigned num = 0
for list *i = __first_free_cap; i; i = i->next:
used[i - __cap_admin] = false
++num
kdebug_num (num, 1)
kdebug (":")
for unsigned i = 0; i < 16; ++i:
kdebug_char (used[i] ? '#' : '.')
kdebug_char ('\n')
void free_slot (unsigned slot):
//kdebug ("free slot\n")
__slot_admin[slot].prev = NULL
__slot_admin[slot].next = __first_free_slot
if __slot_admin[slot].next:
__slot_admin[slot].next->prev = &__slot_admin[slot]
__first_free_slot = &__slot_admin[slot]
void free_cap (Cap cap):
//kdebug ("free cap\n")
if cap.slot () != 0:
kdebug ("trying to free capability from non-0 slot\n")
return
list *l = &__cap_admin[cap.idx ()]
l->prev = NULL
l->next = __first_free_cap
if l->next:
l->next->prev = l
__first_free_cap = l
unsigned alloc_slot ():
//kdebug ("alloc slot\n")
if !__first_free_slot:
// Out of slots... Probably best to raise an exception. For now, just return NO_SLOT.
kdebug ("out of slots!\n")
return ~0
list *ret = __first_free_slot
__first_free_slot = ret->next
if ret->next:
ret->next->prev = NULL
return ret - __slot_admin
Cap alloc_cap ():
//kdebug ("alloc cap\n")
if !__first_free_cap:
// Out of caps... Probably best to raise an exception. For now, just return CAP_NONE
kdebug ("out of capabilities!\n")
return Cap (0, CAP_NONE)
list *ret = __first_free_cap
__first_free_cap = ret->next
if ret->next:
ret->next->prev = NULL
return Cap (0, ret - __cap_admin)
extern "C":
void run__main (unsigned slots, unsigned caps, list *slot_admin, list *cap_admin):
__slots = slots
__caps = caps
__slot_admin = slot_admin
__cap_admin = cap_admin
__first_free_slot = NULL
for unsigned i = 2; i < __slots; ++i:
Kernel::free_slot (i)
__first_free_cap = NULL
for unsigned i = 7; i < __caps; ++i:
Kernel::free_cap (Kernel::Cap (0, i))
Kernel::my_receiver = Kernel::Cap (0, __receiver_num)
Kernel::my_thread = Kernel::Cap (0, __thread_num)
Kernel::my_memory = Kernel::Cap (0, __memory_num)
Kernel::my_call = Kernel::Cap (0, __call_num)
Kernel::my_parent = Kernel::Cap (0, __parent_num)
Kernel::recv.reply = Kernel::alloc_cap ()
Kernel::recv.arg = Kernel::alloc_cap ()
Kernel::Num ret = start ()
Kernel::my_parent.invoke (~0, ret)
Kernel::my_memory.destroy (Kernel::my_thread)
// The program no longer exists. If it somehow does, generate an address fault.
while true:
*(volatile unsigned *)~0
__asm__ volatile ("\t.globl __start\n"
"\t.set noreorder\n"
"__start:\n"
"\tbal 1f\n"
"__hack_label:\n"
"\tnop\n"
"\t.word _gp\n"
"1:\n"
"\tlw $gp, 0($ra)\n"
"\tsll $v0, $a0, 3\n"
"\tsll $v1, $a1, 3\n"
"\tsubu $sp, $sp, $v0\n"
"\tmove $a2, $sp\n"
"\tsubu $sp, $sp, $v1\n"
"\tmove $a3, $sp\n"
"\tla $t9, run__main\n"
"\tjr $t9\n"
"\tnop\n"
"\t.set reorder")

323
source/gpio.ccp Normal file
View File

@@ -0,0 +1,323 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/gpio.ccp: GPIO driver, controlling all devices without special hardware.
// 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"
// Interval between polls for keyboard events (when keys are pressed)
#define ALARM_INTERVAL (HZ / 50)
// GPIO pins for the devices (port.pin)
// keyboard
// Cols = 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13, 3.14, 3.15, 3.29
// Rows = 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7
// For some reason, it only works if the rows are input and the columns are output.
// interrupts: yes, with all columns set to output 0, the first key press can be detected as an interrupt; some other events also trigger interrupts.
// touchpad buttons
// Left: 0.16
// Right: 0.13
// interrupts: yes, for any change.
// Lock leds
// Num lock: 2.22
// Caps lock: 0.27
// Scroll lock: 0.9
// interrupts: no, output only.
// interrupt summary
// Port 0: pin 0, 1, 2, 3, 4, 5, 6, 7: keyboard; 13, 16: touchpad
// Port 1: None.
// Port 2: None.
// Port 3: None.
enum event_type:
KEYBOARD_EVENT
TOUCHPAD_EVENT
NUM_EVENTS
static Kernel::Cap events[NUM_EVENTS]
static void event (event_type type, unsigned data):
events[type].invoke (data)
static void set_cb (event_type type):
Kernel::free_cap (events[type])
events[type] = Kernel::get_arg ()
class DevKeyboard:
static unsigned const encode[GPIO_KBD_NUM_COLS][GPIO_KBD_NUM_ROWS]
unsigned keys[GPIO_KBD_NUM_COLS]
bool scanning
void parse (unsigned col, unsigned data):
for unsigned row = 0; row < GPIO_KBD_NUM_ROWS; ++row:
if (data ^ keys[col]) & (1 << row):
unsigned code = encode[col][row]
if data & (1 << row):
code |= Keyboard::RELEASE
event (KEYBOARD_EVENT, code)
keys[col] = data
// If any keys are pressed, scanning is required.
if data != GPIO_KBD_ROW_MASK:
scanning = true
public:
bool is_scanning ():
return scanning
void scan ():
// Disable interrupts during scan.
GPIO_GPIER (GPIO_KBD_ROW_PORT) &= ~GPIO_KBD_ROW_MASK
// All columns are input.
GPIO_GPDIR (GPIO_KBD_COL_PORT) &= ~GPIO_KBD_COL_MASK
int const cols[GPIO_KBD_NUM_COLS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 29 }
unsigned dir = GPIO_GPDIR (GPIO_KBD_COL_PORT) & ~GPIO_KBD_COL_MASK
unsigned dat = GPIO_GPDR (GPIO_KBD_COL_PORT) & ~GPIO_KBD_COL_MASK
// Set scanning to false before first parse.
scanning = false
// Clear all pins. This is only required once, because it's done at the end of the loop as well.
GPIO_GPDR (GPIO_KBD_COL_PORT) = dat
for unsigned col = 0; col < GPIO_KBD_NUM_COLS; ++col:
// Set pin to output.
GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir | (1 << cols[col])
// Delay for stabalization.
for unsigned i = 0; i < 100; ++i:
GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir | (1 << cols[col])
// Read the result.
unsigned data = GPIO_GPDR (GPIO_KBD_ROW_PORT) & GPIO_KBD_ROW_MASK
// Generate events.
parse (col, data)
// Set pin to get rid of capacitance effects.
GPIO_GPDR (GPIO_KBD_COL_PORT) = dat | (1 << cols[col])
// Delay to make the above trick work.
for unsigned i = 0; i < 100; ++i:
GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir | (1 << cols[col])
// Pin is set to input at the start of the loop.
// set all to 0.
GPIO_GPDR (GPIO_KBD_COL_PORT) = dat
// set all to output.
GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir | GPIO_KBD_COL_MASK
// Delay for stabalization.
for unsigned i = 0; i < 100; ++i:
GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir | GPIO_KBD_COL_MASK
// Set interrupts.
unsigned data = GPIO_GPDR (GPIO_KBD_ROW_PORT)
for unsigned i = 0; i < 8; ++i:
if data & (1 << i):
gpio_irq_low (GPIO_KBD_ROW_PORT, i)
else:
gpio_irq_high (GPIO_KBD_ROW_PORT, i)
// Reenable interrupts.
GPIO_GPIER (GPIO_KBD_ROW_PORT) |= GPIO_KBD_ROW_MASK
DevKeyboard ():
// Set all columns to output without pull-ups when set as input.
GPIO_GPPUR (GPIO_KBD_COL_PORT) &= ~GPIO_KBD_COL_MASK
GPIO_GPDIR (GPIO_KBD_COL_PORT) |= GPIO_KBD_COL_MASK
// Set all rows to input and enable the pull-ups.
GPIO_GPPUR (GPIO_KBD_ROW_PORT) |= GPIO_KBD_ROW_MASK
GPIO_GPDIR (GPIO_KBD_ROW_PORT) &= ~GPIO_KBD_ROW_MASK
// Initialize things in the same way as when a new callback is set up.
send_initial ()
void send_initial ():
for unsigned col = 0; col < GPIO_KBD_NUM_COLS; ++col:
keys[col] = 0xff
scan ()
enum Keys:
N0, N1, N2, N3, N4, N5, N6, N7, N8, N9
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10
SPACE, TAB, ENTER, LBRACE, RBRACE, COMMA, PERIOD, MINUS, EQUAL, SLASH, BACKSLASH, SEMICOLON, EXTRA, BACKQUOTE, QUOTE
UP, DOWN, LEFT, RIGHT
ESC, INSERT, DELETE, BACKSPACE, PAUSE, FN, ZZZ, MENU, SYSRQ
LSHIFT, RSHIFT, CTRL, ALT
CAPS, NUM
NONE = ~Keyboard::RELEASE
unsigned const DevKeyboard::encode[GPIO_KBD_NUM_COLS][GPIO_KBD_NUM_ROWS] = {
{ PAUSE, NONE, NONE, NONE, NONE, NONE, CTRL, F5 },
{ Q, TAB, A, ESC, Z, NONE, BACKQUOTE, N1 },
{ W, CAPS, S, EXTRA, X, NONE, NONE, N2 },
{ E, F3, D, F4, C, NONE, NONE, N3 },
{ R, T, F, G, V, B, N5, N4 },
{ U, Y, J, H, M, N, N6, N7 },
{ I, RBRACE, K, F6, COMMA, NONE, EQUAL, N8 },
{ O, F7, L, NONE, PERIOD, MENU, F8, N9 },
{ NONE, NONE, NONE, SPACE, NUM, NONE, DELETE, NONE },
{ NONE, BACKSPACE, NONE, NONE, ENTER, NONE, F9, NONE },
{ NONE, NONE, NONE, ALT, NONE, NONE, NONE, SYSRQ },
{ P, LBRACE, SEMICOLON, QUOTE, BACKSLASH, SLASH, MINUS, N0 },
{ NONE, ZZZ, NONE, NONE, NONE, NONE, NONE, F10 },
{ NONE, NONE, NONE, NONE, NONE, NONE, F2, NONE },
{ NONE, NONE, NONE, NONE, NONE, NONE, INSERT, NONE },
{ NONE, NONE, UP, DOWN, LEFT, RIGHT, NONE, NONE },
{ NONE, LSHIFT, RSHIFT, NONE, NONE, NONE, F1, FN }}
class Touchpad:
unsigned old_state
public:
void check_events ():
unsigned state = GPIO_GPDR (GPIO_TP_LEFT_PORT)
if state & (1 << GPIO_TP_LEFT):
gpio_irq_low (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
if (state ^ old_state) & (1 << GPIO_TP_LEFT):
event (TOUCHPAD_EVENT, 0)
else:
gpio_irq_high (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
if (state ^ old_state) & (1 << GPIO_TP_LEFT):
event (TOUCHPAD_EVENT, 0 | Keyboard::RELEASE)
if state & (1 << GPIO_TP_RIGHT):
gpio_irq_low (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
if (state ^ old_state) & (1 << GPIO_TP_RIGHT):
event (TOUCHPAD_EVENT, 1)
else:
gpio_irq_high (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
if (state ^ old_state) & (1 << GPIO_TP_RIGHT):
event (TOUCHPAD_EVENT, 1 | Keyboard::RELEASE)
old_state = state
// Ack interrupts.
//GPIO_GPFR (GPIO_TP_LEFT_PORT) = (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT)
Touchpad ():
// Set pins to input with pull-ups.
gpio_as_input (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
gpio_as_input (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
GPIO_GPPUR (0) |= (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT)
// See if they are already pressed. Also set up interrupts. This is done like when a new callback is registered.
send_initial ()
void send_initial ():
old_state = 0
check_events ()
class Lockleds:
// Note that num lock is in port 2. The others are in port 0.
public:
Lockleds ():
gpio_as_output (GPIO_NUM_PORT, GPIO_NUM)
gpio_as_output (GPIO_CAPS_PORT, GPIO_CAPS)
gpio_as_output (GPIO_SCROLL_PORT, GPIO_SCROLL)
GPIO_GPDR (GPIO_NUM_PORT) |= 1 << GPIO_NUM
GPIO_GPDR (GPIO_CAPS_PORT) |= 1 << GPIO_CAPS
GPIO_GPDR (GPIO_SCROLL_PORT) |= 1 << GPIO_SCROLL
void set (unsigned state):
if state & 4:
GPIO_GPDR (GPIO_NUM_PORT) &= ~(1 << GPIO_NUM)
else:
GPIO_GPDR (GPIO_NUM_PORT) |= 1 << GPIO_NUM
if state & 2:
GPIO_GPDR (GPIO_CAPS_PORT) &= ~(1 << GPIO_CAPS)
else:
GPIO_GPDR (GPIO_CAPS_PORT) |= 1 << GPIO_CAPS
if state & 1:
GPIO_GPDR (GPIO_SCROLL_PORT) &= ~(1 << GPIO_SCROLL)
else:
GPIO_GPDR (GPIO_SCROLL_PORT) |= 1 << GPIO_SCROLL
// Not really a gpio device, but it's so small, and uses gpio, so I include it here to avoid ipc.
class Pwm:
public:
Pwm ():
GPIO_GPDIR (GPIO_PWM_ENABLE_PORT) |= 1 << GPIO_PWM_ENABLE
PWM_PER (0) = 300
void set_backlight (unsigned level):
if level > 300:
level = 300
PWM_DUT (0) = level
if level:
PWM_CTR (0) = 0x80
GPIO_GPDR (GPIO_PWM_ENABLE_PORT) |= 1 << GPIO_PWM_ENABLE
else:
PWM_CTR (0) = 0x00
GPIO_GPDR (GPIO_PWM_ENABLE_PORT) &= ~(1 << GPIO_PWM_ENABLE)
// TODO: make it really work as a pwm instead of a switch; check if pwm1 is connected to anything.
enum codes:
KEYBOARD = 32
TOUCHPAD
LOCKLEDS
PWM
Kernel::Num start ():
Kernel::schedule ()
map_gpio ()
map_pwm0 ()
for unsigned i = 0; i < NUM_EVENTS; ++i:
events[i] = Kernel::alloc_cap ()
DevKeyboard kbd
Touchpad tp
Lockleds leds
Pwm pwm
Kernel::Cap c = Kernel::my_receiver.create_capability (KEYBOARD)
Kernel::my_parent.provide_device <Keyboard> (c.copy (), 0)
Kernel::free_cap (c)
c = Kernel::my_receiver.create_capability (TOUCHPAD)
Kernel::my_parent.provide_device <Keyboard> (c.copy (), 1)
Kernel::free_cap (c)
if kbd.is_scanning ():
Kernel::my_receiver.set_alarm (ALARM_INTERVAL)
// Enable interrupts. All are in port 0.
GPIO_GPIER (GPIO_KBD_ROW_PORT) = (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT) | GPIO_KBD_ROW_MASK
Kernel::register_interrupt (IRQ_GPIO0)
while true:
Kernel::schedule ()
Kernel::wait ()
switch Kernel::recv.protected_data.l:
case ~0:
// Alarm.
kbd.scan ()
if kbd.is_scanning ():
Kernel::my_receiver.set_alarm (ALARM_INTERVAL)
break
case IRQ_GPIO0:
// Always scan keyboard and touchpad on any interrupt.
kbd.scan ()
tp.check_events ()
// Reregister the interrupt.
Kernel::register_interrupt (IRQ_GPIO0)
break
case KEYBOARD:
set_cb (KEYBOARD_EVENT)
Kernel::recv.reply.invoke ()
kbd.send_initial ()
event (KEYBOARD_EVENT, ~0)
break
case TOUCHPAD:
set_cb (TOUCHPAD_EVENT)
Kernel::recv.reply.invoke ()
tp.send_initial ()
event (TOUCHPAD_EVENT, ~0)
break
case LOCKLEDS:
leds.set (Kernel::recv.data[0].l)
Kernel::recv.reply.invoke ()
break
case PWM:
pwm.set_backlight (Kernel::recv.data[0].l)
Kernel::recv.reply.invoke ()
break
default:
kdebug ("invalid gpio operation ")
kdebug_num (Kernel::recv.protected_data.l)
kdebug ("\n")
break

350
source/gpio.txt Normal file
View File

@@ -0,0 +1,350 @@
GPIO control:
#define GPIO_BASE 0xB0010000
#define IRQ_GPIO3 25
#define IRQ_GPIO2 26
#define IRQ_GPIO1 27
#define IRQ_GPIO0 28
#define GPIO_IRQ_LOLEVEL 0
#define GPIO_IRQ_HILEVEL 1
#define GPIO_IRQ_FALLEDG 2
#define GPIO_IRQ_RAISEDG 3
// GP ... Registers: one set for each port of 32 pins; total 128 pins means 4 groups. Total size: 4 * 0x30 == 0xc0.
#define GPIO_GPDR(n) (GPIO_BASE + (0x00 + (n)*0x30)) // D: data
#define GPIO_GPDIR(n) (GPIO_BASE + (0x04 + (n)*0x30)) // DI: data in: 0 is input; 1 is output. Disable interrupts on the pin before touching this.
#define GPIO_GPODR(n) (GPIO_BASE + (0x08 + (n)*0x30)) // OD:
#define GPIO_GPPUR(n) (GPIO_BASE + (0x0c + (n)*0x30)) // PU: pull-up (1 is enable)
#define GPIO_GPALR(n) (GPIO_BASE + (0x10 + (n)*0x30)) // AL: alternate lower: per 2 bit; 00 means use as gpio; other values mean use as alternate function
#define GPIO_GPAUR(n) (GPIO_BASE + (0x14 + (n)*0x30)) // AU: alternate upper: same thing, needs 2 registers because it's 2 bits per pin.
#define GPIO_GPIDLR(n) (GPIO_BASE + (0x18 + (n)*0x30)) // IDL: interrupt detect lower: per 2 bit (GPIO_IRQ_*)
#define GPIO_GPIDUR(n) (GPIO_BASE + (0x1c + (n)*0x30)) // IDU: interrupt detect upper: same thing, upper 16 bit
#define GPIO_GPIER(n) (GPIO_BASE + (0x20 + (n)*0x30)) // IE: interrupt enable (0 is disable)
#define GPIO_GPIMR(n) (GPIO_BASE + (0x24 + (n)*0x30)) // IM:
#define GPIO_GPFR(n) (GPIO_BASE + (0x28 + (n)*0x30)) // F: flag: set on interrupt; cleared by user.
#define IRQ_GPIO_0 48
#define NUM_GPIO 128
// Pins for alternate functions:
#define __gpio_as_ssi() \
do { \
REG_GPIO_GPALR(2) &= 0xFC00FFFF; \
REG_GPIO_GPALR(2) |= 0x01550000; \
} while (0)
#define __gpio_as_uart3() \
do { \
REG_GPIO_GPAUR(0) &= 0xFFFF0000; \
REG_GPIO_GPAUR(0) |= 0x00005555; \
} while (0)
#define __gpio_as_uart2() \
do { \
REG_GPIO_GPALR(3) &= 0x3FFFFFFF; \
REG_GPIO_GPALR(3) |= 0x40000000; \
REG_GPIO_GPAUR(3) &= 0xF3FFFFFF; \
REG_GPIO_GPAUR(3) |= 0x04000000; \
} while (0)
#define __gpio_as_uart1() \
do { \
REG_GPIO_GPAUR(0) &= 0xFFF0FFFF; \
REG_GPIO_GPAUR(0) |= 0x00050000; \
} while (0)
#define __gpio_as_uart0() \
do { \
REG_GPIO_GPAUR(3) &= 0x0FFFFFFF; \
REG_GPIO_GPAUR(3) |= 0x50000000; \
} while (0)
#define __gpio_as_scc0() \
do { \
REG_GPIO_GPALR(2) &= 0xFFFFFFCC; \
REG_GPIO_GPALR(2) |= 0x00000011; \
} while (0)
#define __gpio_as_scc1() \
do { \
REG_GPIO_GPALR(2) &= 0xFFFFFF33; \
REG_GPIO_GPALR(2) |= 0x00000044; \
} while (0)
#define __gpio_as_scc() \
do { \
__gpio_as_scc0(); \
__gpio_as_scc1(); \
} while (0)
#define __gpio_as_dma() \
do { \
REG_GPIO_GPALR(0) &= 0x00FFFFFF; \
REG_GPIO_GPALR(0) |= 0x55000000; \
REG_GPIO_GPAUR(0) &= 0xFF0FFFFF; \
REG_GPIO_GPAUR(0) |= 0x00500000; \
} while (0)
#define __gpio_as_msc() \
do { \
REG_GPIO_GPALR(1) &= 0xFFFF000F; \
REG_GPIO_GPALR(1) |= 0x00005550; \
} while (0)
#define __gpio_as_pcmcia() \
do { \
REG_GPIO_GPAUR(2) &= 0xF000FFFF; \
REG_GPIO_GPAUR(2) |= 0x05550000; \
} while (0)
#define __gpio_as_emc(csmask) \
do { \
REG_GPIO_GPALR(2) &= 0x3FFFFFFF; \
REG_GPIO_GPALR(2) |= 0x40000000; \
REG_GPIO_GPAUR(2) &= 0xFFFF0000; \
REG_GPIO_GPAUR(2) |= 0x00005555; \
} while (0)
#define __gpio_as_lcd_slave() \
do { \
REG_GPIO_GPALR(1) &= 0x0000FFFF; \
REG_GPIO_GPALR(1) |= 0x55550000; \
REG_GPIO_GPAUR(1) &= 0x00000000; \
REG_GPIO_GPAUR(1) |= 0x55555555; \
} while (0)
#define __gpio_as_lcd_master() \
do { \
REG_GPIO_GPALR(1) &= 0x0000FFFF; \
REG_GPIO_GPALR(1) |= 0x55550000; \
REG_GPIO_GPAUR(1) &= 0x00000000; \
REG_GPIO_GPAUR(1) |= 0x556A5555; \
} while (0)
#define __gpio_as_usb() \
do { \
REG_GPIO_GPAUR(0) &= 0x00FFFFFF; \
REG_GPIO_GPAUR(0) |= 0x55000000; \
} while (0)
#define __gpio_as_ac97() \
do { \
REG_GPIO_GPALR(2) &= 0xC3FF03FF; \
REG_GPIO_GPALR(2) |= 0x24005400; \
} while (0)
#define __gpio_as_i2s_slave() \
do { \
REG_GPIO_GPALR(2) &= 0xC3FF0CFF; \
REG_GPIO_GPALR(2) |= 0x14005100; \
} while (0)
#define __gpio_as_i2s_master() \
do { \
REG_GPIO_GPALR(2) &= 0xC3FF0CFF; \
REG_GPIO_GPALR(2) |= 0x28005100; \
} while (0)
#define __gpio_as_eth() \
do { \
REG_GPIO_GPAUR(3) &= 0xFC000000; \
REG_GPIO_GPAUR(3) |= 0x01555555; \
} while (0)
#define __gpio_as_pwm() \
do { \
REG_GPIO_GPAUR(2) &= 0x0FFFFFFF; \
REG_GPIO_GPAUR(2) |= 0x50000000; \
} while (0)
#define __gpio_as_ps2() \
do { \
REG_GPIO_GPALR(1) &= 0xFFFFFFF0; \
REG_GPIO_GPALR(1) |= 0x00000005; \
} while (0)
#define __gpio_as_uprt() \
do { \
REG_GPIO_GPALR(1) &= 0x0000000F; \
REG_GPIO_GPALR(1) |= 0x55555550; \
REG_GPIO_GPALR(3) &= 0xC0000000; \
REG_GPIO_GPALR(3) |= 0x15555555; \
} while (0)
#define __gpio_as_cim() \
do { \
REG_GPIO_GPALR(0) &= 0xFF000000; \
REG_GPIO_GPALR(0) |= 0x00555555; \
} while (0)
// Pins on the trendtac:
0.00 keyboard
0.01 keyboard
0.02 keyboard
0.03 keyboard
0.04 keyboard
0.05 keyboard
0.06 keyboard
0.07 keyboard
0.08 keyboard interrupt?
0.09
0.10
0.11
0.12
0.13 touchpad right button
0.14
0.15
0.16 touchpad left button
0.17
0.18
0.19
0.20
0.21
0.22
0.23
0.24
0.25
0.26
0.27
0.28
0.29
0.30
0.31
1.00
1.01
1.02
1.03
1.04
1.05
1.06
1.07
1.08
1.09
1.10
1.11
1.12
1.13
1.14
1.15
1.16
1.17
1.18
1.19
1.20
1.21
1.22
1.23
1.24
1.25
1.26
1.27
1.28
1.29
1.30
1.31
2.00 SPEN: lcd enable
2.01 SPCK: lcd clock
2.02 SPDA: lcd data
2.03 LCD_RET: lcd reset
2.04
2.05
2.06
2.07
2.08
2.09
2.10
2.11
2.12
2.13
2.14
2.15
2.16
2.17
2.18
2.19
2.20
2.21
2.22
2.23
2.24
2.25
2.26
2.27
2.28
2.29
2.30 PWM enable (for lcd backlight)
2.31
3.00 keyboard
3.01 keyboard
3.02 keyboard
3.03 keyboard
3.04 keyboard
3.05 keyboard
3.06 keyboard
3.07 keyboard
3.08 keyboard
3.09 keyboard
3.10 keyboard
3.11 keyboard
3.12 keyboard
3.13 keyboard
3.14 keyboard
3.15 keyboard
3.16
3.17
3.18
3.19
3.20
3.21
3.22
3.23
3.24
3.25
3.26
3.27
3.28
3.29 keyboard
3.30
3.31
Devices enabled in linux:
+ __harb_usb0_uhc();
+ __gpio_as_emc();
+ __gpio_as_uart0();
+ __gpio_as_dma();
+ __gpio_as_eth();
+ __gpio_as_usb();
+ __gpio_as_lcd_master();
+#if defined(CONFIG_I2S_AK4642EN)
+//wjx __gpio_as_scc1();
+ __gpio_as_i2s_master(); //wjx
+#endif
+#if defined(CONFIG_I2S_TSC2301) || defined(CONFIG_I2S_TLC320AIC23)
+ __gpio_as_ssi();
+#endif
+ //__gpio_as_ac97();
+#if defined(CONFIG_I2S_TSC2301) || defined(CONFIG_I2S_TLC320AIC23) || defined(CONFIG_I2S_CS42L51)
+ __gpio_as_i2s_slave();
+#endif
+//wjx __gpio_as_cim();
+ __gpio_as_msc();
+
+/* wjx
+ __gpio_as_output(GPIO_LED_EN);
+ __gpio_set_pin(GPIO_LED_EN);
+
+ __gpio_as_output(GPIO_DISP_OFF_N);
+ __gpio_set_pin(GPIO_DISP_OFF_N);
+*/
+ __gpio_as_output(GPIO_PWM0);
+ __gpio_set_pin(GPIO_PWM0);
+
+
+//wjx __gpio_as_input(GPIO_RTC_IRQ);
+ __gpio_as_output(GPIO_USB_CLK_EN);
+ __gpio_set_pin(GPIO_USB_CLK_EN);

421
source/lcd.ccp Normal file
View File

@@ -0,0 +1,421 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/lcd.ccp: Display driver.
// 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"
__asm__ volatile (".section .rodata\n.globl charset\ncharset:\n.incbin \"boot-programs/charset.data\"\n.section .text")
extern unsigned char const charset[127-32][8][6]
#define assert(x) do { if (!(x)) { kdebug ("assertion failed " #x); while (true) {} } } while (0)
#if defined (TRENDTAC)
static unsigned h = 800, v = 480, fps = 60, Bpp = 2
#define LOG_X_BASE 1
#define LOG_Y_BASE 1
#elif defined (NANONOTE)
static unsigned h = 320, v = 240, fps = 60, Bpp = 4
#define LOG_X_BASE 0
#define LOG_Y_BASE 0
#else
#error unknown board
#endif
#define frame_size (v * h * Bpp)
static unsigned physical_descriptor
/**/struct Descriptor {
unsigned next;
unsigned frame;
unsigned id;
unsigned cmd;
} __attribute__ ((packed))
#if defined (NANONOTE)
#define SP_PORT 2
#define SPEN 21
#define SPDA 22
#define SPCK 23
static void udelay (unsigned num):
for unsigned i = 0; i < num * (JZ_EXTAL / 1000000); ++i:
// set 0 does nothing, but costs at least one clock pulse.
gpio_set (SP_PORT, 0)
// Register names. The registers are not named in the datasheet, and in some cases the name only describes a part of the bits in it.
// The registers with bit 6 set have bit 7 set instead, because of the transfer method.
enum spi_reg:
AC = 0x00
DC = 0x01
BRIGHTNESS = 0x03
FORMAT = 0x04
BACKLIGHT1 = 0x05
VBLANK = 0x06
HBLANK = 0x07
BACKLIGHT2 = 0x08
SYNC = 0x0b
POLARITY = 0x0c
CONTRAST_RGB = 0x0d
SUB_CONTRAST_R = 0x0e
SUB_BRIGHTNESS_R= 0x0f
SUB_CONTRAST_B = 0x10
SUB_BRIGHTNESS_B= 0x11
TRIM = 0x12
COLOR = 0x13
GAMMA = 0x16
GAMMA1 = 0x17
GAMMA2 = 0x18
GAMMA3 = 0x19
GAMMA4 = 0x1a
INVERSION = 0xa5
HLEVEL = 0xa6
LLEVEL = 0xa7
FB = 0xb1
static void write_reg (unsigned reg, unsigned val):
unsigned value = (reg << 8) | (val & 0xff)
gpio_clear (SP_PORT, 1 << SPEN)
udelay (1)
for unsigned i = 0; i < 16; ++i, value <<= 1:
gpio_clear (SP_PORT, 1 << SPCK)
if value & 0x8000:
gpio_set (SP_PORT, 1 << SPDA)
else:
gpio_clear (SP_PORT, 1 << SPDA)
udelay (4)
gpio_set (SP_PORT, 1 << SPCK)
udelay (4)
gpio_set (SP_PORT, 1 << SPEN)
udelay(4)
#endif
static void reset ():
#if defined (TRENDTAC)
// Note that the sync pulse is part of the pre-display region.
// Vertical timings.
unsigned vsync = 20, vpre = 20, vpost = 0
// Horizontal timings.
unsigned hsync = 80, hpre = 80, hpost = 0
// One clock pulse per pixel.
unsigned cpp = 1
// Bits per pixel.
unsigned bpp = LCD_CTRL_BPP_16
// Configuration.
#define MODE_TFT_GEN 0
#define VSYNC_N (1 << 8)
unsigned cfg = MODE_TFT_GEN | VSYNC_N
#elif defined (NANONOTE)
// Note that the sync pulse is part of the pre-display region.
// Horizontal timings.
unsigned hsync = 1, hpre = 70, hpost = 273
// Vertical timings.
unsigned vsync = 1, vpre = 21, vpost = 2
// 3 clocks per pixel.
unsigned cpp = 3
// Bits per pixel.
unsigned bpp = LCD_CTRL_BPP_18_24
// Configuration.
unsigned cfg = LCD_CFG_MODE_SERIAL_TFT | LCD_CFG_HSP | LCD_CFG_VSP | LCD_CFG_PCP
// Set up SPI pins.
gpio_as_output (SP_PORT, (1 << SPEN) | (1 << SPCK) | (1 << SPDA))
gpio_set (SP_PORT, (1 << SPEN) | (1 << SPCK))
#else
#error unknown board
#endif
// Note that the sync pulse is part of the pre-display region.
unsigned vpe = vsync, vds = vpre, vde = vds + v, vt = vde + vpost
unsigned hpe = hsync, hds = hpre, hde = hds + h, ht = hde + hpost
cpm_stop_lcd ()
unsigned pixclock = fps * ht * vt
#if defined (TRENDTAC)
unsigned pllout = cpm_get_pllout ()
CPM_CFCR2 = pllout / pixclock - 1
unsigned val = pllout / (pixclock * 4) - 1
assert (pllout / (val + 1) <= 150000000)
assert (val <= 0xf)
cpm_set_lcdclk_div (val)
CPM_CFCR |= CPM_CFCR_UPE
#elif defined (NANONOTE)
unsigned val = cpm_get_pllout2 () / pixclock - 1
//assert (val < 0x400)
//cpm_set_pixdiv (val)
//cpm_set_pixdiv (12)
val = cpm_get_pllout2 () / (pixclock * 3) - 1
assert (val < 0x20)
//cpm_set_ldiv (val)
// Update dividers.
//CPM_CPCCR |= CPM_CPCCR_CE
#else
#error "Unknown board"
#endif
cpm_start_lcd ()
#ifdef NANONOTE
// Reset the controller.
write_reg (BACKLIGHT1, 0x1e)
// Enable display.
write_reg (BACKLIGHT1, 0x5f)
// Set data to rgbrgbrgb input, with a delta color filter.
write_reg (COLOR, 0x01)
#endif
LCD_CTRL = (bpp << LCD_CTRL_BPP_BIT) | LCD_CTRL_BST_16
LCD_CFG = cfg
LCD_HSYNC = hpe
LCD_VSYNC = vpe
LCD_VAT = (ht << 16) | vt
LCD_DAH = (hds << 16) | hde
LCD_DAV = (vds << 16) | vde
LCD_DA0 = physical_descriptor
LCD_CTRL = (bpp << LCD_CTRL_BPP_BIT) | LCD_CTRL_BST_16 | LCD_CTRL_ENA
//lcd_enable_eof_intr ()
static void putchar (unsigned x, unsigned y, unsigned ch):
if ch < 32 || ch > 126:
ch = 127
ch -= 32
for unsigned k = 0; k < 6; ++k:
for unsigned r = 0; r < 8; ++r:
LCD_FRAMEBUFFER_BASE[(y * 8 + r) * h + x * 6 + k] = charset[ch][r][k] * 0x00010101
static unsigned log_x = LOG_X_BASE, log_y = LOG_Y_BASE
static void inc_logx ():
if ++log_x >= h / 6:
log_x = LOG_X_BASE
if ++log_y >= v / 8:
log_y = LOG_Y_BASE
static void log_char (unsigned ch):
switch ch:
case '\n':
while log_x < h / 6:
putchar (log_x++, log_y, ' ')
inc_logx ()
break
default:
putchar (log_x, log_y, ch)
inc_logx ()
static void log_str (char const *str):
while *str:
log_char (*str++)
static void log_num (Kernel::Num n):
char const *encode = "0123456789abcdef"
log_char ('[')
for unsigned i = 0; i < 8; ++i:
log_char (encode[(n.h >> (4 * (7 - i))) & 0xf])
log_char (' ')
for unsigned i = 0; i < 8; ++i:
log_char (encode[(n.l >> (4 * (7 - i))) & 0xf])
log_char (']')
static void log_msg ():
log_str ("prot:")
log_num (Kernel::recv.protected_data)
log_str ("data:")
for unsigned i = 0; i < 2; ++i:
log_num (Kernel::recv.data[i])
log_char ('\n')
enum captype:
LOG = 32
SET_EOF_CB
BACKLIGHT
static unsigned spot (unsigned x, unsigned y, unsigned cx, unsigned cy):
unsigned dx2 = (x - cx) * (x - cx)
unsigned dy2 = (y - cy) * (y - cy)
unsigned d2 = dx2 + dy2
unsigned l = 120
if d2 >= l * l:
return 0
return ((l * l - d2 - 1) << 8) / (l * l)
Kernel::Num start ():
Kernel::schedule ()
map_lcd ()
map_cpm ()
#ifdef NANONOTE
map_gpio ()
#endif
Descriptor descriptor __attribute__ ((aligned (16)))
unsigned pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS
unsigned physical = Kernel::my_memory.alloc_range (pages)
assert (physical & PAGE_MASK && ~physical)
for unsigned i = 0; i < pages; ++i:
Kernel::Page p = Kernel::my_memory.create_page ()
p.alloc_physical (physical + (i << PAGE_BITS), false, true)
Kernel::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + (i << PAGE_BITS))
Kernel::free_cap (p)
for unsigned y = 0; y < v; ++y:
for unsigned x = 0; x < h; ++x:
unsigned r = spot (x, y, 100, 160)
unsigned g = spot (x, y, 160, 60)
unsigned b = spot (x, y, 220, 160)
#if defined (TRENDTAC)
LCD_FRAMEBUFFER_BASE[y * h + x] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)
#elif defined (NANONOTE)
LCD_FRAMEBUFFER_BASE[y * h + x] = (r << 16) | (g << 8) | b
#else
#error "Define your framebuffer format."
#endif
Kernel::Page p = Kernel::my_memory.mapping (&descriptor)
unsigned paddr = p.physical_address ()
physical_descriptor = paddr + ((unsigned)&descriptor & ~PAGE_MASK)
Kernel::free_cap (p)
descriptor.next = physical_descriptor
descriptor.frame = physical
descriptor.id = 0xdeadbeef
descriptor.cmd = LCD_CMD_EOFINT | ((frame_size / 4) << LCD_CMD_LEN_BIT)
unsigned dptr = (unsigned)&descriptor
__asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0")
reset ()
#if defined (TRENDTAC)
Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG)
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
#endif
// Register the backlight device.
Kernel::Cap backlight = Kernel::my_receiver.create_capability (BACKLIGHT)
Kernel::my_parent.provide_device <Setting> (backlight)
Kernel::Cap eof_cb
bool have_eof = false
bool is_on = true
unsigned backlight_user = 0
Kernel::Num current_backlight = 0
while true:
//log_str ("Wachten...\n")
Kernel::wait ()
//log_msg ()
switch Kernel::recv.protected_data.h:
case 0:
switch Kernel::recv.protected_data.l:
case IRQ_LCD:
lcd_clr_eof ()
eof_cb.invoke ()
have_eof = false
Kernel::free_cap (eof_cb)
break
#if defined (TRENDTAC)
case LOG:
log_char (Kernel::recv.data[0].l)
break
#endif
case BACKLIGHT:
switch Kernel::recv.data[0].l:
case Device::CREATE_USER:
Kernel::Cap reply = Kernel::get_reply ()
Kernel::Cap c = Kernel::my_receiver.create_capability (Kernel::Num (backlight_user++, BACKLIGHT))
reply.invoke (0, 0, c.copy ())
Kernel::free_cap (c)
Kernel::free_cap (reply)
break
case Device::DESTROY_USER:
Kernel::recv.reply.invoke ()
break
case Device::USE:
Kernel::Cap reply = Kernel::get_reply ()
Kernel::Cap arg = Kernel::get_arg ()
current_backlight = Kernel::my_receiver.get_protected (arg)
reply.invoke ()
Kernel::free_cap (arg)
Kernel::free_cap (reply)
break
case Device::UNUSE:
Kernel::Cap reply = Kernel::get_reply ()
Kernel::Cap arg = Kernel::get_arg ()
if current_backlight.value () == Kernel::my_receiver.get_protected (arg).value ():
current_backlight = 0
reply.invoke ()
Kernel::free_cap (arg)
Kernel::free_cap (reply)
break
default:
log_char ('@')
break
break
default:
log_char ('#')
log_num (Kernel::recv.protected_data)
log_char ('\n')
break
break
case BACKLIGHT:
if current_backlight.value () != Kernel::recv.protected_data.value ():
log_char ('&')
log_num (current_backlight)
log_num (Kernel::recv.protected_data)
log_char ('\n')
break
switch Kernel::recv.data[0].l:
case Setting::SET:
// TODO
unsigned state = Kernel::recv.data[1].l
if !state:
#if defined (NANONOTE)
if is_on:
write_reg (BACKLIGHT1, 0x5e)
is_on = false
#else
#endif
else:
#if defined (NANONOTE)
if !is_on:
write_reg (BACKLIGHT1, 0x5f)
is_on = true
#else
#endif
Kernel::recv.reply.invoke ()
break
case Setting::GET_RANGE:
Kernel::recv.reply.invoke (~0)
break
default:
log_char ('$')
break
break
case SET_EOF_CB:
Kernel::Cap reply = Kernel::get_reply ()
if have_eof:
Kernel::free_cap (eof_cb)
else:
Kernel::register_interrupt (IRQ_LCD)
have_eof = true
eof_cb = Kernel::get_arg ()
reply.invoke ()
Kernel::free_cap (reply)
break
default:
log_char ('~')
log_num (Kernel::recv.protected_data)
log_char ('\n')
break

71
source/metronome.ccp Normal file
View File

@@ -0,0 +1,71 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/metronome.ccp: Userspace program.
// 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"
#include "keys.hh"
Kernel::Num start ():
Kernel::schedule ()
Buzzer buzzer = Kernel::my_parent.get_device <Buzzer> ()
Keyboard kbd = Kernel::my_parent.get_device <Keyboard> ()
Kernel::Cap key = Kernel::my_receiver.create_capability (0)
kbd.set_cb (key)
// Frequency of the pulse train in millihertz.
unsigned mHz = 1000
// Frequency of single pulses in hertz.
unsigned freq = 1000
bool running (false)
while true:
Kernel::wait ()
switch Kernel::recv.protected_data.l:
case ~0:
if running:
buzzer.beep (freq, 10, ~0)
Kernel::my_receiver.set_alarm (HZ * 1000 / mHz)
break
case 0:
if Kernel::recv.data[0].l & Keyboard::RELEASE:
break
switch Kernel::recv.data[0].l:
case Key::VOLUME_UP:
freq = freq * 11 / 10
break
case Key::VOLUME_DOWN:
freq = freq * 9 / 10
break
case Key::LEFT:
mHz = mHz * 99 / 100
break
case Key::RIGHT:
mHz = mHz * 101 / 100
break
case Key::UP:
mHz = mHz * 11 / 10
break
case Key::DOWN:
mHz = mHz * 9 / 10
break
case Key::P:
running = !running
if running:
Kernel::my_receiver.set_alarm (0)
break
break
default:
kdebug ("metronome: huh?\n")
break

303
source/nanonote-gpio.ccp Normal file
View File

@@ -0,0 +1,303 @@
#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]
Kernel::Cap event
bool is_active
bool is_scanning
public:
unsigned size ():
return NUM_KEYS
void send_keys (unsigned first, Kernel::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 (Kernel::Num (d[0], d[1]), Kernel::Num (d[2], d[3]))
bool scanning ():
return is_scanning
void inactive ():
if is_active:
Kernel::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 |= 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 (Kernel::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, Key::BACKSLASH, Key::QUOTE, Key::COMMA, Key::PERIOD, Key::SLASH, Key::UP },
{ Key::O, Key::L, Key::EQUAL, Key::ARROW, Key::SPACE, Key::QI, Key::CTRL, Key::LEFT },
{ Key::F8, Key::P, Key::BACKSPACE, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT },
{ Key::SHIFT, Key::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, Key::BACKSLASH, Key::QUOTE, Key::COMMA, Key::PERIOD, Key::SLASH, Key::UP,
Key::O, Key::L, Key::EQUAL, Key::ARROW, Key::SPACE, Key::QI, Key::CTRL, Key::LEFT,
Key::F8, Key::P, Key::BACKSPACE, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT,
Key::SHIFT, Key::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 PowerButton:
bool state, started
Kernel::Cap cb
public:
void scan ():
gpio_mask_irq (3, 1 << 29)
bool s = gpio_get_port (3) & (1 << 29)
if s != state:
state = s
cb.invoke (state ? Keyboard::RELEASE : 0)
gpio_as_interrupt (3, 1 << 29, !state, true)
gpio_unmask_irq (3, 1 << 29)
PowerButton ():
gpio_as_gpio (3, 29)
state = true
started = false
void set_cb (Kernel::Cap c):
if started:
Kernel::free_cap (cb)
else:
started = true
cb = c
state = true
scan ()
enum codes:
KBD_DEV = 32
PWR
Kernel::Num start ():
Kernel::schedule ()
map_gpio ()
DevKbd kbd
PowerButton pwr
Device dev = Kernel::my_receiver.create_capability (KBD_DEV)
Keyboard pw = Kernel::my_receiver.create_capability (PWR)
Kernel::my_parent.provide_device <Keyboard> (dev.copy (), 0)
Kernel::my_parent.provide_device <Keyboard> (pw.copy (), 1)
Kernel::free_cap (dev)
Kernel::free_cap (pw)
if kbd.scanning ():
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
unsigned user (~0)
unsigned next_user (0)
Kernel::register_interrupt (IRQ_GPIO3)
while true:
Kernel::wait ()
switch Kernel::recv.protected_data.h:
case ~0:
// Alarm.
kbd.scan ()
if kbd.scanning ():
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
break
case 0:
switch Kernel::recv.protected_data.l:
case IRQ_GPIO3:
// Interrupt.
pwr.scan ()
kbd.scan ()
if kbd.scanning ():
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
Kernel::register_interrupt (IRQ_GPIO3)
break
case PWR:
// Power button request.
switch Kernel::recv.data[0].l:
case Keyboard::SET_CB:
pwr.set_cb (Kernel::get_arg ())
Kernel::recv.reply.invoke ()
break
default:
kdebug ("power button invalid request\n")
break
break
case KBD_DEV:
// Keyboard device control request.
switch Kernel::recv.data[0].l:
case Device::CREATE_USER:
Kernel::Cap reply = Kernel::get_reply ()
Keyboard cap = Kernel::my_receiver.create_capability (Kernel::Num (next_user++, KBD_DEV))
reply.invoke (0, 0, cap.copy ())
Kernel::free_cap (cap)
Kernel::free_cap (reply)
break
case Device::DESTROY_USER:
Kernel::recv.reply.invoke ()
break
case Device::UNUSE:
kbd.inactive ()
Kernel::recv.reply.invoke ()
break
case Device::USE:
Kernel::Cap reply = Kernel::get_reply ()
user = Kernel::my_receiver.get_protected (Kernel::recv.arg).l
reply.invoke ()
Kernel::free_cap (reply)
break
default:
kdebug ("gpio other dev:")
kdebug_num (Kernel::recv.data[0].l)
kdebug ("\n")
break
break
default:
break
break
case KBD_DEV:
// Keyboard device user request.
if Kernel::recv.protected_data.l != user:
kdebug ("invalid user requesting\n")
Kernel::recv.reply.invoke ()
break
switch Kernel::recv.data[0].l:
case Keyboard::SET_CB:
Kernel::Cap reply = Kernel::get_reply ()
kbd.active (Kernel::get_arg ())
reply.invoke ()
Kernel::free_cap (reply)
break
case Keyboard::GET_NUM_KEYS:
Kernel::recv.reply.invoke (kbd.size ())
break
case Keyboard::GET_KEYS:
kbd.send_keys (Kernel::recv.data[0].l, Kernel::recv.reply)
break
default:
kdebug ("keyboard other\n")
break
break
default:
kdebug ("keyboard unknown num: ")
kdebug_num (Kernel::recv.protected_data.h)
kdebug ("\n")