mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-12-29 18:52:25 +02:00
fixes and improvements
This commit is contained in:
parent
df38266bb8
commit
283b97955d
@ -21,7 +21,7 @@
|
||||
#include "arch.hh"
|
||||
|
||||
// Interval between polls for keyboard (when keys are pressed) and battery/power (always) events
|
||||
#define ALARM_INTERVAL (HZ / 10)
|
||||
#define ALARM_INTERVAL (HZ / 1)
|
||||
|
||||
// GPIO pins for the devices (port.pin)
|
||||
|
||||
@ -89,75 +89,89 @@ enum battery_type:
|
||||
BATTERY_CHARGED
|
||||
|
||||
class Keyboard:
|
||||
enum { NUM_COLS = 17 }
|
||||
enum { COL_MASK = 0x2000ffff }
|
||||
enum { ROW_MASK = 0x000000ff }
|
||||
|
||||
unsigned keys[NUM_COLS]
|
||||
bool scanning
|
||||
|
||||
unsigned keys[GPIO_KBD_NUM_COLS]
|
||||
void parse (unsigned col, unsigned data):
|
||||
for unsigned row = 0; row < GPIO_KBD_NUM_ROWS; ++row:
|
||||
if (data ^ keys[col]) & (1 << row):
|
||||
unsigned code = (col << 3) | row
|
||||
if data & (1 << row):
|
||||
code |= 0x10000
|
||||
event (KEYBOARD_EVENT, code)
|
||||
keys[col] = data
|
||||
public:
|
||||
bool is_scanning ():
|
||||
return scanning
|
||||
void scan ():
|
||||
kdebug ("keyboard scan\n")
|
||||
// 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
|
||||
unsigned data
|
||||
for unsigned col = 0; col < GPIO_KBD_NUM_COLS; ++col:
|
||||
// clear pin
|
||||
GPIO_GPDR (GPIO_KBD_COL_PORT) = dat
|
||||
// output
|
||||
GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir | (1 << cols[col])
|
||||
// Generate events of previous column. Do that now, so there is a short delay for the data to stabilize.
|
||||
if col != 0:
|
||||
parse (col - 1, data)
|
||||
else:
|
||||
// Add a short delay for stabilization.
|
||||
parse (0, keys[0])
|
||||
data = GPIO_GPDR (GPIO_KBD_ROW_PORT) & GPIO_KBD_ROW_MASK
|
||||
// set pin
|
||||
GPIO_GPDR (GPIO_KBD_COL_PORT) = dat | (1 << cols[col])
|
||||
// input
|
||||
GPIO_GPDIR (GPIO_KBD_COL_PORT) = dir
|
||||
parse (GPIO_KBD_NUM_COLS - 1, data)
|
||||
// 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
|
||||
// clear pending interrupts.
|
||||
for unsigned i = 0; i < 8; ++i:
|
||||
GPIO_GPFR (GPIO_KBD_ROW_PORT) |= 1 << i
|
||||
// Reenable interrupts.
|
||||
GPIO_GPIER (GPIO_KBD_ROW_PORT) |= GPIO_KBD_ROW_MASK
|
||||
Keyboard ():
|
||||
// Set all columns to input and disable the pull-ups.
|
||||
GPIO_GPDIR (3) &= ~COL_MASK
|
||||
GPIO_GPPUR (3) &= ~COL_MASK
|
||||
// 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_GPDIR (0) &= ~ROW_MASK
|
||||
GPIO_GPPUR (0) |= ROW_MASK
|
||||
// Enable interrupts on falling edge.
|
||||
GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & 0xffff) | (GPIO_IRQ_FALLEDG * 0xaaaa)
|
||||
GPIO_GPIER (0) |= 0xff
|
||||
scanning = false
|
||||
|
||||
for unsigned i = 0; i < NUM_COLS; ++i:
|
||||
GPIO_GPPUR (GPIO_KBD_ROW_PORT) |= GPIO_KBD_ROW_MASK
|
||||
GPIO_GPDIR (GPIO_KBD_ROW_PORT) &= ~GPIO_KBD_ROW_MASK
|
||||
// Detect interrupts on falling edge.
|
||||
for unsigned i = 0; i < GPIO_KBD_NUM_ROWS; ++i:
|
||||
gpio_irq_fall (GPIO_KBD_ROW_PORT, i)
|
||||
// Initialize matrix.
|
||||
for unsigned i = 0; i < GPIO_KBD_NUM_COLS; ++i:
|
||||
keys[i] = 0xff
|
||||
// Perform initial scan to get real values into matrix and set up the rest.
|
||||
scan ()
|
||||
void scan ():
|
||||
// Set all columns to 0 when they become output.
|
||||
GPIO_GPDR (3) &= ~COL_MASK
|
||||
scanning = false
|
||||
int const cols[NUM_COLS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 29 }
|
||||
for unsigned col = 0; col < NUM_COLS; ++col:
|
||||
GPIO_GPDIR (3) = (GPIO_GPDIR (3) & ~COL_MASK) | (1 << cols[col])
|
||||
//udelay (100)
|
||||
unsigned data = GPIO_GPDR (0) & ROW_MASK
|
||||
// Generate events.
|
||||
for unsigned row = 0; row < 8; ++row:
|
||||
if (data ^ keys[col]) & (1 << row):
|
||||
unsigned code = (row << 8) | col
|
||||
if data & (1 << row):
|
||||
code |= 0x10000
|
||||
event (KEYBOARD_EVENT, code)
|
||||
keys[col] = data
|
||||
if data != ROW_MASK:
|
||||
scanning = true
|
||||
scanning = true
|
||||
if scanning:
|
||||
GPIO_GPDIR (3) &= ~COL_MASK
|
||||
else:
|
||||
GPIO_GPDIR (3) |= COL_MASK
|
||||
|
||||
class Touchpad:
|
||||
unsigned old_state
|
||||
public:
|
||||
void check_events ():
|
||||
unsigned state = GPIO_GPDR (0)
|
||||
if (state ^ old_state) & (1 << GPIO_TP_LEFT):
|
||||
if state & (1 << GPIO_TP_LEFT):
|
||||
gpio_irq_fall (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
|
||||
unsigned state = GPIO_GPDR (GPIO_TP_LEFT_PORT)
|
||||
if state & (1 << GPIO_TP_LEFT):
|
||||
gpio_irq_fall (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
|
||||
if (state ^ old_state) & (1 << GPIO_TP_LEFT):
|
||||
event (TOUCHPAD_EVENT, 0)
|
||||
else:
|
||||
gpio_irq_rise (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
|
||||
else:
|
||||
gpio_irq_rise (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
|
||||
if (state ^ old_state) & (1 << GPIO_TP_LEFT):
|
||||
event (TOUCHPAD_EVENT, 0x10000)
|
||||
if (state ^ old_state) & (1 << GPIO_TP_RIGHT):
|
||||
if state & (1 << GPIO_TP_RIGHT):
|
||||
gpio_irq_fall (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
|
||||
if state & (1 << GPIO_TP_RIGHT):
|
||||
gpio_irq_fall (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
|
||||
if (state ^ old_state) & (1 << GPIO_TP_RIGHT):
|
||||
event (TOUCHPAD_EVENT, 1)
|
||||
else:
|
||||
gpio_irq_rise (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
|
||||
else:
|
||||
gpio_irq_rise (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
|
||||
if (state ^ old_state) & (1 << GPIO_TP_RIGHT):
|
||||
event (TOUCHPAD_EVENT, 0x10001)
|
||||
old_state = state
|
||||
Touchpad ():
|
||||
@ -165,20 +179,13 @@ class Touchpad:
|
||||
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)
|
||||
// Set up interrupts.
|
||||
gpio_irq_rise (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
|
||||
gpio_irq_rise (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
|
||||
old_state = 0
|
||||
// See if they are already pressed. If so, the interrupt detection is changed.
|
||||
// See if they are already pressed. Also set up interrupts.
|
||||
check_events ()
|
||||
// Now enable the interrupts.
|
||||
GPIO_GPIER (0) |= (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT)
|
||||
|
||||
class Lockleds:
|
||||
// Note that num lock is in port 2. The others are in port 0.
|
||||
enum { NUM = 1 << 22 }
|
||||
enum { CAPS = 1 << 27 }
|
||||
enum { SCROLL = 1 << 9 }
|
||||
public:
|
||||
Lockleds ():
|
||||
gpio_as_output (GPIO_NUM_PORT, GPIO_NUM)
|
||||
@ -203,13 +210,11 @@ class Lockleds:
|
||||
|
||||
class Power:
|
||||
// Power out is in port 2, the rest in port 3.
|
||||
enum { PWR_OUT = 1 << 2 }
|
||||
enum { PWR_IN = 1 << 1 }
|
||||
enum { BATTERY = 1 << 29 }
|
||||
unsigned old_state
|
||||
bool was_present
|
||||
public:
|
||||
void poll ():
|
||||
#if 0
|
||||
// Switch off keyboard interrupts, because this may interfere with them.
|
||||
GPIO_GPIER (0) &= ~0xff
|
||||
GPIO_GPDIR (3) &= ~(PWR_IN | BATTERY)
|
||||
@ -237,16 +242,16 @@ class Power:
|
||||
GPIO_GPDIR (3) &= ~(PWR_IN | BATTERY)
|
||||
//udelay (100)
|
||||
GPIO_GPIER (3) |= 0xff
|
||||
#endif
|
||||
Power ():
|
||||
GPIO_GPDR (2) |= PWR_OUT
|
||||
GPIO_GPDIR (2) |= PWR_OUT
|
||||
was_present = true
|
||||
old_state = BATTERY
|
||||
//old_state = BATTERY
|
||||
poll ()
|
||||
void poweroff ():
|
||||
gpio_as_gpio (GPIO_PW_O_PORT, GPIO_PW_O)
|
||||
gpio_as_output (GPIO_PW_O_PORT, GPIO_PW_O)
|
||||
GPIO_GPDR (GPIO_PW_O) &= ~(1 << GPIO_PW_O)
|
||||
// TODO: doesn't work.
|
||||
i2c_open ()
|
||||
i2c_write_page (I2C_DEV_MCU, I2C_MCU_SHUTDOWN, "\1", 1)
|
||||
i2c_close ()
|
||||
while true:
|
||||
// Do nothing; wait until the device stops running.
|
||||
void reboot ():
|
||||
@ -257,29 +262,27 @@ class Power:
|
||||
|
||||
// Not really a gpio device, but it's so small, and uses gpio, so I include it here to avoid ipc.
|
||||
class Pwm:
|
||||
// Pin definitions, all in port 2.
|
||||
enum { PWM_ENABLE = 1 << 30 }
|
||||
public:
|
||||
Pwm ():
|
||||
GPIO_GPDIR (2) |= PWM_ENABLE
|
||||
GPIO_GPDIR (GPIO_PWM_ENABLE_PORT) |= 1 << GPIO_PWM_ENABLE
|
||||
PWM_PER (0) = 300
|
||||
void set_backlight (bool state):
|
||||
if state:
|
||||
PWM_DUT (0) = 300
|
||||
PWM_CTR (0) = 0xbf
|
||||
GPIO_GPDR (2) |= PWM_ENABLE
|
||||
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_DUT (0) = 0
|
||||
PWM_CTR (0) = 0x3f
|
||||
GPIO_GPDR (2) &= ~PWM_ENABLE
|
||||
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.
|
||||
|
||||
int main ():
|
||||
schedule ()
|
||||
|
||||
map_gpio ()
|
||||
map_pwm0 ()
|
||||
map_wdt ()
|
||||
map_i2c ()
|
||||
|
||||
Keyboard kbd
|
||||
Touchpad tp
|
||||
@ -287,6 +290,8 @@ int main ():
|
||||
Power power
|
||||
Pwm pwm
|
||||
|
||||
// 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
|
||||
register_interrupt (IRQ_GPIO0)
|
||||
|
||||
Capability cap_kbd = receiver_create_capability (__my_receiver, CAP_KEYBOARD)
|
||||
@ -302,25 +307,27 @@ int main ():
|
||||
|
||||
receiver_set_alarm (__my_receiver, ALARM_INTERVAL)
|
||||
while true:
|
||||
schedule ()
|
||||
Message msg
|
||||
wait (&msg)
|
||||
switch msg.protected_data:
|
||||
case ~0:
|
||||
// Alarm.
|
||||
if kbd.is_scanning ():
|
||||
kbd.scan ()
|
||||
//power.poll ()
|
||||
kdebug ("alarm\n")
|
||||
// Periodically scan several devices.
|
||||
kbd.scan ()
|
||||
power.poll ()
|
||||
receiver_set_alarm (__my_receiver, ALARM_INTERVAL)
|
||||
break
|
||||
case IRQ_GPIO0:
|
||||
kdebug ("gpio interrupt")
|
||||
unsigned irq = GPIO_GPFR (0)
|
||||
// Ack all. This works because they are all edge triggered.
|
||||
GPIO_GPFR (0) = irq
|
||||
if irq & 0xff:
|
||||
kbd.scan ()
|
||||
if irq & ((1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT)):
|
||||
tp.check_events ()
|
||||
kdebug ("gpio interrupt\n")
|
||||
//unsigned irq = GPIO_GPFR (0)
|
||||
// Ack all.
|
||||
GPIO_GPFR (0) = (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT) | GPIO_KBD_ROW_MASK
|
||||
// Always scan keyboard and touchpad on any interrupt.
|
||||
kbd.scan ()
|
||||
tp.check_events ()
|
||||
// Reregister the interrupt.
|
||||
register_interrupt (IRQ_GPIO0)
|
||||
break
|
||||
case CAP_KEYBOARD:
|
||||
|
@ -39,7 +39,7 @@ static void setup ():
|
||||
wait (&msg)
|
||||
switch msg.data[0]:
|
||||
case INIT_SET_GPIO_0:
|
||||
kdebug ("gpio 0")
|
||||
kdebug ("gpio 0\n")
|
||||
kbd = msg.cap[0]
|
||||
tp = msg.cap[1]
|
||||
poweroff = msg.cap[2]
|
||||
@ -47,14 +47,14 @@ static void setup ():
|
||||
++state
|
||||
break
|
||||
case INIT_SET_GPIO_1:
|
||||
kdebug ("gpio 1")
|
||||
kdebug ("gpio 1\n")
|
||||
battery = msg.cap[0]
|
||||
lockleds = msg.cap[1]
|
||||
pwm = msg.cap[2]
|
||||
++state
|
||||
break
|
||||
case INIT_SET_LCD:
|
||||
kdebug ("lcd")
|
||||
kdebug ("lcd\n")
|
||||
lcd = msg.cap[0]
|
||||
++state
|
||||
break
|
||||
@ -67,10 +67,11 @@ static void setup ():
|
||||
invoke_01 (pwm, 1)
|
||||
|
||||
int main ():
|
||||
// Set up lcd first
|
||||
schedule ()
|
||||
kdebug ("start init")
|
||||
kdebug ("start init\n")
|
||||
setup ()
|
||||
kdebug ("run init")
|
||||
kdebug ("run init\n")
|
||||
while true:
|
||||
Message msg
|
||||
wait (&msg)
|
||||
@ -81,9 +82,14 @@ int main ():
|
||||
kdebug_char ('\n')
|
||||
break
|
||||
case TP:
|
||||
if msg.data[0] == 0:
|
||||
// Press left button.
|
||||
invoke_00 (poweroff)
|
||||
unsigned leds = 0
|
||||
if msg.data[0] & 1:
|
||||
leds |= 0x1
|
||||
else:
|
||||
leds |= 0x4
|
||||
if !(msg.data[0] & 0x10000):
|
||||
leds |= 0x2
|
||||
invoke_01 (lockleds, leds)
|
||||
break
|
||||
case POWERBUTTON:
|
||||
kdebug ("powerbutton event\n")
|
||||
|
17
iris.h
17
iris.h
@ -30,7 +30,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
// Number of clock interrupts per second.
|
||||
#define HZ 10
|
||||
#define HZ 20
|
||||
|
||||
#define PAGE_BITS (12)
|
||||
#define PAGE_SIZE (1 << PAGE_BITS)
|
||||
@ -441,6 +441,20 @@ static void invoke_41 (Capability t, Capability c0, Capability c1, Capability c2
|
||||
invoke (t, &msg);
|
||||
}
|
||||
|
||||
static void call_00 (Capability c)
|
||||
{
|
||||
Message msg;
|
||||
msg.cap[0] = c;
|
||||
msg.data[0] = 0;
|
||||
msg.data[1] = 0;
|
||||
msg.data[2] = 0;
|
||||
msg.data[3] = 0;
|
||||
msg.cap[1] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
call (__my_call, &msg);
|
||||
}
|
||||
|
||||
static Capability call_c01 (Capability c, unsigned d)
|
||||
{
|
||||
Message msg;
|
||||
@ -760,7 +774,6 @@ static unsigned memory_limit (Capability memory, unsigned limit)
|
||||
|
||||
static void drop (Capability cap)
|
||||
{
|
||||
return;
|
||||
invoke_11 (__my_memory, cap, CAP_MEMORY_DROP);
|
||||
}
|
||||
|
||||
|
@ -1399,8 +1399,15 @@ static void __map_io (unsigned physical, unsigned mapping):
|
||||
#define I2C_SR_DRF (1 << 1)
|
||||
#define I2C_SR_ACKF (1 << 0)
|
||||
|
||||
#define I2C_WRITE 0
|
||||
#define I2C_READ 1
|
||||
|
||||
|
||||
/* I2C devices */
|
||||
#define I2C_DEV_MCU 0x48
|
||||
/* I2C device registers */
|
||||
#define I2C_MCU_SHUTDOWN 0xd8
|
||||
#define I2C_MCU_BAT_STATUS 0xdb
|
||||
#define I2C_MCU_BAT_CHARGE 0xd9
|
||||
|
||||
/*************************************************************************
|
||||
* UDC usb device controller (unused in trendtac)
|
||||
@ -2821,8 +2828,8 @@ static __inline__ unsigned msc_calc_slow_clk_divisor (bool is_sd):
|
||||
|
||||
#define GPIO_PW_I_PORT 3
|
||||
#define GPIO_PW_I 1
|
||||
#define GPIO_PW_O_PORT 2
|
||||
#define GPIO_PW_O 2
|
||||
#define GPIO_MCU_PORT 2
|
||||
#define GPIO_MCU 1
|
||||
#define GPIO_LED_EN_PORT 2
|
||||
#define GPIO_LED_EN 28
|
||||
#define GPIO_DISP_OFF_N_PORT 2
|
||||
@ -2847,6 +2854,15 @@ static __inline__ unsigned msc_calc_slow_clk_divisor (bool is_sd):
|
||||
#define GPIO_TP_LEFT 16
|
||||
#define GPIO_TP_RIGHT_PORT 0
|
||||
#define GPIO_TP_RIGHT 13
|
||||
#define GPIO_PWM_ENABLE_PORT 2
|
||||
#define GPIO_PWM_ENABLE 30
|
||||
#define GPIO_KBD_NUM_ROWS 8
|
||||
#define GPIO_KBD_NUM_COLS 17
|
||||
#define GPIO_KBD_COL_PORT 3
|
||||
#define GPIO_KBD_COL_MASK 0x2000ffff
|
||||
#define GPIO_KBD_ROW_PORT 0
|
||||
#define GPIO_KBD_ROW_MASK 0x000000ff
|
||||
#define GPIO_KBD_ROW_HALF 0x00005555
|
||||
|
||||
#define GPIO_HALF(x) (((x) & 0xf) << 1)
|
||||
|
||||
@ -3012,6 +3028,48 @@ static __inline__ void gpio_as_cim ():
|
||||
#define i2c_read() ( I2C_DR )
|
||||
#define i2c_write(val) ( I2C_DR = (val) )
|
||||
|
||||
#ifndef __KERNEL
|
||||
static __inline__ void i2c_open ():
|
||||
i2c_set_clk (JZ_EXTAL, 10000)
|
||||
i2c_enable ()
|
||||
|
||||
// Note that this kills messages from the queue.
|
||||
static __inline__ void i2c_close ():
|
||||
Message msg
|
||||
receiver_set_alarm (__my_receiver, 3 * HZ / 10)
|
||||
call_00 (0)
|
||||
i2c_disable ()
|
||||
|
||||
static __inline__ bool i2c_send (unsigned data):
|
||||
unsigned timeout = 10000
|
||||
i2c_write (data)
|
||||
i2c_set_drf ()
|
||||
while i2c_check_drf () != 0:
|
||||
while !i2c_transmit_ended ():
|
||||
while !i2c_received_ack ():
|
||||
if !--timeout:
|
||||
return false
|
||||
return true
|
||||
|
||||
static __inline__ unsigned i2c_write_page (unsigned dev, unsigned addr, char const *data, unsigned count):
|
||||
unsigned timeout = 5
|
||||
i2c_send_start ()
|
||||
if !i2c_send ((dev << 1) | I2C_WRITE):
|
||||
i2c_send_stop ()
|
||||
return 0
|
||||
if !i2c_send (addr):
|
||||
i2c_send_stop ()
|
||||
return 0
|
||||
if count > 8:
|
||||
count = 8
|
||||
unsigned i
|
||||
for i = 0; i < count; ++i:
|
||||
if !i2c_send (*data++):
|
||||
break
|
||||
i2c_send_stop ()
|
||||
return i
|
||||
#endif
|
||||
|
||||
/***************************************************************************
|
||||
* UDC
|
||||
***************************************************************************/
|
||||
|
Loading…
Reference in New Issue
Block a user