@@ -16,13 +16,15 @@ LDSCRIPT= sample.ld.gd32vf103
|
|||||||
### LDSCRIPT= sample.ld.m4
|
### LDSCRIPT= sample.ld.m4
|
||||||
### LDSCRIPT= sample.ld
|
### LDSCRIPT= sample.ld
|
||||||
### LDSCRIPT= sample.ld.m3
|
### LDSCRIPT= sample.ld.m3
|
||||||
CSRC = sample.c
|
CSRC = sample.c usb-vendor-specific.c
|
||||||
|
# CSRC += debug.c
|
||||||
|
|
||||||
ARCH=riscv32
|
ARCH=riscv32
|
||||||
CHIP=gd32vf103
|
CHIP=gd32vf103
|
||||||
### CHIP=stm32l4
|
### CHIP=stm32l4
|
||||||
### USE_SYS = yes
|
### USE_SYS = yes
|
||||||
USE_USART = yes
|
USE_USART = yes
|
||||||
|
USE_USB = yes
|
||||||
|
|
||||||
###################################
|
###################################
|
||||||
### CROSS = arm-none-eabi-
|
### CROSS = arm-none-eabi-
|
||||||
@@ -40,6 +42,7 @@ DEFS = -DFREE_STANDING -DMHZ=96
|
|||||||
### DEFS = -DFREE_STANDING -DUSE_SYS3 -DBUSY_LOOP -DCHX_FLAGS_MAIN=CHOPSTX_SCHED_RR
|
### DEFS = -DFREE_STANDING -DUSE_SYS3 -DBUSY_LOOP -DCHX_FLAGS_MAIN=CHOPSTX_SCHED_RR
|
||||||
OPT = -O3 -Os -g
|
OPT = -O3 -Os -g
|
||||||
LIBS =
|
LIBS =
|
||||||
|
#LIBS = -lgcc
|
||||||
|
|
||||||
CSRC += $(CHOPSTX)/contrib/spi-st.c
|
CSRC += $(CHOPSTX)/contrib/spi-st.c
|
||||||
|
|
||||||
|
|||||||
34
example-lcd/bouncing_gpg.py
Normal file
34
example-lcd/bouncing_gpg.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
from load_image_to_screen import Longan_LCD
|
||||||
|
|
||||||
|
from gnupg_logo_16bit_160x80 import gnupg_logo_16bit_160x80
|
||||||
|
|
||||||
|
image = gnupg_logo_16bit_160x80
|
||||||
|
|
||||||
|
pos = [ 1, 2, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9, 12, 14, 17, 20, 23, 28, 33, 40, 47, 56 ]
|
||||||
|
|
||||||
|
background0 = [ 0x5d, 0xdf ]
|
||||||
|
background1 = [ 0x7e, 0xdf ]
|
||||||
|
|
||||||
|
def fill(i, bg0, bg1):
|
||||||
|
if (i % 2) == 0:
|
||||||
|
return bg0
|
||||||
|
else:
|
||||||
|
return bg1
|
||||||
|
|
||||||
|
def move_right(x, bg0, bg1, img):
|
||||||
|
result = []
|
||||||
|
for i in range(80):
|
||||||
|
for j in range(x):
|
||||||
|
result = result + fill(j, bg0, bg1)
|
||||||
|
result = result + (img[i*160*2:(i+1)*160*2])[0:160*2-x*2]
|
||||||
|
return result
|
||||||
|
|
||||||
|
images = [ bytes(move_right(x, background0, background1, image)) for x in pos ]
|
||||||
|
|
||||||
|
lcd = Longan_LCD()
|
||||||
|
|
||||||
|
for loop in range(10):
|
||||||
|
for i in range(len(pos)):
|
||||||
|
lcd.load_image_to_screen(images[len(pos)-1-i])
|
||||||
|
for i in range(len(pos)):
|
||||||
|
lcd.load_image_to_screen(images[i])
|
||||||
26
example-lcd/debug.c
Normal file
26
example-lcd/debug.c
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <chopstx.h>
|
||||||
|
#include <contrib/usart.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
extern int vsnprintf(char *str, size_t size, const char *format, va_list ap);
|
||||||
|
|
||||||
|
#define USART_NO 0
|
||||||
|
|
||||||
|
/* Intentionally only adding LF */
|
||||||
|
void
|
||||||
|
debug (const char *fmt, ...)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
va_list ap;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
len = vsnprintf (buf, sizeof buf - 1, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
if (len >= sizeof buf - 1)
|
||||||
|
len = sizeof buf - 2;
|
||||||
|
buf[len++] = '\n';
|
||||||
|
usart_write (USART_NO, buf, len);
|
||||||
|
}
|
||||||
1
example-lcd/debug.h
Normal file
1
example-lcd/debug.h
Normal file
@@ -0,0 +1 @@
|
|||||||
|
void debug (const char *fmt, ...);
|
||||||
1602
example-lcd/gnupg_logo_16bit_160x80.py
Normal file
1602
example-lcd/gnupg_logo_16bit_160x80.py
Normal file
File diff suppressed because it is too large
Load Diff
96
example-lcd/l.py
Normal file
96
example-lcd/l.py
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#! /usr/bin/python3
|
||||||
|
|
||||||
|
# pos = [
|
||||||
|
# 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
# 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
|
||||||
|
# 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 9, 9, 10, 11,
|
||||||
|
# 12, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 28, 30, 31, 33, 35,
|
||||||
|
# 37, 40, 42, 44, 47, 50, 53, 56, 59, 63, 66, 70, 75, 79, 84, 89, 94,100,105,112,
|
||||||
|
# 118,125,133,141,149,158
|
||||||
|
# ]
|
||||||
|
|
||||||
|
pos = [
|
||||||
|
0, 1, 1, 1,
|
||||||
|
1, 2, 2, 3,
|
||||||
|
4, 6, 8, 11,
|
||||||
|
15, 20, 26, 35,
|
||||||
|
47, 63, 84, 112,
|
||||||
|
149
|
||||||
|
]
|
||||||
|
|
||||||
|
import usb.core
|
||||||
|
import usb.util
|
||||||
|
|
||||||
|
dev = usb.core.find(idVendor=0xffff, idProduct=0x0001)
|
||||||
|
|
||||||
|
if dev is None:
|
||||||
|
raise ValueError('Device not found')
|
||||||
|
|
||||||
|
# dev.set_configuration()
|
||||||
|
|
||||||
|
# get an endpoint instance
|
||||||
|
cfg = dev.get_active_configuration()
|
||||||
|
intf = cfg[(0,0)]
|
||||||
|
|
||||||
|
ep_out = usb.util.find_descriptor(
|
||||||
|
intf,
|
||||||
|
# match the first OUT endpoint
|
||||||
|
custom_match = \
|
||||||
|
lambda e: \
|
||||||
|
usb.util.endpoint_direction(e.bEndpointAddress) == \
|
||||||
|
usb.util.ENDPOINT_OUT)
|
||||||
|
|
||||||
|
ep_in = usb.util.find_descriptor(
|
||||||
|
intf,
|
||||||
|
# match the first IN endpoint
|
||||||
|
custom_match = \
|
||||||
|
lambda e: \
|
||||||
|
usb.util.endpoint_direction(e.bEndpointAddress) == \
|
||||||
|
usb.util.ENDPOINT_IN)
|
||||||
|
|
||||||
|
if ep_out is None:
|
||||||
|
raise ValueError('Endpoint to send data not found')
|
||||||
|
|
||||||
|
if ep_in is None:
|
||||||
|
raise ValueError('Endpoint to receive data not found')
|
||||||
|
|
||||||
|
color_black = [ 0, 0 ]
|
||||||
|
color0 = [ 0xff, 0x03 ]
|
||||||
|
color1 = [ 0xef, 0x7f ]
|
||||||
|
color2 = [ 0x00, 0x78 ]
|
||||||
|
color3 = [ 0xff, 0xff ]
|
||||||
|
|
||||||
|
def gen_image(x):
|
||||||
|
image = []
|
||||||
|
for i in range(80):
|
||||||
|
image = image + (color_black * x) + (color0 * (160-x))
|
||||||
|
return image
|
||||||
|
|
||||||
|
images = [ gen_image(p) for p in pos ]
|
||||||
|
# images = [ gen_image(p) for p in range(160) ]
|
||||||
|
|
||||||
|
import time
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def prepare_send():
|
||||||
|
w=ep_in.read(64)
|
||||||
|
# print(w)
|
||||||
|
|
||||||
|
def finish_send():
|
||||||
|
dev.ctrl_transfer(0x41, 0x00, 0x00, 0x00, "")
|
||||||
|
# print(".", end='', flush=True)
|
||||||
|
|
||||||
|
for i in range(len(images)*8):
|
||||||
|
i0 = i % (len(images)*2)
|
||||||
|
if i0 < len(images):
|
||||||
|
x = (i % len(images))
|
||||||
|
else:
|
||||||
|
x = len(images)- 1 - (i % len(images))
|
||||||
|
# print("%d %d: %d" % (i, x, len(images[x])))
|
||||||
|
if True:
|
||||||
|
prepare_send()
|
||||||
|
ep_out.write(images[x])
|
||||||
|
finish_send()
|
||||||
|
|
||||||
|
prepare_send()
|
||||||
|
dev.ctrl_transfer(0x41, 0x00, 0x01, 0x00, "")
|
||||||
51
example-lcd/load_image_to_screen.py
Normal file
51
example-lcd/load_image_to_screen.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#! /usr/bin/python3
|
||||||
|
|
||||||
|
import usb.core
|
||||||
|
import usb.util
|
||||||
|
import time
|
||||||
|
import sys
|
||||||
|
|
||||||
|
class Longan_LCD(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.dev = usb.core.find(idVendor=0xffff, idProduct=0x0001)
|
||||||
|
|
||||||
|
if self.dev is None:
|
||||||
|
raise ValueError('Device not found')
|
||||||
|
|
||||||
|
cfg = self.dev.get_active_configuration()
|
||||||
|
intf = cfg[(0,0)]
|
||||||
|
|
||||||
|
self.ep_out = usb.util.find_descriptor(
|
||||||
|
intf,
|
||||||
|
# match the first OUT endpoint
|
||||||
|
custom_match = \
|
||||||
|
lambda e: \
|
||||||
|
usb.util.endpoint_direction(e.bEndpointAddress) == \
|
||||||
|
usb.util.ENDPOINT_OUT)
|
||||||
|
|
||||||
|
self.ep_in = usb.util.find_descriptor(
|
||||||
|
intf,
|
||||||
|
# match the first IN endpoint
|
||||||
|
custom_match = \
|
||||||
|
lambda e: \
|
||||||
|
usb.util.endpoint_direction(e.bEndpointAddress) == \
|
||||||
|
usb.util.ENDPOINT_IN)
|
||||||
|
|
||||||
|
if self.ep_out is None:
|
||||||
|
raise ValueError('Endpoint to send data not found')
|
||||||
|
|
||||||
|
if self.ep_in is None:
|
||||||
|
raise ValueError('Endpoint to receive data not found')
|
||||||
|
|
||||||
|
def prepare_send(self):
|
||||||
|
w=self.ep_in.read(64)
|
||||||
|
# print(w)
|
||||||
|
|
||||||
|
def finish_send(self):
|
||||||
|
self.dev.ctrl_transfer(0x41, 0x00, 0x00, 0x00, "")
|
||||||
|
# print(".", end='', flush=True)
|
||||||
|
|
||||||
|
def load_image_to_screen(self, image):
|
||||||
|
self.prepare_send()
|
||||||
|
self.ep_out.write(image)
|
||||||
|
self.finish_send()
|
||||||
93
example-lcd/longan_usb_load_image.py
Executable file
93
example-lcd/longan_usb_load_image.py
Executable file
@@ -0,0 +1,93 @@
|
|||||||
|
#! /usr/bin/python3
|
||||||
|
|
||||||
|
import usb.core
|
||||||
|
import usb.util
|
||||||
|
|
||||||
|
dev = usb.core.find(idVendor=0xffff, idProduct=0x0001)
|
||||||
|
|
||||||
|
if dev is None:
|
||||||
|
raise ValueError('Device not found')
|
||||||
|
|
||||||
|
# dev.set_configuration()
|
||||||
|
|
||||||
|
# get an endpoint instance
|
||||||
|
cfg = dev.get_active_configuration()
|
||||||
|
intf = cfg[(0,0)]
|
||||||
|
|
||||||
|
ep_out = usb.util.find_descriptor(
|
||||||
|
intf,
|
||||||
|
# match the first OUT endpoint
|
||||||
|
custom_match = \
|
||||||
|
lambda e: \
|
||||||
|
usb.util.endpoint_direction(e.bEndpointAddress) == \
|
||||||
|
usb.util.ENDPOINT_OUT)
|
||||||
|
|
||||||
|
ep_in = usb.util.find_descriptor(
|
||||||
|
intf,
|
||||||
|
# match the first IN endpoint
|
||||||
|
custom_match = \
|
||||||
|
lambda e: \
|
||||||
|
usb.util.endpoint_direction(e.bEndpointAddress) == \
|
||||||
|
usb.util.ENDPOINT_IN)
|
||||||
|
|
||||||
|
if ep_out is None:
|
||||||
|
raise ValueError('Endpoint to send data not found')
|
||||||
|
|
||||||
|
if ep_in is None:
|
||||||
|
raise ValueError('Endpoint to receive data not found')
|
||||||
|
|
||||||
|
def prepare_send():
|
||||||
|
w=ep_in.read(64)
|
||||||
|
# print(w)
|
||||||
|
|
||||||
|
def finish_send():
|
||||||
|
dev.ctrl_transfer(0x41, 0x00, 0x00, 0x00, "")
|
||||||
|
# print(".", end='', flush=True)
|
||||||
|
|
||||||
|
|
||||||
|
color0 = [ 0xff, 0x03 ]
|
||||||
|
color1 = [ 0xef, 0x7f ]
|
||||||
|
color2 = [ 0x00, 0x78 ]
|
||||||
|
color3 = [ 0xff, 0xff ]
|
||||||
|
|
||||||
|
image = color0*160*80
|
||||||
|
# + color1*160*40
|
||||||
|
image64 = color0*32
|
||||||
|
image = color1*160*80
|
||||||
|
point1600a=(color0*40+color1*40)*20
|
||||||
|
point1600b=(color1*40+color0*40)*20
|
||||||
|
|
||||||
|
point1600c=(color2*20+color3*20)*40
|
||||||
|
point1600d=(color3*20+color2*20)*40
|
||||||
|
|
||||||
|
import time
|
||||||
|
import sys
|
||||||
|
|
||||||
|
for i in range(10):
|
||||||
|
prepare_send()
|
||||||
|
|
||||||
|
ep_out.write(point1600a)
|
||||||
|
print(".", end='', flush=True)
|
||||||
|
ep_out.write(point1600b)
|
||||||
|
print(".", end='', flush=True)
|
||||||
|
ep_out.write(point1600a)
|
||||||
|
print(".", end='', flush=True)
|
||||||
|
ep_out.write(point1600b)
|
||||||
|
print(".", end='', flush=True)
|
||||||
|
ep_out.write(point1600a)
|
||||||
|
print(".", end='', flush=True)
|
||||||
|
ep_out.write(point1600b)
|
||||||
|
print(".", end='', flush=True)
|
||||||
|
ep_out.write(point1600a)
|
||||||
|
print(".", end='', flush=True)
|
||||||
|
ep_out.write(point1600b)
|
||||||
|
print(".")
|
||||||
|
finish_send()
|
||||||
|
|
||||||
|
prepare_send()
|
||||||
|
ep_out.write(point1600c*2+point1600d*2+point1600c*2+point1600d*2)
|
||||||
|
print(".")
|
||||||
|
finish_send()
|
||||||
|
|
||||||
|
prepare_send()
|
||||||
|
dev.ctrl_transfer(0x41, 0x00, 0x01, 0x00, "")
|
||||||
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include <mcu/gd32vf103.h>
|
#include <mcu/gd32vf103.h>
|
||||||
|
|
||||||
|
#include "vrsp.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
set_led_b (void)
|
set_led_b (void)
|
||||||
{
|
{
|
||||||
@@ -33,91 +35,13 @@ set_led (int on)
|
|||||||
GPIOC->ODR |= (1 << 13);
|
GPIOC->ODR |= (1 << 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
static chopstx_mutex_t mtx;
|
|
||||||
static chopstx_cond_t cnd0;
|
|
||||||
static chopstx_cond_t cnd1;
|
|
||||||
|
|
||||||
static uint8_t u, v;
|
|
||||||
static uint8_t m; /* 0..100 */
|
|
||||||
|
|
||||||
static void
|
|
||||||
wait_for (uint32_t usec)
|
|
||||||
{
|
|
||||||
#if defined(BUSY_LOOP)
|
|
||||||
uint32_t count = usec * 6;
|
|
||||||
uint32_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
asm volatile ("" : : "r" (i) : "memory");
|
|
||||||
#else
|
|
||||||
chopstx_usec_wait (usec);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
|
||||||
pwm (void *arg)
|
|
||||||
{
|
|
||||||
(void)arg;
|
|
||||||
|
|
||||||
chopstx_mutex_lock (&mtx);
|
|
||||||
chopstx_cond_wait (&cnd0, &mtx);
|
|
||||||
chopstx_mutex_unlock (&mtx);
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
set_led (u&v);
|
|
||||||
wait_for (m);
|
|
||||||
set_led (0);
|
|
||||||
wait_for (100-m);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
|
||||||
blk (void *arg)
|
|
||||||
{
|
|
||||||
(void)arg;
|
|
||||||
|
|
||||||
chopstx_mutex_lock (&mtx);
|
|
||||||
chopstx_cond_wait (&cnd1, &mtx);
|
|
||||||
chopstx_mutex_unlock (&mtx);
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
v = 0;
|
|
||||||
wait_for (200*1000);
|
|
||||||
v = 1;
|
|
||||||
wait_for (200*1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(BUSY_LOOP)
|
|
||||||
#define PRIO_PWM (CHOPSTX_SCHED_RR|1)
|
|
||||||
#define PRIO_BLK (CHOPSTX_SCHED_RR|1)
|
|
||||||
#else
|
|
||||||
#define PRIO_PWM 3
|
|
||||||
#define PRIO_BLK 2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define STACK_MAIN
|
#define STACK_MAIN
|
||||||
#define STACK_PROCESS_1
|
#define STACK_PROCESS_1
|
||||||
#define STACK_PROCESS_2
|
|
||||||
#define STACK_PROCESS_3
|
|
||||||
#include "stack-def.h"
|
#include "stack-def.h"
|
||||||
|
|
||||||
|
#define PRIO_USART 3
|
||||||
#define STACK_ADDR_PWM ((uint32_t)process1_base)
|
#define STACK_ADDR_USART ((uint32_t)process1_base)
|
||||||
#define STACK_SIZE_PWM (sizeof process1_base)
|
#define STACK_SIZE_USART (sizeof process1_base)
|
||||||
|
|
||||||
#define STACK_ADDR_BLK ((uint32_t)process2_base)
|
|
||||||
#define STACK_SIZE_BLK (sizeof process2_base)
|
|
||||||
|
|
||||||
#define PRIO_USART 4
|
|
||||||
#define STACK_ADDR_USART ((uint32_t)process3_base)
|
|
||||||
#define STACK_SIZE_USART (sizeof process3_base)
|
|
||||||
|
|
||||||
#define LCD_WIDTH 160
|
#define LCD_WIDTH 160
|
||||||
#define LCD_HEIGHT 80
|
#define LCD_HEIGHT 80
|
||||||
@@ -168,10 +92,8 @@ lcd_control (int control)
|
|||||||
static void
|
static void
|
||||||
lcd_send (uint8_t data)
|
lcd_send (uint8_t data)
|
||||||
{
|
{
|
||||||
lcd_chip_select (1);
|
|
||||||
spi_send (data);
|
spi_send (data);
|
||||||
spi_recv ();
|
spi_recv ();
|
||||||
lcd_chip_select (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -206,13 +128,14 @@ lcd_init (void)
|
|||||||
lcd_reset (1);
|
lcd_reset (1);
|
||||||
chopstx_usec_wait (500*1000);
|
chopstx_usec_wait (500*1000);
|
||||||
lcd_reset (0);
|
lcd_reset (0);
|
||||||
chopstx_usec_wait (50*1000);
|
lcd_chip_select (1);
|
||||||
|
chopstx_usec_wait (100*1000);
|
||||||
|
|
||||||
lcd_command (0x11); /* SLPOUT: Sleep out */
|
lcd_command (0x11); /* SLPOUT: Sleep out */
|
||||||
chopstx_usec_wait (100*1000);
|
chopstx_usec_wait (100*1000);
|
||||||
|
|
||||||
lcd_command (0x21); /* INVON: display inversion on */
|
lcd_command (0x21); /* INVON: display inversion on */
|
||||||
/* INVOFF: display inversion off: 0x20 */
|
/* INVOFF: display inversion off: 0x20 */
|
||||||
|
|
||||||
lcd_command (0x3a); /* COLMOD: Pixel data format */
|
lcd_command (0x3a); /* COLMOD: Pixel data format */
|
||||||
lcd_data8 (0x05); /* 16-bit/pixel */
|
lcd_data8 (0x05); /* 16-bit/pixel */
|
||||||
@@ -356,72 +279,93 @@ ss_notify (uint8_t dev_no, uint16_t state_bits)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "fsij-logo.c"
|
uint16_t screen_image[12800];
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, const char *argv[])
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
chopstx_poll_cond_t poll_desc;
|
chopstx_poll_cond_t usart_poll_desc;
|
||||||
struct chx_poll_head *ph[1];
|
chopstx_poll_cond_t usb_poll_desc;
|
||||||
|
struct chx_poll_head *ph[2];
|
||||||
uint32_t timeout;
|
uint32_t timeout;
|
||||||
int cl = 0;
|
int cl = 0;
|
||||||
|
int play_mode = 0;
|
||||||
|
struct vrsp *v;
|
||||||
|
uint32_t u = 0;
|
||||||
|
|
||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
||||||
set_led (1);
|
|
||||||
|
|
||||||
chopstx_mutex_init (&mtx);
|
|
||||||
chopstx_cond_init (&cnd0);
|
|
||||||
chopstx_cond_init (&cnd1);
|
|
||||||
|
|
||||||
m = 10;
|
|
||||||
|
|
||||||
chopstx_create (PRIO_PWM, STACK_ADDR_PWM, STACK_SIZE_PWM, pwm, NULL);
|
|
||||||
chopstx_create (PRIO_BLK, STACK_ADDR_BLK, STACK_SIZE_BLK, blk, NULL);
|
|
||||||
|
|
||||||
chopstx_usec_wait (200*1000);
|
|
||||||
|
|
||||||
chopstx_mutex_lock (&mtx);
|
|
||||||
chopstx_cond_signal (&cnd0);
|
|
||||||
chopstx_cond_signal (&cnd1);
|
|
||||||
chopstx_mutex_unlock (&mtx);
|
|
||||||
|
|
||||||
lcd_init ();
|
|
||||||
|
|
||||||
usart_init (PRIO_USART, STACK_ADDR_USART, STACK_SIZE_USART, ss_notify);
|
usart_init (PRIO_USART, STACK_ADDR_USART, STACK_SIZE_USART, ss_notify);
|
||||||
usart_config (0, B115200 | CS8 | STOP1B);
|
usart_config (0, B115200 | CS8 | STOP1B);
|
||||||
|
|
||||||
usart_read_prepare_poll (0, &poll_desc);
|
v = vrsp_open ();
|
||||||
ph[0] = (struct chx_poll_head *)&poll_desc;
|
|
||||||
|
chopstx_usec_wait (500*1000);
|
||||||
|
set_led (1);
|
||||||
|
|
||||||
|
lcd_init ();
|
||||||
|
lcd_clear (colors[26]);
|
||||||
|
|
||||||
|
chopstx_usec_wait (500*1000);
|
||||||
|
|
||||||
|
vrsp_prepare_poll (v, &usb_poll_desc);
|
||||||
|
ph[0] = (struct chx_poll_head *)&usb_poll_desc;
|
||||||
|
|
||||||
|
usart_read_prepare_poll (0, &usart_poll_desc);
|
||||||
|
ph[1] = (struct chx_poll_head *)&usart_poll_desc;
|
||||||
|
|
||||||
timeout = 200*1000*6;
|
timeout = 200*1000*6;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
chopstx_poll (&timeout, 1, ph);
|
chopstx_poll (&timeout, 2, ph);
|
||||||
|
|
||||||
|
if (usart_poll_desc.ready)
|
||||||
|
{
|
||||||
|
char buf[16];
|
||||||
|
int r;
|
||||||
|
r = usart_read (0, buf, 16);
|
||||||
|
if (r)
|
||||||
|
usart_write (0, buf, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usb_poll_desc.ready)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = vrsp_screen_acquire (v);
|
||||||
|
if (r < 0)
|
||||||
|
/* It's busy. */
|
||||||
|
;
|
||||||
|
else if (r == 0)
|
||||||
|
{
|
||||||
|
play_mode = 1;
|
||||||
|
lcd_load_image (screen_image);
|
||||||
|
vrsp_screen_release (v);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
play_mode = 0;
|
||||||
|
vrsp_screen_release (v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (timeout == 0)
|
if (timeout == 0)
|
||||||
{
|
{
|
||||||
usart_write (0, "Hello\r\n", 7);
|
usart_write (0, "Hello\r\n", 7);
|
||||||
u ^= 1;
|
|
||||||
timeout = 200*1000*6;
|
timeout = 200*1000*6;
|
||||||
|
|
||||||
lcd_clear (colors[cl]);
|
u ^= 1;
|
||||||
|
set_led (u);
|
||||||
|
|
||||||
chopstx_usec_wait (1000*1000);
|
if (play_mode == 0)
|
||||||
lcd_load_image (fsij_logo);
|
{
|
||||||
chopstx_usec_wait (1000*1000);
|
lcd_clear (colors[cl]);
|
||||||
|
|
||||||
cl++;
|
cl++;
|
||||||
if (cl >= 27)
|
if (cl >= 27)
|
||||||
cl = 0;
|
cl = 0;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
char buf[256];
|
|
||||||
int r;
|
|
||||||
r = usart_read (0, buf, 256);
|
|
||||||
if (r)
|
|
||||||
usart_write (0, buf, r);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ SECTIONS
|
|||||||
*(.process_stack.1)
|
*(.process_stack.1)
|
||||||
*(.process_stack.2)
|
*(.process_stack.2)
|
||||||
*(.process_stack.3)
|
*(.process_stack.3)
|
||||||
|
*(.process_stack.4)
|
||||||
. = ALIGN(8);
|
. = ALIGN(8);
|
||||||
} > ram
|
} > ram
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
#define MAIN_SIZE 0x0100 /* Idle+Exception handlers */
|
#define MAIN_SIZE 0x0100 /* Idle+Exception handlers */
|
||||||
#define SIZE_0 0x0400 /* Main program */
|
#define SIZE_0 0x0600 /* Main program */
|
||||||
#define SIZE_1 0x0200 /* first thread program */
|
#define SIZE_1 0x0c00 /* first thread program */
|
||||||
#define SIZE_2 0x0200 /* second thread program */
|
#define SIZE_2 0x0600 /* second thread program */
|
||||||
#define SIZE_3 0x0600 /* second thread program */
|
#define SIZE_3 0x0000 /* third thread program */
|
||||||
|
#define SIZE_4 0x0000 /* fourth thread program */
|
||||||
|
|
||||||
#if defined(STACK_MAIN)
|
#if defined(STACK_MAIN)
|
||||||
/*
|
/*
|
||||||
|
|||||||
585
example-lcd/usb-vendor-specific.c
Normal file
585
example-lcd/usb-vendor-specific.c
Normal file
@@ -0,0 +1,585 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <chopstx.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "board.h"
|
||||||
|
#include "usb_lld.h"
|
||||||
|
#include "vrsp.h"
|
||||||
|
|
||||||
|
extern uint16_t screen_image[12800];
|
||||||
|
|
||||||
|
static chopstx_intr_t usb_intr;
|
||||||
|
|
||||||
|
struct vrsp {
|
||||||
|
struct usb_dev dev;
|
||||||
|
chopstx_mutex_t mtx;
|
||||||
|
chopstx_cond_t cnd;
|
||||||
|
uint32_t device_state : 3; /* USB device status */
|
||||||
|
uint32_t screen_mem_owner : 1; /* 0: driver, 1: app */
|
||||||
|
uint32_t mode : 8;
|
||||||
|
uint16_t *screen_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct vrsp vrsp0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Locate VRSP structure from interface number or endpoint number.
|
||||||
|
* Currently, it always returns vrsp0, because we only have the one.
|
||||||
|
*/
|
||||||
|
static struct vrsp *
|
||||||
|
vrsp_get (int interface, uint8_t ep_num)
|
||||||
|
{
|
||||||
|
struct vrsp *v = &vrsp0;
|
||||||
|
|
||||||
|
(void)interface;
|
||||||
|
(void)ep_num;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vrsp_update_finish (struct vrsp *v, int value);
|
||||||
|
|
||||||
|
/* USB Device Descriptor */
|
||||||
|
static const uint8_t vrsp_device_desc[18] = {
|
||||||
|
18, /* bLength */
|
||||||
|
DEVICE_DESCRIPTOR, /* bDescriptorType */
|
||||||
|
0x10, 0x01, /* bcdUSB = 1.1 */
|
||||||
|
0x00, /* bDeviceClass. */
|
||||||
|
0x00, /* bDeviceSubClass. */
|
||||||
|
0x00, /* bDeviceProtocol. */
|
||||||
|
0x40, /* bMaxPacketSize. */
|
||||||
|
0xFF, 0xFF, /* idVendor */
|
||||||
|
0x01, 0x00, /* idProduct */
|
||||||
|
0x00, 0x01, /* bcdDevice */
|
||||||
|
1, /* iManufacturer. */
|
||||||
|
2, /* iProduct. */
|
||||||
|
3, /* iSerialNumber. */
|
||||||
|
1 /* bNumConfigurations. */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FEATURE_BUS_POWERED 0x80
|
||||||
|
|
||||||
|
/* Configuration Descriptor */
|
||||||
|
static const uint8_t vrsp_config_desc[32] = {
|
||||||
|
9,
|
||||||
|
CONFIG_DESCRIPTOR, /* bDescriptorType: Configuration */
|
||||||
|
/* Configuration Descriptor.*/
|
||||||
|
32, 0x00, /* wTotalLength. */
|
||||||
|
0x01, /* bNumInterfaces. */
|
||||||
|
0x01, /* bConfigurationValue. */
|
||||||
|
0, /* iConfiguration. */
|
||||||
|
FEATURE_BUS_POWERED, /* bmAttributes. */
|
||||||
|
50, /* bMaxPower (100mA). */
|
||||||
|
/* Interface Descriptor.*/
|
||||||
|
9,
|
||||||
|
INTERFACE_DESCRIPTOR,
|
||||||
|
0x00, /* bInterfaceNumber. */
|
||||||
|
0x00, /* bAlternateSetting. */
|
||||||
|
0x02, /* bNumEndpoints. */
|
||||||
|
0xFF, /* bInterfaceClass (Vendor specific). */
|
||||||
|
0x00, /* bInterfaceSubClass. */
|
||||||
|
0x00, /* bInterfaceProtocol. */
|
||||||
|
0, /* iInterface. */
|
||||||
|
/* Endpoint 1-OUT Descriptor.*/
|
||||||
|
7,
|
||||||
|
ENDPOINT_DESCRIPTOR,
|
||||||
|
ENDP1, /* bEndpointAddress. */
|
||||||
|
0x02, /* bmAttributes (Bulk). */
|
||||||
|
0x40, 0x00, /* wMaxPacketSize. */
|
||||||
|
0x00, /* bInterval. */
|
||||||
|
/* Endpoint 1-IN Descriptor.*/
|
||||||
|
7,
|
||||||
|
ENDPOINT_DESCRIPTOR,
|
||||||
|
ENDP1|0x80, /* bEndpointAddress. */
|
||||||
|
0x02, /* bmAttributes (Bulk). */
|
||||||
|
0x40, 0x00, /* wMaxPacketSize. */
|
||||||
|
0x00, /* bInterval. */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* U.S. English language identifier.
|
||||||
|
*/
|
||||||
|
static const uint8_t vrsp_string0[4] = {
|
||||||
|
4, /* bLength */
|
||||||
|
STRING_DESCRIPTOR,
|
||||||
|
0x09, 0x04 /* LangID = 0x0409: US-English */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t vrsp_string1[] = {
|
||||||
|
23*2+2, /* bLength */
|
||||||
|
STRING_DESCRIPTOR, /* bDescriptorType */
|
||||||
|
/* Manufacturer: "Flying Stone Technology" */
|
||||||
|
'F', 0, 'l', 0, 'y', 0, 'i', 0, 'n', 0, 'g', 0, ' ', 0, 'S', 0,
|
||||||
|
't', 0, 'o', 0, 'n', 0, 'e', 0, ' ', 0, 'T', 0, 'e', 0, 'c', 0,
|
||||||
|
'h', 0, 'n', 0, 'o', 0, 'l', 0, 'o', 0, 'g', 0, 'y', 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t vrsp_string2[] = {
|
||||||
|
14*2+2, /* bLength */
|
||||||
|
STRING_DESCRIPTOR, /* bDescriptorType */
|
||||||
|
/* Product name: "Chopstx Sample" */
|
||||||
|
'C', 0, 'h', 0, 'o', 0, 'p', 0, 's', 0, 't', 0, 'x', 0, ' ', 0,
|
||||||
|
'S', 0, 'a', 0, 'm', 0, 'p', 0, 'l', 0, 'e', 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Serial Number string.
|
||||||
|
*/
|
||||||
|
static const uint8_t vrsp_string3[10] = {
|
||||||
|
10, /* bLength */
|
||||||
|
STRING_DESCRIPTOR, /* bDescriptorType */
|
||||||
|
'0', 0, '.', 0, '0', 0, '0', 0, /* Version number */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NUM_INTERFACES 1
|
||||||
|
|
||||||
|
static void
|
||||||
|
usb_device_reset (struct usb_dev *dev)
|
||||||
|
{
|
||||||
|
usb_lld_reset (dev, FEATURE_BUS_POWERED);
|
||||||
|
|
||||||
|
chopstx_mutex_lock (&vrsp0.mtx);
|
||||||
|
vrsp0.device_state = USB_DEVICE_STATE_ATTACHED;
|
||||||
|
vrsp0.screen_mem_owner = 0;
|
||||||
|
vrsp0.screen_ptr = screen_image;
|
||||||
|
vrsp0.mode = 2;
|
||||||
|
chopstx_cond_signal (&vrsp0.cnd);
|
||||||
|
chopstx_mutex_unlock (&vrsp0.mtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
usb_ctrl_write_finish (struct usb_dev *dev)
|
||||||
|
{
|
||||||
|
(void)dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
usb_setup (struct usb_dev *dev)
|
||||||
|
{
|
||||||
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t type_rcp = arg->type & (REQUEST_TYPE|RECIPIENT);
|
||||||
|
|
||||||
|
if (USB_SETUP_SET (arg->type))
|
||||||
|
{
|
||||||
|
if (type_rcp == (VENDOR_REQUEST | INTERFACE_RECIPIENT)
|
||||||
|
&& arg->request == 0x00
|
||||||
|
&& arg->index == 0 /* interface 0 */)
|
||||||
|
{
|
||||||
|
struct vrsp *v = vrsp_get (arg->index, 0);
|
||||||
|
|
||||||
|
/* Finish the screen update. */
|
||||||
|
vrsp_update_finish (v, arg->value);
|
||||||
|
return usb_lld_ctrl_ack (dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
usb_get_descriptor (struct usb_dev *dev)
|
||||||
|
{
|
||||||
|
struct device_req *arg = &dev->dev_req;
|
||||||
|
uint8_t rcp = arg->type & RECIPIENT;
|
||||||
|
uint8_t desc_type = (arg->value >> 8);
|
||||||
|
uint8_t desc_index = (arg->value & 0xff);
|
||||||
|
|
||||||
|
if (rcp != DEVICE_RECIPIENT)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (desc_type == DEVICE_DESCRIPTOR)
|
||||||
|
return usb_lld_ctrl_send (dev,
|
||||||
|
vrsp_device_desc, sizeof (vrsp_device_desc));
|
||||||
|
else if (desc_type == CONFIG_DESCRIPTOR)
|
||||||
|
return usb_lld_ctrl_send (dev,
|
||||||
|
vrsp_config_desc, sizeof (vrsp_config_desc));
|
||||||
|
else if (desc_type == STRING_DESCRIPTOR)
|
||||||
|
{
|
||||||
|
const uint8_t *str;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
switch (desc_index)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
str = vrsp_string0;
|
||||||
|
size = sizeof (vrsp_string0);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
str = vrsp_string1;
|
||||||
|
size = sizeof (vrsp_string1);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
str = vrsp_string2;
|
||||||
|
size = sizeof (vrsp_string2);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
str = vrsp_string3;
|
||||||
|
size = sizeof (vrsp_string3);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return usb_lld_ctrl_send (dev, str, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint8_t status_zero;
|
||||||
|
|
||||||
|
static void
|
||||||
|
vrsp_setup_endpoints_for_interface (struct usb_dev *dev,
|
||||||
|
uint16_t interface, int stop)
|
||||||
|
{
|
||||||
|
if (interface == 0)
|
||||||
|
{
|
||||||
|
if (!stop)
|
||||||
|
{
|
||||||
|
struct vrsp *v = vrsp_get (interface, 0);
|
||||||
|
|
||||||
|
usb_lld_setup_endp (dev, ENDP1, EP_BULK, 1, 1);
|
||||||
|
|
||||||
|
if (v->screen_mem_owner == 0)
|
||||||
|
usb_lld_tx_enable_buf (&v->dev, ENDP1, &status_zero, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
usb_lld_stall_rx (dev, ENDP1);
|
||||||
|
usb_lld_stall_tx (dev, ENDP1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
usb_set_configuration (struct usb_dev *dev)
|
||||||
|
{
|
||||||
|
uint8_t current_conf;
|
||||||
|
|
||||||
|
current_conf = usb_lld_current_configuration (dev);
|
||||||
|
if (current_conf == 0)
|
||||||
|
{
|
||||||
|
if (dev->dev_req.value != 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
usb_lld_set_configuration (dev, 1);
|
||||||
|
vrsp_setup_endpoints_for_interface (dev, 0, 0);
|
||||||
|
}
|
||||||
|
else if (current_conf != dev->dev_req.value)
|
||||||
|
{
|
||||||
|
if (dev->dev_req.value != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
usb_lld_set_configuration (dev, 0);
|
||||||
|
vrsp_setup_endpoints_for_interface (dev, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return usb_lld_ctrl_ack (dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
usb_set_interface (struct usb_dev *dev)
|
||||||
|
{
|
||||||
|
uint16_t interface = dev->dev_req.index;
|
||||||
|
uint16_t alt = dev->dev_req.value;
|
||||||
|
|
||||||
|
if (interface >= NUM_INTERFACES)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (alt != 0)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vrsp_setup_endpoints_for_interface (dev, interface, 0);
|
||||||
|
return usb_lld_ctrl_ack (dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
usb_get_interface (struct usb_dev *dev)
|
||||||
|
{
|
||||||
|
const uint8_t zero = 0;
|
||||||
|
uint16_t interface = dev->dev_req.index;
|
||||||
|
|
||||||
|
if (interface >= NUM_INTERFACES)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* We don't have alternate interface, so, always return 0. */
|
||||||
|
return usb_lld_ctrl_send (dev, &zero, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
usb_get_status_interface (struct usb_dev *dev)
|
||||||
|
{
|
||||||
|
const uint16_t status_info = 0;
|
||||||
|
uint16_t interface = dev->dev_req.index;
|
||||||
|
|
||||||
|
if (interface >= NUM_INTERFACES)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return usb_lld_ctrl_send (dev, &status_info, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vrsp_update_receive (struct vrsp *v, int len)
|
||||||
|
{
|
||||||
|
chopstx_mutex_lock (&v->mtx);
|
||||||
|
if (v->screen_mem_owner == 0 && v->screen_ptr)
|
||||||
|
{
|
||||||
|
v->screen_ptr += len / 2;
|
||||||
|
if (v->screen_ptr < screen_image + 12800)
|
||||||
|
usb_lld_rx_enable_buf (&v->dev, ENDP1, v->screen_ptr, 64);
|
||||||
|
}
|
||||||
|
chopstx_mutex_unlock (&v->mtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vrsp_update_finish (struct vrsp *v, int value)
|
||||||
|
{
|
||||||
|
chopstx_mutex_lock (&v->mtx);
|
||||||
|
if (v->screen_mem_owner == 0 && v->screen_ptr)
|
||||||
|
{
|
||||||
|
v->screen_ptr = NULL;
|
||||||
|
v->mode = value;
|
||||||
|
chopstx_cond_signal (&v->cnd);
|
||||||
|
}
|
||||||
|
chopstx_mutex_unlock (&v->mtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usb_tx_done (uint8_t ep_num, uint16_t len)
|
||||||
|
{
|
||||||
|
struct vrsp *v = vrsp_get (-1, ep_num);
|
||||||
|
|
||||||
|
(void)len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Coming here means that notification ("it's ready to accept screen
|
||||||
|
* data") is retrieved by host. Enable the receive endpoint to
|
||||||
|
* accept data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* EP_NUM should be ENDP1 in this implementation. */
|
||||||
|
usb_lld_rx_enable_buf (&v->dev, ENDP1, v->screen_ptr, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usb_rx_ready (uint8_t ep_num, uint16_t len)
|
||||||
|
{
|
||||||
|
struct vrsp *v = vrsp_get (-1, ep_num);
|
||||||
|
|
||||||
|
if (ep_num == ENDP1)
|
||||||
|
vrsp_update_receive (v, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PRIO_VRSP 4
|
||||||
|
|
||||||
|
#define STACK_PROCESS_2
|
||||||
|
#include "stack-def.h"
|
||||||
|
#define STACK_ADDR_VRSP ((uint32_t)process2_base)
|
||||||
|
#define STACK_SIZE_VRSP (sizeof process2_base)
|
||||||
|
|
||||||
|
static void *
|
||||||
|
vrsp_main (void *arg)
|
||||||
|
{
|
||||||
|
struct vrsp *v = arg;
|
||||||
|
struct usb_dev *dev = &v->dev;
|
||||||
|
int e;
|
||||||
|
|
||||||
|
chopstx_claim_irq (&usb_intr, INTR_REQ_USB);
|
||||||
|
usb_lld_init (dev, FEATURE_BUS_POWERED);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
chopstx_intr_wait (&usb_intr);
|
||||||
|
if (usb_intr.ready)
|
||||||
|
{
|
||||||
|
uint8_t ep_num;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When interrupt is detected, call usb_lld_event_handler.
|
||||||
|
* The event may be one of following:
|
||||||
|
* (1) Transfer to endpoint (bulk or interrupt)
|
||||||
|
* In this case EP_NUM is encoded in the variable E.
|
||||||
|
* (2) "NONE" event: some trasfer was done, but all was
|
||||||
|
* done by lower layer, no other work is needed in
|
||||||
|
* upper layer.
|
||||||
|
* (3) Device events: Reset or Suspend
|
||||||
|
* (4) Device requests to the endpoint zero.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
e = usb_lld_event_handler (dev);
|
||||||
|
chopstx_intr_done (&usb_intr);
|
||||||
|
ep_num = USB_EVENT_ENDP (e);
|
||||||
|
|
||||||
|
if (ep_num != 0)
|
||||||
|
{
|
||||||
|
if (USB_EVENT_TXRX (e))
|
||||||
|
usb_tx_done (ep_num, USB_EVENT_LEN (e));
|
||||||
|
else
|
||||||
|
usb_rx_ready (ep_num, USB_EVENT_LEN (e));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
switch (USB_EVENT_ID (e))
|
||||||
|
{
|
||||||
|
case USB_EVENT_DEVICE_RESET:
|
||||||
|
usb_device_reset (dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_DEVICE_ADDRESSED:
|
||||||
|
/* The addres is assigned to the device. We don't
|
||||||
|
* need to do anything for this actually, but in this
|
||||||
|
* application, we maintain the USB status of the
|
||||||
|
* device. Usually, just "continue" as EVENT_OK is
|
||||||
|
* OK.
|
||||||
|
*/
|
||||||
|
chopstx_mutex_lock (&v->mtx);
|
||||||
|
v->device_state = USB_DEVICE_STATE_ADDRESSED;
|
||||||
|
chopstx_cond_signal (&v->cnd);
|
||||||
|
chopstx_mutex_unlock (&v->mtx);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_GET_DESCRIPTOR:
|
||||||
|
if (usb_get_descriptor (dev) < 0)
|
||||||
|
usb_lld_ctrl_error (dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_SET_CONFIGURATION:
|
||||||
|
if (usb_set_configuration (dev) < 0)
|
||||||
|
usb_lld_ctrl_error (dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_SET_INTERFACE:
|
||||||
|
if (usb_set_interface (dev) < 0)
|
||||||
|
usb_lld_ctrl_error (dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_CTRL_REQUEST:
|
||||||
|
/* Device specific device request. */
|
||||||
|
if (usb_setup (dev) < 0)
|
||||||
|
usb_lld_ctrl_error (dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_GET_STATUS_INTERFACE:
|
||||||
|
if (usb_get_status_interface (dev) < 0)
|
||||||
|
usb_lld_ctrl_error (dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_GET_INTERFACE:
|
||||||
|
if (usb_get_interface (dev) < 0)
|
||||||
|
usb_lld_ctrl_error (dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_SET_FEATURE_DEVICE:
|
||||||
|
case USB_EVENT_SET_FEATURE_ENDPOINT:
|
||||||
|
case USB_EVENT_CLEAR_FEATURE_DEVICE:
|
||||||
|
case USB_EVENT_CLEAR_FEATURE_ENDPOINT:
|
||||||
|
usb_lld_ctrl_ack (dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_CTRL_WRITE_FINISH:
|
||||||
|
/* Control WRITE transfer finished. */
|
||||||
|
usb_ctrl_write_finish (dev);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case USB_EVENT_OK:
|
||||||
|
case USB_EVENT_DEVICE_SUSPEND:
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vrsp_ready_check (void *arg)
|
||||||
|
{
|
||||||
|
struct vrsp *v = arg;
|
||||||
|
return v->screen_mem_owner == 0 && v->screen_ptr == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* API exposed to application. */
|
||||||
|
|
||||||
|
struct vrsp *
|
||||||
|
vrsp_open (void)
|
||||||
|
{
|
||||||
|
struct vrsp *v = &vrsp0; /* Now, we only have a single VRSP. */
|
||||||
|
|
||||||
|
chopstx_mutex_init (&v->mtx);
|
||||||
|
chopstx_cond_init (&v->cnd);
|
||||||
|
v->device_state = USB_DEVICE_STATE_UNCONNECTED;
|
||||||
|
v->screen_mem_owner = 0;
|
||||||
|
v->screen_ptr = screen_image;
|
||||||
|
v->mode = 1;
|
||||||
|
|
||||||
|
chopstx_create (PRIO_VRSP, STACK_ADDR_VRSP, STACK_SIZE_VRSP, vrsp_main, v);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
vrsp_prepare_poll (struct vrsp *v, chopstx_poll_cond_t *poll_desc)
|
||||||
|
{
|
||||||
|
poll_desc->type = CHOPSTX_POLL_COND;
|
||||||
|
poll_desc->ready = 0;
|
||||||
|
poll_desc->cond = &v->cnd;
|
||||||
|
poll_desc->mutex = &v->mtx;
|
||||||
|
poll_desc->check = vrsp_ready_check;
|
||||||
|
poll_desc->arg = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vrsp_screen_acquire: Acquire the screen memory by the application to
|
||||||
|
* update the LCD.
|
||||||
|
*
|
||||||
|
* Returns < 0 on error
|
||||||
|
* >= 0 on success
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vrsp_screen_acquire (struct vrsp *v)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
chopstx_mutex_lock (&v->mtx);
|
||||||
|
while (1)
|
||||||
|
if (v->screen_mem_owner != 0)
|
||||||
|
{
|
||||||
|
/* something goes wrong, it's your turn already. */
|
||||||
|
r = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (v->screen_ptr)
|
||||||
|
/* The use of screen has not been finished yet. */
|
||||||
|
chopstx_cond_wait (&v->cnd, &v->mtx);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v->screen_mem_owner = 1;
|
||||||
|
r = v->mode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
chopstx_mutex_unlock (&v->mtx);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vrsp_screen_release: release the screen memory by the application
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
vrsp_screen_release (struct vrsp *v)
|
||||||
|
{
|
||||||
|
chopstx_mutex_lock (&v->mtx);
|
||||||
|
v->screen_mem_owner = 0;
|
||||||
|
v->screen_ptr = screen_image;
|
||||||
|
chopstx_mutex_unlock (&v->mtx);
|
||||||
|
|
||||||
|
/* Put the notification to host. */
|
||||||
|
usb_lld_tx_enable_buf (&v->dev, ENDP1, &status_zero, 1);
|
||||||
|
}
|
||||||
7
example-lcd/vrsp.h
Normal file
7
example-lcd/vrsp.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
struct vrsp;
|
||||||
|
|
||||||
|
struct vrsp *vrsp_open (void);
|
||||||
|
|
||||||
|
void vrsp_prepare_poll (struct vrsp *v, chopstx_poll_cond_t *poll_desc);
|
||||||
|
int vrsp_screen_acquire (struct vrsp *v);
|
||||||
|
void vrsp_screen_release (struct vrsp *v);
|
||||||
Reference in New Issue
Block a user