mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-04-21 12:27:27 +03:00
lots of stuff
This commit is contained in:
@@ -60,7 +60,7 @@ Kernel::Num start ():
|
||||
DevBuzzer buzzer
|
||||
|
||||
Device dev = Kernel::my_receiver.create_capability (BUZZER)
|
||||
Kernel::my_parent.ocall (dev.copy (), Buzzer::ID)
|
||||
Kernel::my_parent.provide_device <Buzzer> (dev.copy ())
|
||||
Kernel::free_cap (dev)
|
||||
unsigned user (~0)
|
||||
unsigned next_user (0)
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "devices.hh"
|
||||
#include "init.hh"
|
||||
#define ARCH
|
||||
#include "arch.hh"
|
||||
|
||||
@@ -247,6 +246,12 @@ class Pwm:
|
||||
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 ()
|
||||
@@ -260,7 +265,12 @@ Kernel::Num start ():
|
||||
Lockleds leds
|
||||
Pwm pwm
|
||||
|
||||
((Init)Kernel::my_parent).register_gpio ()
|
||||
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)
|
||||
@@ -286,23 +296,23 @@ Kernel::Num start ():
|
||||
// Reregister the interrupt.
|
||||
Kernel::register_interrupt (IRQ_GPIO0)
|
||||
break
|
||||
case Init::GPIO_KEYBOARD:
|
||||
case KEYBOARD:
|
||||
set_cb (KEYBOARD_EVENT)
|
||||
Kernel::recv.reply.invoke ()
|
||||
kbd.send_initial ()
|
||||
event (KEYBOARD_EVENT, ~0)
|
||||
break
|
||||
case Init::GPIO_TOUCHPAD:
|
||||
case TOUCHPAD:
|
||||
set_cb (TOUCHPAD_EVENT)
|
||||
Kernel::recv.reply.invoke ()
|
||||
tp.send_initial ()
|
||||
event (TOUCHPAD_EVENT, ~0)
|
||||
break
|
||||
case Init::GPIO_LOCKLEDS:
|
||||
case LOCKLEDS:
|
||||
leds.set (Kernel::recv.data[0].l)
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
case Init::GPIO_PWM:
|
||||
case PWM:
|
||||
pwm.set_backlight (Kernel::recv.data[0].l)
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
|
||||
@@ -60,7 +60,6 @@ static void setup ():
|
||||
unsigned state = 0
|
||||
Kernel::Caps caps = Kernel::my_memory.create_caps (32)
|
||||
slot = caps.use ()
|
||||
Kernel::Caps slot0 = Kernel::my_thread.get_caps (0)
|
||||
Kernel::Cap user
|
||||
unsigned device
|
||||
while true:
|
||||
@@ -68,32 +67,37 @@ static void setup ():
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Keyboard::ID:
|
||||
switch Kernel::recv.data[0].h:
|
||||
case 0:
|
||||
caps.set (KBDDEV, arg.copy ())
|
||||
kbd_dev = Kernel::Cap (slot, KBDDEV)
|
||||
case Parent::PROVIDE_DEVICE:
|
||||
switch Kernel::recv.data[1].l:
|
||||
case Keyboard::ID:
|
||||
switch Kernel::recv.data[0].h:
|
||||
case 0:
|
||||
caps.set (KBDDEV, arg.copy ())
|
||||
kbd_dev = Kernel::Cap (slot, KBDDEV)
|
||||
break
|
||||
case 1:
|
||||
caps.set (SYSREQ, arg.copy ())
|
||||
sysreq = Kernel::Cap (slot, SYSREQ)
|
||||
break
|
||||
default:
|
||||
kdebug ("unexpected keyboard\n")
|
||||
break
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case 1:
|
||||
caps.set (SYSREQ, arg.copy ())
|
||||
sysreq = Kernel::Cap (slot, SYSREQ)
|
||||
case Buzzer::ID:
|
||||
caps.set (BUZDEV, arg.copy ())
|
||||
buz_dev = Kernel::Cap (slot, BUZDEV)
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
default:
|
||||
kdebug ("unexpected keyboard\n")
|
||||
kdebug ("unexpected device\n")
|
||||
break
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Buzzer::ID:
|
||||
caps.set (BUZDEV, arg.copy ())
|
||||
buz_dev = Kernel::Cap (slot, BUZDEV)
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Parent::GET_DEVICE:
|
||||
user = reply
|
||||
device = Kernel::recv.data[1].l
|
||||
slot0.print (reply.idx ())
|
||||
break
|
||||
default:
|
||||
kdebug ("unknown setup request for init\n")
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "devices.hh"
|
||||
#include "init.hh"
|
||||
#define ARCH
|
||||
#include "arch.hh"
|
||||
|
||||
@@ -28,11 +27,9 @@ extern unsigned char const charset[127-32][6]
|
||||
#define assert(x) do { while (!(x)) kdebug ("assertion failed " #x); } while (0)
|
||||
|
||||
#if defined (TRENDTAC)
|
||||
// For now, support only 16 bpp.
|
||||
// Screen is 800x480 tft.
|
||||
static unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2
|
||||
#else if defined (NANONOTE)
|
||||
static unsigned h = 320, v = 240, fps = 70, Bpp = 3
|
||||
static unsigned h = 800, v = 480, fps = 60, Bpp = 2
|
||||
#elif defined (NANONOTE)
|
||||
static unsigned h = 320, v = 240, fps = 70, Bpp = 4
|
||||
#else
|
||||
#error unknown board
|
||||
#endif
|
||||
@@ -40,19 +37,80 @@ static unsigned h = 320, v = 240, fps = 70, Bpp = 3
|
||||
|
||||
static unsigned physical_descriptor
|
||||
|
||||
struct Descriptor:
|
||||
unsigned next
|
||||
unsigned frame
|
||||
unsigned id
|
||||
unsigned cmd
|
||||
/**/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_B = 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):
|
||||
gpio_clear (SP_PORT, 1 << SPEN)
|
||||
udelay (1)
|
||||
unsigned value = (reg << 8) | (val & 0xff)
|
||||
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 (1)
|
||||
gpio_set (SP_PORT, 1 << SPEN)
|
||||
udelay(4)
|
||||
#endif
|
||||
|
||||
static void reset ():
|
||||
#if defined (TRENDTAC)
|
||||
unsigned fps = 60
|
||||
#if defined (TRENDTAC)
|
||||
// Note that the sync pulse is part of the pre-display region.
|
||||
// Vertical timings.
|
||||
unsigned vps = 0, vpe = vps + 20, vds = vpe, vde = vds + v, vt = vde
|
||||
unsigned vsync = 20, vpre = 20, vpost = 0
|
||||
// Horizontal timings.
|
||||
unsigned hps = 0, hpe = hps + 80, hds = hpe, hde = hds + h, ht = hde
|
||||
unsigned hsync = 80, hpre = 80, hpost = 0
|
||||
|
||||
// One clock pulse per pixel.
|
||||
unsigned extra = 0
|
||||
// Bits per pixel.
|
||||
unsigned bpp = LCD_CTRL_BPP_16
|
||||
@@ -60,33 +118,41 @@ static void reset ():
|
||||
#define MODE_TFT_GEN 0
|
||||
#define VSYNC_N (1 << 8)
|
||||
unsigned cfg = MODE_TFT_GEN | VSYNC_N
|
||||
#elif defined (NANONOTE)
|
||||
unsigned fps = 70
|
||||
#elif defined (NANONOTE)
|
||||
// Note that the sync pulse is part of the pre-display region.
|
||||
// Vertical timings.
|
||||
unsigned vps = 0, vpe = vps + 1, vds = vpe + 20, vde = vds + v, vt = vde + 1
|
||||
unsigned vsync = 1, vpre = 21, vpost = 2
|
||||
// Horizontal timings.
|
||||
unsigned hps = 0, hpe = hps + 1, hds = hpe + 140, hde = hds + h, ht = hde + 273
|
||||
unsigned hsync = 1, hpre = 70, hpost = 686
|
||||
|
||||
// 3 bytes per pixel, so for the display area 2 extra clocks are sent.
|
||||
unsigned extra = 2
|
||||
// Bits per pixel.
|
||||
unsigned bpp = LCD_CTRL_BPP_18_24
|
||||
// Configuration.
|
||||
unsigned cfg = LCD_CFG_MODE_TFT_SERIAL_TFT | LCD_CFG_PCP | LCD_CFG_HSP | LCD_CFG_VSP
|
||||
#else
|
||||
#error unknown board
|
||||
#endif
|
||||
unsigned cfg = LCD_CFG_MODE_SERIAL_TFT | LCD_CFG_HSP | LCD_CFG_VSP
|
||||
// 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 vps = 0, vpe = vps + vsync, vds = vps + vpre, vde = vds + v, vt = vde + vpost
|
||||
unsigned hps = 0, hpe = hps + hsync, hds = hps + hpre, hde = hds + h, ht = hde + hpost
|
||||
|
||||
LCD_CTRL = bpp | LCD_CTRL_BST_16
|
||||
LCD_VSYNC = (vps << 16) | vpe
|
||||
LCD_HSYNC = (hps << 16) | hpe
|
||||
LCD_DAV = (vds << 16) | vde
|
||||
LCD_DAH = (hds << 16) | hde
|
||||
LCD_VAT = (ht << 16) | vt
|
||||
LCD_CFG = cfg
|
||||
LCD_HSYNC = (hps << 16) | hpe
|
||||
LCD_VSYNC = (vps << 16) | vpe
|
||||
LCD_VAT = (ht << 16) | vt
|
||||
LCD_DAH = (hds << 16) | hde
|
||||
LCD_DAV = (vds << 16) | vde
|
||||
LCD_CTRL = (bpp << LCD_CTRL_BPP_BIT) | LCD_CTRL_BST_16
|
||||
|
||||
cpm_stop_lcd ()
|
||||
|
||||
unsigned pixclock = fps * (ht + extra * (hde - hds)) * vt
|
||||
unsigned pixclock = fps * (ht + extra * h) * vt
|
||||
|
||||
#if defined (TRENDTAC)
|
||||
unsigned pllout = cpm_get_pllout ()
|
||||
@@ -98,28 +164,30 @@ static void reset ():
|
||||
cpm_set_lcdclk_div (val)
|
||||
CPM_CFCR |= CPM_CFCR_UPE
|
||||
#elif defined (NANONOTE)
|
||||
unsigned val = cpm_get_pllout2 () / pclk - 1
|
||||
if val > 0x3ff:
|
||||
kdebug ("pixel clock too large\n")
|
||||
Kernel::panic ()
|
||||
return
|
||||
unsigned val = cpm_get_pllout2 () / pixclock - 1
|
||||
kdebug_num (val)
|
||||
kdebug ("\n")
|
||||
assert (val < 0x400)
|
||||
cpm_set_pixdiv (val);
|
||||
|
||||
|
||||
val = cpm_get_pllout () / (pixclock * 3)
|
||||
if val > 0x1f:
|
||||
kdebug ("pixel divider too large\n")
|
||||
Kernel::panic ()
|
||||
return
|
||||
assert (val < 0x20)
|
||||
cpm_set_ldiv (val)
|
||||
// Update dividers.
|
||||
CPM_CPCCR |= CPM_CPCCR_CE
|
||||
#endif
|
||||
|
||||
cpm_start_lcd ()
|
||||
|
||||
LCD_DA0 = physical_descriptor
|
||||
lcd_set_ena ()
|
||||
lcd_enable_eof_intr ()
|
||||
//lcd_enable_eof_intr ()
|
||||
|
||||
#ifdef NANONOTE
|
||||
// Reset registers.
|
||||
write_reg (BACKLIGHT1, 0)
|
||||
// Enable display.
|
||||
write_reg (BACKLIGHT1, 0x5f)
|
||||
#endif
|
||||
|
||||
static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff, unsigned bg = 0x0000):
|
||||
if ch < 32 || ch > 126:
|
||||
@@ -170,9 +238,16 @@ static void log_msg ():
|
||||
log_num (Kernel::recv.data[i])
|
||||
log_char ('\n')
|
||||
|
||||
enum captype:
|
||||
LOG
|
||||
SET_EOF_CB
|
||||
|
||||
Kernel::Num start ():
|
||||
map_lcd ()
|
||||
map_cpm ()
|
||||
#ifdef NANONOTE
|
||||
map_gpio ()
|
||||
#endif
|
||||
|
||||
Descriptor descriptor __attribute__ ((aligned (16)))
|
||||
unsigned pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS
|
||||
@@ -184,23 +259,22 @@ Kernel::Num start ():
|
||||
Kernel::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE)
|
||||
Kernel::free_cap (p)
|
||||
for unsigned y = 0; y < v; ++y:
|
||||
unsigned g = (y << 6) / v
|
||||
unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * h * h + 25 * v * v)
|
||||
unsigned g = (y << 8) / v
|
||||
for unsigned x = 0; x < h; ++x:
|
||||
unsigned r = (x << 5) / h
|
||||
unsigned b = ((9 * x * x + 25 * y * y) << 5) / (9 * h * h + 25 * v * v)
|
||||
if r != olr:
|
||||
olr = r
|
||||
r = 0x1f
|
||||
unsigned oyb = b
|
||||
if y > 0:
|
||||
oyb = ((9 * x * x + 25 * (y - 1) * (y - 1)) << 5) / (9 * h * h + 25 * v * v)
|
||||
if b != ob || b != oyb:
|
||||
ob = b
|
||||
b = 0x1f
|
||||
LCD_FRAMEBUFFER_BASE[y * h + x] = (r << 11) | (g << 5) | (b)
|
||||
unsigned r = (x << 8) / h
|
||||
unsigned b = ((x + y) << 8) / (h + v)
|
||||
#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) * Bpp + 2] = r
|
||||
LCD_FRAMEBUFFER_BASE[(y * h + x) * Bpp + 1] = g
|
||||
LCD_FRAMEBUFFER_BASE[(y * h + x) * Bpp + 0] = b
|
||||
#else
|
||||
#error "Define your framebuffer format."
|
||||
#endif
|
||||
Kernel::Page p = Kernel::my_memory.mapping (&descriptor)
|
||||
physical_descriptor = p.physical_address () + ((unsigned)&descriptor & ~PAGE_MASK)
|
||||
unsigned paddr = p.physical_address ()
|
||||
physical_descriptor = paddr + ((unsigned)&descriptor & ~PAGE_MASK)
|
||||
Kernel::free_cap (p)
|
||||
descriptor.next = physical_descriptor
|
||||
descriptor.frame = physical
|
||||
@@ -210,7 +284,7 @@ Kernel::Num start ():
|
||||
__asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0")
|
||||
reset ()
|
||||
|
||||
Kernel::Cap logcap = Kernel::my_receiver.create_capability (Init::LCD_LOG)
|
||||
Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG)
|
||||
#if defined (TRENDTAC)
|
||||
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
|
||||
#endif
|
||||
@@ -225,7 +299,7 @@ Kernel::Num start ():
|
||||
lcd_clr_eof ()
|
||||
eof_cb.invoke ()
|
||||
break
|
||||
case Init::LCD_SET_EOF_CB:
|
||||
case SET_EOF_CB:
|
||||
if have_eof:
|
||||
Kernel::free_cap (eof_cb)
|
||||
else:
|
||||
@@ -236,7 +310,7 @@ Kernel::Num start ():
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Init::LCD_LOG:
|
||||
case LOG:
|
||||
log_char (Kernel::recv.data[0].l)
|
||||
break
|
||||
default:
|
||||
|
||||
@@ -25,10 +25,11 @@ Kernel::Num start ():
|
||||
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
|
||||
Kernel::my_receiver.set_alarm (1)
|
||||
bool running (true)
|
||||
bool running (false)
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.protected_data.l:
|
||||
@@ -48,10 +49,10 @@ Kernel::Num start ():
|
||||
freq = freq * 9 / 10
|
||||
break
|
||||
case Key::LEFT:
|
||||
mHz = mHz * 101 / 100
|
||||
mHz = mHz * 99 / 100
|
||||
break
|
||||
case Key::RIGHT:
|
||||
mHz = mHz * 99 / 100
|
||||
mHz = mHz * 101 / 100
|
||||
break
|
||||
case Key::UP:
|
||||
mHz = mHz * 11 / 10
|
||||
@@ -62,7 +63,7 @@ Kernel::Num start ():
|
||||
case Key::P:
|
||||
running = !running
|
||||
if running:
|
||||
Kernel::my_receiver.set_alarm (1)
|
||||
Kernel::my_receiver.set_alarm (0)
|
||||
break
|
||||
break
|
||||
default:
|
||||
|
||||
@@ -202,8 +202,8 @@ Kernel::Num start ():
|
||||
|
||||
Device dev = Kernel::my_receiver.create_capability (KBD_DEV)
|
||||
Keyboard pw = Kernel::my_receiver.create_capability (PWR)
|
||||
Kernel::my_parent.ocall (dev.copy (), Kernel::Num (Keyboard::ID, 0))
|
||||
Kernel::my_parent.ocall (pw.copy (), Kernel::Num (Keyboard::ID, 1))
|
||||
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 ():
|
||||
|
||||
Reference in New Issue
Block a user