⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 led.c

📁 pebble
💻 C
字号:
/* 
 * Copyright 1999, 2000, 2001, 2002 Lucent Technologies Inc.
 * All Rights Reserved.
 * Information Sciences Research Center, Bell Labs.
 *
 * LUCENT TECHNOLOGIES DOES NOT CLAIM MERCHANTABILITY OF THIS SOFTWARE 
 * OR THE SUITABILITY OF THIS SOFTWARE FOR ANY PARTICULAR PURPOSE. The
 * software is provided "as is" without expressed or implied warranty 
 * of any kind.
 *
 * These notices must be retained in any copies of any part of this
 * software.
 *
 */

/*
 * combined LED, LCD, and BCR (board configuration register) driver
 *
 * Everything send to the LED is printed on the top line of the LCD display.
 *
 * In addition, can write a character anywhere on the LCD display.
 *
 * Runs in user mode with interrupts enabled.
 *
 * This driver is based in part on PMON sources from Algorithmics,
 * which are in the public domain.
 */

#include "pebble.h"
#include "string.h"
#include "machine/cpu.h"
#ifndef	Cobalt
#include "sbd.h"
#include "rtc.h"
#include "lcd.h"
#else
#include "qube.h"
#endif
#include "mem.h"
#include "time.h"
#include "synch.h"

#ifndef	Cobalt	/* presently not supported on Cobalt */

#define	LED_START	((volatile uint *)(IO_BASE+LED_BASE))
#define	LCD_START	((volatile uint *)(IO_BASE+LCD_BASE))

static volatile lcddev *lcd = (lcddev *)LCD_START;
static int lcd_present = 0;
static int lcd_sem, led_sem;

const char LCD_NOT_PRESENT[] = "LCD not present";
const char INVALID_LCD_ADDRESS[] = "invalid LCD row/column address";


/* first the board configuration register code */

/* portal implementation */
int
sys_bcr_clear(Thread *t, uint mask)
{
	int i;
        int *addr;

#ifdef P4032
	/* first do the low bits */
	addr = (int *) (IO_BASE + BCR_BASE);
	for (i = 0; i < 8; ++i) {
		if (mask & 01) {
			*addr = 0;
		}
		addr++;
		mask >>= 1;
	}
#else
	/* first do the low bits */
	addr = (int *) (IO_BASE + BCR0_BASE);
	for (i = 0; i < 8; ++i) {
		if (mask & 01) {
			*addr = 0;
		}
		addr++;
		mask >>= 1;
	}

	addr = (int *) (IO_BASE + BCR1_BASE);
	for (i = 0; i < 8; ++i) {
		if (mask & 01) {
			*addr = 0;
		}
		addr++;
		mask >>= 1;
	}
#endif
	return(0);
}

/* portal implementation */
int
sys_bcr_set(Thread *t, uint mask)
{
	int i;
        int *addr;

#ifdef P4032
	/* first do the low bits */
	addr = (int *) (IO_BASE + BCR_BASE);
	for (i = 0; i < 8; ++i) {
		if (mask & 01) {
			*addr = 1;
		}
		addr++;
		mask >>= 1;
	}
#else
	/* first do the low bits */
	addr = (int *) (IO_BASE + BCR0_BASE);
	for (i = 0; i < 8; ++i) {
		if (mask & 01) {
			*addr = 1;
		}
		addr++;
		mask >>= 1;
	}

	addr = (int *) (IO_BASE + BCR1_BASE);
	for (i = 0; i < 8; ++i) {
		if (mask & 01) {
			*addr = 1;
		}
		addr++;
		mask >>= 1;
	}
#endif
	return(0);
}

/* 
 * lcd driver code 
 */

/* checks whether the LCD is busy. Takes at least one usec. */
static int
lcd_busy(void)
{
	us_delay(1);
	return (lcd->lcd_stat & LCD_STAT_BUSY) != 0;
}

/* waits until LCD is free again */
static int
lcd_wait(void)
{
	int i;
	int busy;
	int iter = 2000;	/* about 2msec. */

	for (i = 0; ((busy = lcd_busy()) != 0) && (i < iter); i++)
		;

	return (busy)? -1 : 0;
}

static void
lcd_command(uchar cmd)
{
	if (lcd_wait() < 0)
		return; 
	lcd->lcd_cmd = cmd;
	us_delay(40);
}

static uint
lcd_rdata(void)
{
	uint data;

	lcd_wait();
	data = lcd->lcd_data & 0xff;
	us_delay(40);

	return data;
}


static void
lcd_wdata(char c)
{
	if (lcd_wait() < 0)
		return;
	lcd->lcd_data = c;
	us_delay(40);
}

static void
lcd_init(void)
{
	/* test pattern for display data memory */
	static const uchar tpat[4] = {0xaa, 0x55, 0xff, 0x00};
	int i;

	lcd_present = 0;

	/* should we wait a little here? */
	if (lcd_wait() < 0)
		return;

	lcd_command (LCD_CLEAR);
	/* should be busy */
	if (lcd_busy() == 0)
		return;

	/* initialize the display */
	lcd_command (LCD_FUNC | LCD_FUNC_8BIT | LCD_FUNC_2LINE | LCD_FUNC_5x7);
	lcd_command (LCD_CTRL | LCD_CTRL_DISPLAY);
	lcd_command (LCD_MODE | LCD_MODE_INCR);
	lcd_command (LCD_HOME);

	/* store pattern into display memory */
	lcd_command (LCD_SET_DDADDR | 0);
	for (i = 0; i < sizeof(tpat); i++)
		lcd_wdata (tpat[i]);

	/* read back pattern */
	lcd_command (LCD_SET_DDADDR | 0);
	for (i = 0; i < sizeof(tpat); i++) {
		/* check dd ram contents */
		if (lcd_rdata () != tpat[i])
			return;
        }

	lcd_present = 1;
}

/*
 * write a NULL terminated string at specified position
 * Only up to LCD_CHARS chars are printed from the string.
 *
 * The write to the LCD is protected with a semaphore against
 * concurrent access. Note that we must not use mutex locks,
 * since this is a slow operation and the LCD driver runs with
 * interrupts enabled.
 */
int
lcd_write(int row, int col, const char *s)
{
	int i;
	int addr;

	if (!lcd_present)
		error(LCD_NOT_PRESENT);
	if (row < 0 || row >= LCD_LINES || col < 0 || col >= LCD_CHARS)
		error(INVALID_LCD_ADDRESS);

	sem_wait(lcd_sem);
	addr = row * 0x40 + col;
	lcd_command(LCD_SET_DDADDR | addr);

	for (i = 0; (col + i) < LCD_CHARS && s[i] != 0; i++)
		lcd_wdata(s[i]);
	sem_post(lcd_sem);

	return i;
}

static void
lcd_write_top_line(const char *s, int len)
{
	int i;
	char line[LCD_CHARS];

	for (i = 0; (i < len) && (i < LCD_CHARS); i++) {
		line[i] = s[i];
		if (line[i] < ' ')		/* control characters */
			line[i] = ' ';
	}

	/* fill the rest of the line with blanks */
	for (; i < LCD_CHARS; i++)
		line[i] = ' ';

	if (lcd_present)
		lcd_write(0, 0, line);
}

/*
 * led driver code
 *
 * The write to the LED is protected with a semaphore against
 * concurrent access. Note that we must not use mutex locks,
 * since the LED driver runs with interrupts enabled.
 */

static int
led_write(char *str, int len)
{
	int i = 0;

	/* turn on LED */
	sys_bcr_set(NULL, BCR_LED_ON);
	
	/* show chars */
	sem_wait(led_sem);
	if (str != NULL)
		for (i = 0; i < 4 && i < len && str[i] != '\0' && str[i] != '\n'; i++) 
			LED_START[3-i] = str[i] & 0xff;

	/* blank unfilled spaces */
	for (; i < 4; i++)
		LED_START[3-i] = ' ';
	sem_post(led_sem);

	lcd_write_top_line(str, len);

	return i;
}

/* writes string up to 4 chars of string s to LED */
int
sys_led_write(Thread *t, char *str, int len)
{
	param_check(str, len, 0);
	return led_write(str, len);
}

/* writes a string to LCD */
int
sys_lcd_write(Thread *t, int row, int col, const char *s)
{
	param_check(s, LCD_CHARS, 0);
	return lcd_write(row, col, s);
}

#else /* Cobalt - dummy functions */

static int lcd_present = 0;
static int lcd_sem, led_sem;

static void 
lcd_init()
{

}

static int
led_write(char *str, int len)
{
	return 0;
}

int
sys_bcr_clear(Thread *t, uint mask)
{
	return 0;
}

int
sys_bcr_set(Thread *t, uint mask)
{
	return 0;
}

int
sys_led_write(Thread *t, char *str, int len)
{
	return 0;
}

int
sys_lcd_write(Thread *t, int row, int col, const char *s)
{
	return 0;
}

#endif	/* !Cobalt */

/*
 * initialization
 */

/* driver initialization thread */
int main()
{
	int x; 
	int lcd_id;
	char *msg = "LED & LCD";

        /* verify that we are running in user mode with interrupts enabled */ 
        if (!check_psw(1,1)) {
                printf("led: invalid processor status: %08lx\n", get_psw());
                task_exit(1);
        }

	printf("LED and LCD initialization. asid=%d stack at %p\n",
	       get_asid(), &x);

	if ((led_sem = sem_create(1)) < 0)
		panic("sem_create of led_sem failed");
	if ((lcd_sem = sem_create(1)) < 0)
		panic("sem_create of lcd_sem failed");

	lcd_init();
	if (lcd_present)
		printf("LCD initialized\n");
	else
		printf("LCD is missing\n");

	/* cannot call sys_led_write,  */
	/* since it expects the argument to reside on system stack */
	/* only first four characters will apprer on LED */
	led_write(msg, strlen(msg));

	if (portal_create(WRITE2PORT(3), "smtiii", 0, sys_led_write, 0) < 0)
		panic("portal_create for led_write on standard error");

	if (portal_create_pair("led", NULL, sys_led_write) < 0)
		panic("portal_create_pair for led failed");
	if (lcd_present) {
		if ((lcd_id = portal_create(-1, "smtiii", 0, sys_lcd_write, 0))
		    < 0)
			panic("portal_create for sys_lcd_write failed");
		if (portal_name(lcd_id, "lcd", 1) < 0)
			panic("portal_name for lcd_write failed");
	}
	if (portal_create(SYS_BCR_SET, "smtiii", 0, sys_bcr_set, 0) < 0)
		panic("portal_create for bcr_set() failed\n");
	if (portal_create(SYS_BCR_CLEAR, "smtiii", 0, sys_bcr_clear, 0) < 0)
		panic("portal_create for bcr_clear() failed\n");
	/*
	 * return to initialization code.
	 * cannot just "return", since the startup code (crt0.S) calls
	 * exit when main routine terminates.
	 */
	call_portal(SYS_RTN_RPC);
	return(1);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -