5 Commits

Author SHA1 Message Date
t-moe 552d0585de Unpacked Tft, Touch,Gui and SD library from idpa project 2015-03-17 14:18:36 +01:00
t-moe 91352a222b Added idpa reference software 2015-03-17 13:48:39 +01:00
t-moe 0dbe45a0b4 Cleaned up folders. 2015-03-17 13:33:35 +01:00
t-moe 6967573645 Updated pheriph driver to 1.4 2015-03-02 20:01:54 +01:00
t-moe cc41f75734 First version of disovery toolchain 2015-03-02 19:16:04 +01:00
339 changed files with 4579 additions and 284241 deletions
+7 -8
View File
@@ -22,8 +22,11 @@
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.174263624" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
<builder id="cdt.managedbuild.builder.gnu.cross.1279514893" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.builder.gnu.cross"/>
<tool id="cdt.managedbuild.tool.gnu.cross.c.compiler.1136001261" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
<option id="gnu.c.compiler.option.include.paths.649992569" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/discoverpixy discovery/common}&quot;"/>
<option id="gnu.c.compiler.option.include.paths.649992569" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/example/libs/BSP}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/example/libs/sGUI}&quot;"/>
<listOptionValue builtIn="false" value="/usr/arm-none-eabi/include"/>
<listOptionValue builtIn="false" value="/usr/lib/gcc/arm-none-eabi/4.9.2/include"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1184220438" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
@@ -32,8 +35,8 @@
</tool>
<tool id="cdt.managedbuild.tool.gnu.cross.c.linker.1771545603" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/>
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.linker.490606250" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker">
<option id="gnu.cpp.link.option.paths.312574565" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" valueType="libPaths">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/discoverpixy discovery/libs}&quot;"/>
<option id="gnu.cpp.link.option.paths.312574565" superClass="gnu.cpp.link.option.paths" valueType="libPaths">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/example/libs}&quot;"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.648346019" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
@@ -46,10 +49,6 @@
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="common" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="common"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
-5
View File
@@ -3,8 +3,3 @@ obj/
libs/*/obj
libs/*/*.a
libs/*/*.o
*~
*.swp
*.swo
+1 -8
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>discoverpixy discovery</name>
<name>example</name>
<comment></comment>
<projects>
</projects>
@@ -24,11 +24,4 @@
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
<linkedResources>
<link>
<name>common</name>
<type>2</type>
<location>PARENT-1-PROJECT_LOC/common</location>
</link>
</linkedResources>
</projectDescription>
@@ -5,10 +5,6 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
<provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="1373821771994211724" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
</extension>
</configuration>
-2414
View File
File diff suppressed because it is too large Load Diff
+10 -43
View File
@@ -1,14 +1,13 @@
#2015 by tmoe, id10101 (and the internet :) )
#Name of the binary/project
TARGET=discoverpixy
TARGET=hello
#Tools
CROSS_COMPILE=arm-none-eabi-
CC=$(CROSS_COMPILE)gcc -fdiagnostics-color=auto
CC=$(CROSS_COMPILE)gcc
OBJCOPY=$(CROSS_COMPILE)objcopy
GDB=$(CROSS_COMPILE)gdb
SIZE=$(CROSS_COMPILE)size
MKDIR=mkdir -p
RM=rm -f
@@ -22,56 +21,32 @@ SRC_DIR=./src
OBJ_DIR=./obj
BUILD_DIR=./build
LIB_DIR=./libs
COMMON_DIR=../common
#Architecture flags
FP_FLAGS?=-mfpu=fpv4-sp-d16 -mfloat-abi=softfp
ARCH_FLAGS=-mthumb -mcpu=cortex-m4 $(FP_FLAGS)
#Compiler, Linker Options
#LIB_FOLDERS=$(shell find $(LIB_DIR) -maxdepth 1 -type d ! -path $(LIB_DIR))
INCLUDES=$(LIB_DIR)/StmCoreNPheriph/inc
INCLUDES+=$(LIB_DIR)/StmUsbHost/STM32_USB_Device_Specific
INCLUDES+=$(LIB_DIR)/StmUsbHost/STM32_USB_OTG_Driver/inc
INCLUDES+=$(LIB_DIR)/StmUsbHost/STM32_USB_HOST_Library/Core/inc
INCLUDES+=$(shell find $(COMMON_DIR) -maxdepth 1 -type d ! -path $(COMMON_DIR))
CPPFLAGS=-I$(LIB_DIR)/StmCoreNPheriph/inc
CFLAGS=$(ARCH_FLAGS) -O0 -g
INCLUDES:=$(addprefix -I,$(INCLUDES))
CPPFLAGS=-DUSE_USB_OTG_FS -DUSE_HOST_MODE $(INCLUDES)
CFLAGS=$(ARCH_FLAGS) -O0 -g -std=c99 -fdata-sections -ffunction-sections
LIBS=pixy usbhost coreperiph stdc++
LIBSEARCHDIRS=$(LIB_DIR)/StmCoreNPheriph
LIBSEARCHDIRS+=$(LIB_DIR)/StmUsbHost
LIBSEARCHDIRS+=$(LIB_DIR)/Pixy
LDFLAGS=--specs=nano.specs -Wl,--gc-sections
LDFLAGS+=$(addprefix -L,$(LIBSEARCHDIRS))
LDFLAGS+=$(addprefix -l,$(LIBS))
LDFLAGS=--specs=nosys.specs
#Finding Input files
CFILES=$(shell find $(SRC_DIR) -name '*.c')
SFILES=$(SRC_DIR)/startup.s
COMMON_CFILES=$(shell find $(COMMON_DIR) -name '*.c')
#Generate corresponding obj names
SOBJS=$(SFILES:.s=.o)
COBJS=$(CFILES:.c=.o)
OBJS=$(patsubst $(SRC_DIR)/%,$(OBJ_DIR)/%,$(SOBJS) $(COBJS))
COMMON_OBJS=$(patsubst $(COMMON_DIR)/%,$(OBJ_DIR)/%,$(COMMON_CFILES:.c=.o))
#Keep the objects files
.SECONDARY: $(OBJS)
#Mark targets which are not "file-targets"
.PHONY: all debug flash start stop backup clean
#keep objs files
.SECONDARY: $(OBJS) $(COMMON_OBJS)
# List of all binaries to build
all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).bin
@@ -82,16 +57,14 @@ stop:
$(STUTIL) stop
#objects to elf
%.elf : $(OBJS) $(COMMON_OBJS)
%.elf : $(OBJS)
@echo Linking...
$(MKDIR) $(BUILD_DIR)
$(CC) -o $@ $(CFLAGS) $(CPPFLAGS) -T./utils/stm32_flash.ld -Wl,-Map,$(BUILD_DIR)/$(TARGET).map $^ $(LDFLAGS)
#$(CC) -o $@ $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -Wl,--verbose -Wl,-Map,$(BUILD_DIR)/$(TARGET).map $^
$(CC) -o $@ $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -T./utils/stm32_flash.ld $^
#elf to binary
%.bin: %.elf
$(OBJCOPY) -O binary $< $@
$(SIZE) $<
#Asm files to objects
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.s
@@ -105,12 +78,6 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(MKDIR) $(OBJ_DIR)
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
#common C files to objects
$(OBJ_DIR)/%.o: $(COMMON_DIR)/%.c
@echo Compiling Common file $<...
$(MKDIR) $(dir $(patsubst $(COMMON_DIR)/%,$(OBJ_DIR)/%, $<))
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
#Clean Obj files and builded stuff
clean:
$(RMDIR) $(BUILD_DIR) $(OBJ_DIR)
+4 -22
View File
@@ -1,24 +1,6 @@
# discoverpixy
A Project with the Pixy cam and the STM32F4 Discovery. The project can also be run on linux/windows using a qt-based emulator.
Discoverpixy
============================
![Pixy Logo](doc/pixy.png)
<img src="doc/mainscreen_emulator.png" width="300">
<img src="doc/tracking_emulator.png" width="300">
#TODO
Adjust this readme
## Documentation
Take a look at our [docu.pdf](./doc/docu.pdf) (German)
Also make sure to check out the [doxygen documentation](http://t-moe.github.io/discoverpixy/) for the common folder.
## Folder structure
* *common*: device independent code and the "Application" itself
* *emulator*: display/touch/sd emulator written in qt. pixy can be connect via usb to computer
* *discovery*: display/touch/sd/pixy can be connected to STM32F4Discovery
All code in the common folder **MUST** be device independent.
The folder *common/lowlevel* provides the function headers for the device specific code.
## How to build
Go into the *emulator* or the *discovery* folder an use *make*
-2
View File
@@ -1,2 +0,0 @@
# Temporary files
*.swp
-53
View File
@@ -1,53 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/app.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator
* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop.
* 2015-04-03 timolang@gmail.com cab8609 Integrated pixy into emulator. Pixy is no longer in the common/libs folder but in emulator/libs and discovery/libs
* 2015-04-03 timolang@gmail.com 1aa9194 Fixed Drawing of rects in Emulator. Got frames from pixy to emulator. Slooooow.
* 2015-04-25 timolang@gmail.com 416883c Pixy&Usb work with the new folder structure now.
* 2015-04-25 timolang@gmail.com 3d1e4b2 Simplified code a bit. Emulator does not work stable when replugging pixy.
* 2015-04-25 timolang@gmail.com 0858b0d Fixed some bugs when receiving large data.
* 2015-04-27 timolang@gmail.com 259d446 Added touch support to emulator. Implemented basic touch function.
* 2015-04-27 aaron@duckpond.ch aed90ef Drawcircle added (emulator)
* 2015-04-27 timolang@gmail.com e249fb2 Added font support
* 2015-04-27 timolang@gmail.com 7c9eabc Added button support.
* 2015-04-27 timolang@gmail.com b300ac5 Added Checkbox support
* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
* 2015-05-10 timolang@gmail.com e2bce8f Added filesystem module, tests and implementation for it in emulator.
* 2015-05-12 aaron@duckpond.ch aec62d4 Added datasheets, updated touchsupport.
* 2015-05-28 aaron@duckpond.ch 5bda699 implemented functions to get x and y coordinates and a test function
* 2015-05-29 aaron@duckpond.ch 7d2d1a1 Implemented basic sampling and averaging of touch coordinates using timer7
*
**************************************************************************************************************************************/
#include "app.h"
#include "tft.h"
#include "system.h"
#include "touch.h"
#include "screen_main.h"
#include "filesystem.h"
void app_init()
{
system_init();
tft_init();
touch_init();
filesystem_init();
gui_screen_navigate(get_screen_main());
}
//app event loop
void app_process()
{
system_process(); //Let the system handle it's pending events
gui_screen_update(); //update the currently active screen
}
-47
View File
@@ -1,47 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/app.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator
* 2015-05-10 timolang@gmail.com 21edc56 Added doxyfile (doxygen) for the common folder. Started with doxygen comments for app and tft module.
* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure
* 2015-06-08 timolang@gmail.com 73db8b5 Added doxygen mainpage comment in app.h
*
**************************************************************************************************************************************/
#ifndef APP_H
#define APP_H
/*!
\mainpage discoverpixy Doxygen Documentation
Welcome to the code-documentation for all common (and plattformindependent) code. \n
A good point to start is probably the <a href="modules.html">Modules</a> page.
*/
/**
* @defgroup app Application
* The App Module contains the effective, platform independent application.
*/
/*@{*/
/**
* Starts/Initializes the app
* This function should be called at the top of the main function of your platform
*/
void app_init();
/**
* Executes one cycle of the app
* Call this function repeatedly from a loop inside the main function
*/
void app_process();
/*@}*/
#endif /* APP_H */
-88
View File
@@ -1,88 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/pixy_control.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-06-02 aaron@duckpond.ch e018a75 Implemented basic pi and pid controller
* 2015-06-06 aaron@duckpond.ch 8c264c2 Comment refactoring, updated PID values
* 2015-06-06 aaron@duckpond.ch a04cda9 Refactured comments and implemented a bugfix for the PID controller
* 2015-06-07 aaron@duckpond.ch 802d3df Fixed pid controller and refactored code
* 2015-06-07 aaron@duckpond.ch 3d98ca9 Minor changes
* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h
*
**************************************************************************************************************************************/
/*
* pixy_control.c
*
* Notation
* --------
*
* x : Sollwert (Führgrösse)
* w : Istwert (Reglergrösse)
* esum : Integralteil
* e : Regelabweichung
* y : Stellgrösse
*
*
*/
#include<pixy_control.h>
#include<stdint.h>
// PID tuning factors
#define REG_PID_KP (0.41f)
#define REG_PID_KI (0.001f)
#define REG_PID_KD (0.00025f)
#define REG_PID_TA (0.001f)
#define REG_PID_YKOR (0.3f)
// PID controller implementatoin for the y-axis
int16_t pixy_PID_Y(int16_t x, int16_t w)
{
float e = 0;
static float esum = 0;
static float eold = 0;
float y = 0;
e = (float)(x - w); // calculate the controller offset
//----PID-control-------------------------------------------------------------------------
esum = esum + e; // add e to the current sum
y += (REG_PID_KP + REG_PID_YKOR) * e; // add the proportional part to the output
y += REG_PID_KI * REG_PID_TA * esum; // add the integral part to the output
y += REG_PID_KD * (e - eold) / REG_PID_TA; // add the differential part to the output
//----------------------------------------------------------------------------------------
eold = e; // save the previous value
return (int16_t)y;
}
// PID controller implementation for the x-axis
int16_t pixy_PID_X(int16_t x, int16_t w)
{
float e = 0;
static float esum = 0;
static float eold = 0;
float y = 0;
e = (float)(x - w); // calculate the controller offset
//----PID-control-------------------------------------------------------------------------
esum = esum + e; // add e to the current sum
y += REG_PID_KP * e; // add the proportional part to the output
y += REG_PID_KI * REG_PID_TA * esum; // add the integral part to the output
y += REG_PID_KD * (e - eold) / REG_PID_TA; // add the differential part to the output
//----------------------------------------------------------------------------------------
eold = e; // save the previous value
return (int16_t)y;
}
-58
View File
@@ -1,58 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/pixy_control.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-06-02 aaron@duckpond.ch e018a75 Implemented basic pi and pid controller
* 2015-06-06 aaron@duckpond.ch 8c264c2 Comment refactoring, updated PID values
* 2015-06-06 aaron@duckpond.ch a04cda9 Refactured comments and implemented a bugfix for the PID controller
* 2015-06-07 aaron@duckpond.ch 802d3df Fixed pid controller and refactored code
* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h
*
**************************************************************************************************************************************/
#ifndef PIXY_CONTROL_H_
#define PIXY_CONTROL_H_
#include<stdint.h>
/**
* @addtogroup app
*/
/*@{*/
/**
* @defgroup pixy_control Pixy Control Helper
* A collection of helper functions that contain PID Control code used for object tracking.
*/
/*@}*/
/**
* @addtogroup pixy_control
*/
/*@{*/
/**
* Execute one step of PID regulation for the Y-servo.
* @param x desired value (e.g. current y-position of the biggest block)
* @param w actual value (e.g desired y-position)
* @return The offset which needs to be added to the Y-Servo position
*/
int16_t pixy_PID_Y(int16_t x, int16_t w);
/**
* Execute one step of PID regulation for the X-servo.
* @param x desired value (e.g. current x-position of the biggest block)
* @param w actual value (e.g desired x-position)
* @return The offset which needs to be added to the X-Servo position
*/
int16_t pixy_PID_X(int16_t x, int16_t w);
/*@}*/
#endif /* PIXY_CONTROL_H_ */
-248
View File
@@ -1,248 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/pixy_frame.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h
*
**************************************************************************************************************************************/
#include "pixy_frame.h"
#include "pixy.h"
#include "tft.h"
#include <stdlib.h>
static int renderBA81(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t* frame);
static int saveBA81(FILE_HANDLE* handle, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t* frame);
int pixy_render_full_frame(uint16_t x, uint16_t y)
{
return pixy_render_cropped_frame(x, y, 0, 0, 320, 200);
}
int pixy_render_cropped_frame(uint16_t x, uint16_t y, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height)
{
uint8_t* videodata;
int32_t response;
int32_t fourccc;
int8_t renderflags;
uint16_t xwidth;
uint16_t ywidth;
uint32_t size;
int return_value = pixy_command("cam_getFrame", // String id for remote procedure
INT8(0x21), // mode
INT16(xoffset), // xoffset
INT16(yoffset), // yoffset
INT16(width), // width
INT16(height), // height
END_OUT_ARGS, // separator
&response, // pointer to mem address for return value
&fourccc,
&renderflags,
&xwidth,
&ywidth,
&size,
&videodata, // pointer to mem address for returned frame
END_IN_ARGS);
if (return_value == 0) {
return_value = renderBA81(x, y, xwidth, ywidth, size, videodata);
}
return return_value;
}
int pixy_save_full_frame(FILE_HANDLE* handle)
{
return pixy_save_cropped_frame(handle, 0, 0, 320, 200);
}
int pixy_save_cropped_frame(FILE_HANDLE* handle, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height)
{
uint8_t* videodata;
int32_t response;
int32_t fourccc;
int8_t renderflags;
uint16_t xwidth;
uint16_t ywidth;
uint32_t size;
int return_value = pixy_command("cam_getFrame", // String id for remote procedure
INT8(0x21), // mode
INT16(xoffset), // xoffset
INT16(yoffset), // yoffset
INT16(width), // width
INT16(height), // height
END_OUT_ARGS, // separator
&response, // pointer to mem address for return value
&fourccc,
&renderflags,
&xwidth,
&ywidth,
&size,
&videodata, // pointer to mem address for returned frame
END_IN_ARGS);
if (return_value == 0) {
return_value = saveBA81(handle, xwidth, ywidth, size, videodata);
}
return return_value;
}
static void interpolateBayer(uint16_t width, uint16_t x, uint16_t y, uint8_t* pixel, uint8_t* r, uint8_t* g, uint8_t* b)
{
if (y & 1) {
if (x & 1) {
*r = *pixel;
*g = (*(pixel - 1) + * (pixel + 1) + * (pixel + width) + * (pixel - width)) >> 2;
*b = (*(pixel - width - 1) + * (pixel - width + 1) + * (pixel + width - 1) + * (pixel + width + 1)) >> 2;
} else {
*r = (*(pixel - 1) + * (pixel + 1)) >> 1;
*g = *pixel;
*b = (*(pixel - width) + * (pixel + width)) >> 1;
}
} else {
if (x & 1) {
*r = (*(pixel - width) + * (pixel + width)) >> 1;
*g = *pixel;
*b = (*(pixel - 1) + * (pixel + 1)) >> 1;
} else {
*r = (*(pixel - width - 1) + * (pixel - width + 1) + * (pixel + width - 1) + * (pixel + width + 1)) >> 2;
*g = (*(pixel - 1) + * (pixel + 1) + * (pixel + width) + * (pixel - width)) >> 2;
*b = *pixel;
}
}
}
static int renderBA81(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t* frame)
{
uint16_t x, y;
uint8_t r, g, b;
// skip first line
frame += width;
// don't render top and bottom rows, and left and rightmost columns because of color
// interpolation
//uint32_t decodedimage[(width-2)*(height-2)];
uint16_t* decodedimage = malloc(sizeof(uint16_t) * (width - 2) * (height - 2));
if (decodedimage == NULL) { //not enough free space to decode image in memory
//decode & render image pixel by pixel
for (y = 1; y < height - 1; y++) {
frame++;
for (x = 1; x < width - 1; x++, frame++) {
interpolateBayer(width, x, y, frame, &r, &g, &b);
tft_draw_pixel(xpos + x - 1, ypos + y - 1, RGB(r, g, b));
}
frame++;
}
} else { //enough space
uint16_t* line = decodedimage;
for (y = 1; y < height - 1; y++) {
//line = (unsigned int *)img.scanLine(y-1);
frame++;
for (x = 1; x < width - 1; x++, frame++) {
interpolateBayer(width, x, y, frame, &r, &g, &b);
//*line++ = (0xff<<24) | (r<<16) | (g<<8) | (b<<0);
*line++ = RGB(r, g, b);
}
frame++;
}
tft_draw_bitmap_unscaled(xpos, ypos, width - 2, height - 2, decodedimage);
free(decodedimage);
}
return 0;
}
static int saveBA81(FILE_HANDLE* handle, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t* frame)
{
uint16_t x, y;
uint8_t r, g, b;
uint32_t fpos = handle->fpos;
uint32_t row_size_padded = ((width - 2) * 3 + 3) & (~3); //row size aligned to 4 bytes
uint32_t fpos_end = fpos + row_size_padded * (height - 2);
// skip first line
frame += width;
// don't render top and bottom rows, and left and rightmost columns because of color
// interpolation
for (y = 1; y < height - 1; y++) {
frame++;
uint8_t rowbuf[row_size_padded];
//Bitmaps are saved "bottom-up". Seek to the right row.
if (filesystem_file_seek(handle, fpos_end - row_size_padded * y) != F_OK) {
return -1;
}
for (x = 1; x < width - 1; x++, frame++) {
interpolateBayer(width, x, y, frame, &r, &g, &b);
//bitmaps are saved in 24bit b,g,r format
rowbuf[(x - 1) * 3] = b;
rowbuf[(x - 1) * 3 + 1] = g;
rowbuf[(x - 1) * 3 + 2] = r;
}
if (filesystem_file_write(handle, rowbuf, row_size_padded) != F_OK) {
return -1;
}
frame++;
}
return 0;
}
int pixy_cc_set_region(uint8_t signum, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height)
{
int32_t response;
int return_value = pixy_command("cc_setSigRegion", // String id for remote procedure
INT32(0), // type = normal color code
INT8(signum),
INT16(xoffset), // xoffset
INT16(yoffset), // yoffset
INT16(width), // width
INT16(height), // height
END_OUT_ARGS, // separator
&response, // pointer to mem address for return value
END_IN_ARGS);
return return_value;
}
-94
View File
@@ -1,94 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/pixy_frame.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h
*
**************************************************************************************************************************************/
#ifndef PIXY_FRAME_H
#define PIXY_FRAME_H
#include <stdbool.h>
#include <stdint.h>
#include "filesystem.h"
/**
* @addtogroup app
*/
/*@{*/
/**
* @defgroup pixy_helper Pixy Frame Helper
* A collection of helper functions that allow receiving and rendering a frame from pixy onto the display.
* Furthermore you can select a color in a frame, to use for tracking.
*/
/*@}*/
/**
* @addtogroup pixy_helper
*/
/*@{*/
/**
* Receives a fullsized frame from pixy and display's it on the display with the topleft corner at (x,y)
* @param x The x-Coordinate of the top left corner
* @param y The y-Coordinate of the top left corner
* @return 0 on success, otherwise the errorcode from pixy
*/
int pixy_render_full_frame(uint16_t x, uint16_t y);
/**
* Receives a cropped frame from pixy and display's it on the display with the topleft corner at (x,y)
* @param x The x-Coordinate of the top left corner to draw the image
* @param y The y-Coordinate of the top left corner to draw the image
* @param xoffset The x-Coordinate on the pixy image from where on you want the frame data
* @param yoffset The y-Coordinate on the pixy image from where on you want the frame data
* @param width The width of the image recorded from pixy
* @param height The height of the image recorded from pixy
* @return 0 on success, otherwise the errorcode from pixy
*/
int pixy_render_cropped_frame(uint16_t x, uint16_t y, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height);
/**
* Receives a fullsized frame from pixy and saves it to the given file in the 24bit (b,g,a) format.
* Use this method to write the bitmap-data part of a windows bitmap (.bmp).
* This method will neither open nor close the passed file.
* @param handle The file to write the data to. The file must be open and it should be seeked to the right position.
* @return 0 on success, otherwise the errorcode from pixy
*/
int pixy_save_full_frame(FILE_HANDLE* handle);
/**
* Receives a cropped frame from pixy and saves it to the given file in the 24bit (b,g,a) format.
* @param handle The file to write the data to. The file must be open and it should be seeked to the right position.
* @param xoffset The x-Coordinate on the pixy image from where on you want the frame data
* @param yoffset The y-Coordinate on the pixy image from where on you want the frame data
* @param width The width of the image recorded from pixy
* @param height The height of the image recorded from pixy
* @return 0 on success, otherwise the errorcode from pixy
*/
int pixy_save_cropped_frame(FILE_HANDLE* handle, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height);
/**
* Sets the color signature to the color in the selected region of the frame
* @param signum the color signature number (1..7)
* @param xoffset The x-Coordinate of the topleft point of the region
* @param yoffset The y-Coordinate of the topleft point of the region
* @param width The width of the region
* @param height The height of the region
* @return 0 on success, otherwise the errorcode from pixy
*/
int pixy_cc_set_region(uint8_t signum, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height);
/*@}*/
#endif /* PIXY_FRAME_H */
-155
View File
@@ -1,155 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_filetest.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-05-10 timolang@gmail.com e2bce8f Added filesystem module, tests and implementation for it in emulator.
* 2015-05-10 timolang@gmail.com 790f602 Added bitmap decoding/drawing example
* 2015-05-10 timolang@gmail.com 21edc56 Added doxyfile (doxygen) for the common folder. Started with doxygen comments for app and tft module.
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
* 2015-05-15 timolang@gmail.com 85f1aee Changed filetest to use new bitmap draw method.
*
**************************************************************************************************************************************/
#include "screen_filetest.h"
#include "button.h"
#include "tft.h"
#include "filesystem.h"
#include <stdlib.h>
static BUTTON_STRUCT b_back;
static void b_back_cb(void* button)
{
gui_screen_back();
}
static void image_test();
static void enter(void* screen)
{
tft_clear(HEX(0xBABECD));
//Back button
b_back.base.x1 = 10; //Start X of Button
b_back.base.y1 = 200; //Start Y of Button
b_back.base.x2 = AUTO; //b_back.base.x1+160; //Auto Calculate X2 with String Width
b_back.base.y2 = AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor = WHITE; //Set foreground color
b_back.bgcolor = HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font = 0; //Select Font
b_back.text = "Back"; //Set Text (For formatted strings take sprintf)
b_back.callback = b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
tft_draw_line(10, 30, 310, 30, BLACK);
tft_print_line(10, 18, BLUE, TRANSPARENT, 0, "Name D H RO Date Time Size");
int y = 33;
DIRECTORY_STRUCT* dir = filesystem_dir_open(".");
if (dir == NULL) {
return;
}
for (int i = 0; i < dir->num_files; i++) {
FILE_STRUCT* file = &(dir->files[i]);
tft_print_formatted(10, y,
(file->fattrib & F_DIR) ? GREEN : RED,
TRANSPARENT, 0, "%-13s%c %c %s %02u%02u%02u %02u:%02u:%02u %u",
file->fname,
(file->fattrib & F_DIR) ? 'D' : ' ',
(file->fattrib & F_HID) ? 'H' : ' ',
(file->fattrib & F_RDO) ? "R " : "RW",
file->fdate.day,
file->fdate.month,
(file->fdate.year + 1980) % 100,
file->ftime.hour,
file->ftime.min,
file->ftime.sec * 2,
file->fsize);
y += 14;
}
filesystem_dir_close(dir);
y += 14;
FILE_HANDLE* file = filesystem_file_open("test.txt");
if (file == NULL) {
tft_print_line(10, y, BLUE, TRANSPARENT, 0, "Could not open test.txt");
} else {
char buf [30];
int size = (file->fsize > 30) ? 29 : file->fsize - 1;
FILE_STATUS st = filesystem_file_read(file, buf, size);
if (st == F_OK) {
buf[file->fpos] = '\0';
tft_print_formatted(10, y, BLUE, TRANSPARENT, 0, "test.txt contains \"%s\"", buf);
long num = strtol(&(buf[file->fpos - 4]), NULL, 0);
num++;
y += 14;
if (filesystem_file_seek(file, file->fpos - 4) != F_OK) {
tft_print_formatted(10, y, BLUE, TRANSPARENT, 0, "Could not seek to %d", file->fpos - 4);
} else {
sprintf(buf, "%04d", num);
if (filesystem_file_write(file, buf, 4) != F_OK) {
tft_print_formatted(10, y, BLUE, TRANSPARENT, 0, "Could not write new number %d", num);
} else {
tft_print_formatted(10, y, BLUE, TRANSPARENT, 0, "New number written %d", num);
}
}
} else {
tft_print_line(10, y, BLUE, TRANSPARENT, 0, "Could not read from test.txt");
}
}
filesystem_file_close(file);
image_test();
}
static void leave(void* screen)
{
gui_button_remove(&b_back);
}
static void update(void* screen)
{
}
static SCREEN_STRUCT screen = {
enter,
leave,
update
};
SCREEN_STRUCT* get_screen_filetest()
{
return &screen;
}
static void image_test()
{
if (!tft_draw_bitmap_file_unscaled(250, 170, "cpu.bmp")) {
tft_print_line(10, 180, BLUE, TRANSPARENT, 0, "Could not open cpu.bmp");
}
tft_draw_rectangle(250 - 1, 170 - 1, 250 - 1 + 64, 170 - 1 + 64, BLACK);
}
-38
View File
@@ -1,38 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_filetest.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-05-10 timolang@gmail.com e2bce8f Added filesystem module, tests and implementation for it in emulator.
* 2015-05-10 timolang@gmail.com 21edc56 Added doxyfile (doxygen) for the common folder. Started with doxygen comments for app and tft module.
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
*
**************************************************************************************************************************************/
#include "screen.h"
/**
* @addtogroup screens
*/
/*@{*/
/**
* @defgroup filetest Filetest (Screen)
* The File-Test Screen tests the filesystem module. It read/writes from/to files and shows a bitmap
*/
/*@{*/
/**
* Returns a pointer to the filetest screen
* \sa gui_screen_navigate
* @return
*/
SCREEN_STRUCT* get_screen_filetest();
/*@}*/
/*@}*/
-164
View File
@@ -1,164 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_guitest.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
* 2015-04-30 timolang@gmail.com 76ea9d8 Added num up down support.
* 2015-05-09 timolang@gmail.com c652b6b Improved Emulator Gui
* 2015-05-29 aaron@duckpond.ch 7d2d1a1 Implemented basic sampling and averaging of touch coordinates using timer7
* 2015-06-01 timolang@gmail.com eb573bc Finalized calibration. Fixed a bug in screen module.
* 2015-06-02 timolang@gmail.com da34bce Fixed all printf related problems on discovery using workarounds and newlib nano-instead of newlib
*
**************************************************************************************************************************************/
#include "screen_guitest.h"
#include "button.h"
#include "tft.h"
#include "checkbox.h"
#include "numupdown.h"
static BUTTON_STRUCT b_back;
static TOUCH_AREA_STRUCT a_area;
static CHECKBOX_STRUCT c_cbox;
static NUMUPDOWN_STRUCT n_updown;
static void checkboxCB(void* checkbox, bool checked)
{
printf("Checkbox %s\n", (checked ? "checked" : "unchecked"));
}
static void b_back_cb(void* button)
{
gui_screen_back();
}
static void n_updown_cb(void* numupdown, int16_t value)
{
printf("New NumUpDown Value %d\n", value);
}
static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction)
{
switch (triggeredAction) {
case PEN_DOWN:
printf("action PEN_DOWN\n");
break;
case PEN_UP:
printf("action PEN_UP\n");
break;
case PEN_MOVE:
printf("action PEN_MOVE\n");
break;
case PEN_ENTER:
printf("action PEN_ENTER\n");
break;
case PEN_LEAVE:
printf("action PEN_LEAVE\n");
break;
default:
printf("action %s\n", triggeredAction);
break;
}
}
static void enter(void* screen)
{
tft_clear(HEX(0xA6FD9A));
//Back button
b_back.base.x1 = 10; //Start X of Button
b_back.base.y1 = 10; //Start Y of Button
b_back.base.x2 = AUTO; //b_back.base.x1+160; //Auto Calculate X2 with String Width
b_back.base.y2 = AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor = WHITE; //Set foreground color
b_back.bgcolor = HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font = 0; //Select Font
b_back.text = "Back"; //Set Text (For formatted strings take sprintf)
b_back.callback = b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
//tft test
tft_draw_pixel(0, 0, BLACK);
tft_draw_pixel(319, 239, BLACK);
tft_draw_pixel(10, 210, BLUE);
tft_draw_pixel(12, 210, BLUE);
tft_draw_rectangle(40, 100, 60, 235, BLUE);
tft_fill_rectangle(100, 215, 200, 225, GREEN);
tft_draw_line(10, 50, 310, 225, RGB(0xFF, 0, 0xFF));
tft_draw_circle(10, 10, 100, RED);
tft_print_line(30, 130, RED, BLUE, 0, "Hallo");
//Area test
a_area.hookedActions = PEN_DOWN | PEN_UP | PEN_MOVE | PEN_ENTER | PEN_LEAVE;
a_area.x1 = 130;
a_area.y1 = 30;
a_area.x2 = 200;
a_area.y2 = 60;
a_area.callback = touchCB;
touch_register_area(&a_area);
//Checkbox test
c_cbox.base.x1 = 220;
c_cbox.base.y1 = 45;
c_cbox.base.x2 = c_cbox.base.x1 + 16;
c_cbox.base.y2 = c_cbox.base.y1 + 16;
c_cbox.fgcolor = GREEN;
c_cbox.checked = true;
c_cbox.callback = checkboxCB;
gui_checkbox_add(&c_cbox);
//Num up down test
n_updown.x = 200;
n_updown.y = 120;
n_updown.fgcolor = RED;
n_updown.value = -3;
n_updown.max = 11;
n_updown.min = -5;
n_updown.callback = n_updown_cb;
gui_numupdown_add(&n_updown);
}
static void leave(void* screen)
{
gui_button_remove(&b_back);
gui_checkbox_remove(&c_cbox);
gui_numupdown_remove(&n_updown);
touch_unregister_area(&a_area);
}
static void update(void* screen)
{
//gui_button_redraw(&b_back); //only needed if button is overdrawn by others
//.... for the other elements as well
}
static SCREEN_STRUCT screen = {
enter,
leave,
update
};
SCREEN_STRUCT* get_screen_guitest()
{
return &screen;
}
-39
View File
@@ -1,39 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_guitest.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
* 2015-05-10 timolang@gmail.com 21edc56 Added doxyfile (doxygen) for the common folder. Started with doxygen comments for app and tft module.
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
*
**************************************************************************************************************************************/
#include "screen.h"
/**
* @addtogroup screens
*/
/*@{*/
/**
* @defgroup guitest Guitest (Screen)
* The Gui-Test Screen tests the gui and the tft module.
*/
/*@{*/
/**
* Returns a pointer to the guitest screen
* \sa gui_screen_navigate
* @return
*/
SCREEN_STRUCT* get_screen_guitest();
/*@}*/
/*@}*/
-199
View File
@@ -1,199 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_main.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
* 2015-05-10 timolang@gmail.com e2bce8f Added filesystem module, tests and implementation for it in emulator.
* 2015-05-15 timolang@gmail.com 27c09ba Redesigned main menu. Moved stuff from pixytest to a new helper file and to the new "photo mode"-screen.
* 2015-05-16 timolang@gmail.com e46314b Added Tracking Screen and implemented "Reference Tracking" and "Color Region Selection"
* 2015-06-01 aaron@duckpond.ch caa7b5c Added IRQ for user button, fixed some touchproblems.
* 2015-06-01 timolang@gmail.com 3155f42 Fixed mainscreen layout.
*
**************************************************************************************************************************************/
#include "screen_main.h"
#include "screen_guitest.h"
#include "screen_pixytest.h"
#include "screen_filetest.h"
#include "screen_photomode.h"
#include "screen_tracking.h"
#include "button.h"
#include "tft.h"
#include "filesystem.h"
BUTTON_STRUCT b_guitest;
BUTTON_STRUCT b_pixytest;
BUTTON_STRUCT b_filetest;
BUTTON_STRUCT b_our_tracking;
BUTTON_STRUCT b_ref_tracking;
BUTTON_STRUCT b_photo_mode;
static void b_our_tracking_cb(void* button)
{
tracking_set_mode(OUR_TRACKING);
gui_screen_navigate(get_screen_tracking());
}
static void b_ref_tracking_cb(void* button)
{
tracking_set_mode(REFERENCE_TRACKING);
gui_screen_navigate(get_screen_tracking());
}
static void b_photo_mode_cb(void* button)
{
gui_screen_navigate(get_screen_photomode());
}
static void b_guitest_cb(void* button)
{
gui_screen_navigate(get_screen_guitest());
}
static void b_filetest_cb(void* button)
{
gui_screen_navigate(get_screen_filetest());
}
static void b_pixytest_cb(void* button)
{
gui_screen_navigate(get_screen_pixytest());
}
static void enter(void* screen)
{
tft_clear(WHITE);
//Heading
tft_print_line(10, 10, BLUE, TRANSPARENT, 1, "Discoverpixy");
tft_draw_line(0, 40, 319, 40, BLACK);
#define X_TAB 97
#define BUTTON_SPACING 7
//First line of buttons
#define Y_FIRST 60
tft_print_line(10, Y_FIRST, BLACK, TRANSPARENT, 0, "Tracking:");
b_our_tracking.base.x1 = X_TAB; //Start X of Button
b_our_tracking.base.y1 = Y_FIRST - 3; //Start Y of Button
b_our_tracking.base.x2 = AUTO; //Auto Calculate X2 with String Width
b_our_tracking.base.y2 = AUTO; //Auto Calculate Y2 with String Height
b_our_tracking.txtcolor = WHITE; //Set foreground color
b_our_tracking.bgcolor = HEX(0xE30535); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_our_tracking.font = 0; //Select Font
b_our_tracking.text = "Our Tracking"; //Set Text (For formatted strings take sprintf)
b_our_tracking.callback = b_our_tracking_cb; //Call b_our_tracking when the button get's pressed
gui_button_add(&b_our_tracking); //Register Button (and run the callback from now on)
b_ref_tracking.base.x1 = b_our_tracking.base.x2 + BUTTON_SPACING;
b_ref_tracking.base.y1 = Y_FIRST - 3;
b_ref_tracking.base.x2 = AUTO;
b_ref_tracking.base.y2 = AUTO;
b_ref_tracking.txtcolor = WHITE;
b_ref_tracking.bgcolor = HEX(0xFF2151);
b_ref_tracking.font = 0;
b_ref_tracking.text = "Ref Tracking";
b_ref_tracking.callback = b_ref_tracking_cb;
gui_button_add(&b_ref_tracking);
//Second line of buttons
#define Y_SECOND Y_FIRST+25
tft_print_line(10, Y_SECOND, BLACK, TRANSPARENT, 0, "Photo mode:");
b_photo_mode.base.x1 = X_TAB;
b_photo_mode.base.y1 = Y_SECOND - 3;
b_photo_mode.base.x2 = AUTO;
b_photo_mode.base.y2 = AUTO;
b_photo_mode.txtcolor = WHITE;
b_photo_mode.bgcolor = HEX(0x21B1FF);
b_photo_mode.font = 0;
b_photo_mode.text = "Photo Mode";
b_photo_mode.callback = b_photo_mode_cb;
gui_button_add(&b_photo_mode);
//Third line of buttons
#define Y_THIRD Y_SECOND+25
tft_print_line(10, Y_THIRD, BLACK, TRANSPARENT, 0, "Tests:");
b_guitest.base.x1 = X_TAB;
b_guitest.base.y1 = Y_THIRD - 3;
b_guitest.base.x2 = AUTO;
b_guitest.base.y2 = AUTO;
b_guitest.txtcolor = BLACK;
b_guitest.bgcolor = HEX(0x00FA21);
b_guitest.font = 0;
b_guitest.text = "Gui & Tft";
b_guitest.callback = b_guitest_cb;
gui_button_add(&b_guitest);
b_pixytest.base.x1 = b_guitest.base.x2 + BUTTON_SPACING;
b_pixytest.base.y1 = Y_THIRD - 3;
b_pixytest.base.x2 = AUTO;
b_pixytest.base.y2 = AUTO;
b_pixytest.txtcolor = BLACK;
b_pixytest.bgcolor = HEX(0x00FA96);
b_pixytest.font = 0;
b_pixytest.text = "Pixy";
b_pixytest.callback = b_pixytest_cb;
gui_button_add(&b_pixytest);
b_filetest.base.x1 = b_pixytest.base.x2 + BUTTON_SPACING;
b_filetest.base.y1 = Y_THIRD - 3;
b_filetest.base.x2 = AUTO;
b_filetest.base.y2 = AUTO;
b_filetest.txtcolor = BLACK;
b_filetest.bgcolor = HEX(0x00FAC4);
b_filetest.font = 0;
b_filetest.text = "File";
b_filetest.callback = b_filetest_cb;
gui_button_add(&b_filetest);
//Bottom line
tft_draw_line(0, 145, 319, 145, BLACK);
tft_print_line(10, 150, BLUE, TRANSPARENT, 0, "Powered by");
tft_draw_bitmap_file_unscaled(10, 165, "pixy_small.bmp");
tft_draw_bitmap_file_unscaled(165, 165, "stm_small.bmp");
}
static void leave(void* screen)
{
gui_button_remove(&b_our_tracking);
gui_button_remove(&b_ref_tracking);
gui_button_remove(&b_photo_mode);
gui_button_remove(&b_guitest);
gui_button_remove(&b_pixytest);
gui_button_remove(&b_filetest);
}
static void update(void* screen)
{
//gui_button_redraw(&b_guitest); //only needed if button is overdrawn by others
}
static SCREEN_STRUCT screen = {
enter,
leave,
update
};
SCREEN_STRUCT* get_screen_main()
{
return &screen;
}
-52
View File
@@ -1,52 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_main.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
* 2015-05-10 timolang@gmail.com 21edc56 Added doxyfile (doxygen) for the common folder. Started with doxygen comments for app and tft module.
* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure
* 2015-05-12 timolang@gmail.com 1402598 Added doxygen stuff for button module and some minor changes to touch, screen_main and tft module.
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
*
**************************************************************************************************************************************/
#include "screen.h"
/**
* @addtogroup app
*/
/*@{*/
/**
* @defgroup screens Screens
* The Screens of the application. \sa \ref screen
*/
/*@}*/
/**
* @addtogroup screens
*/
/*@{*/
/**
* @defgroup main Main (Screen)
* The Main Screen is the start-screen for the application
*/
/*@{*/
/**
* Returns a pointer to the main screen
* \sa gui_screen_navigate
* @return
*/
SCREEN_STRUCT* get_screen_main();
/*@}*/
/*@}*/
-208
View File
@@ -1,208 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_photomode.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-05-15 timolang@gmail.com 27c09ba Redesigned main menu. Moved stuff from pixytest to a new helper file and to the new "photo mode"-screen.
* 2015-05-16 timolang@gmail.com 62006e0 Documented pixy_helper and implemented/finished photo-mode screens! Snap some shots!
* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h
*
**************************************************************************************************************************************/
#include "screen_photomode.h"
#include "screen_photomode_save.h"
#include "button.h"
#include "tft.h"
#include "touch.h"
#include "pixy.h"
#include "system.h"
#include "pixy_frame.h"
static bool pixy_connected = false; //Whether or not the pixy cam is currently connected
static BUTTON_STRUCT b_back; //Button to navigate back
static BUTTON_STRUCT b_save; //Button to save the current image
static TOUCH_AREA_STRUCT a_area; //Touch Area, where the frame is drawn. Used to drag the image around
static bool subMenu = false; //Whether or not we left the current screen for a submenu
//Callback for when the user presses the "back" button
static void b_back_cb(void* button)
{
subMenu = false; //we're not entering a submenu
gui_screen_back(); //navigate back to the previous screen
}
//Callback for when the user presses the "save" button
static void b_save_cb(void* button)
{
subMenu = true; //we're entering a submenu
gui_screen_navigate(get_screen_photomodesave()); //navigate to the save screen
}
static POINT_STRUCT pixy_pos; //The current position of pixy's servos
static POINT_STRUCT old_pos; //The last touch position on the screen
//Callback for when the user drags the image around
static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction)
{
POINT_STRUCT p = touch_get_last_point(); //get the last touched point
switch (triggeredAction) {
case PEN_ENTER:
case PEN_DOWN:
old_pos = p; //If the user "newly" enters the touch area, we set the "last" position to the current
break;
case PEN_MOVE: { //the user is moving around, he entered the screen a while ago (old_pos is set)
int16_t deltaX = p.x - old_pos.x; //Calculate x difference between last and current touch
int16_t deltaY = p.y - old_pos.y; //Calculate y difference between last and current touch
old_pos = p; //store the current touch point for the next time
//printf("%d %d\n",deltaX,deltaY);
if (pixy_connected) {
//Calculate new servo coordinates. 2 is just a proportional factor
int16_t new_x = pixy_pos.x + deltaX * 2;
int16_t new_y = pixy_pos.y - deltaY * 2;
//check limits
if (new_x < 0) {
new_x = 0;
}
if (new_x > 1000) {
new_x = 1000;
}
if (new_y < 0) {
new_y = 0;
}
if (new_y > 1000) {
new_y = 1000;
}
//set pixy_pos so that the main routine can send it to the servos
pixy_pos.x = new_x;
pixy_pos.y = new_y;
}
}
break;
case PEN_UP:
case PEN_LEAVE:
//printf("Leave/up\n");
break;
default:
break;
}
}
//Callback for when the screen is entered/loaded
static void enter(void* screen)
{
tft_clear(WHITE);
tft_print_line(5, 5, BLACK, TRANSPARENT, 0, "Drag the image around and ");
//Back button
b_back.base.x1 = 5; //Start X of Button
b_back.base.y1 = 19; //Start Y of Button
b_back.base.x2 = AUTO; //Auto Calculate X2 with String Width
b_back.base.y2 = AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor = WHITE; //Set foreground color
b_back.bgcolor = HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font = 0; //Select Font
b_back.text = "Back"; //Set Text (For formatted strings take sprintf)
b_back.callback = b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
//Save button
b_save.base.x1 = 190;
b_save.base.y1 = 3;
b_save.base.x2 = AUTO;
b_save.base.y2 = AUTO;
b_save.txtcolor = WHITE;
b_save.bgcolor = HEX(0x1010AE);
b_save.font = 0;
b_save.text = "Save it!";
b_save.callback = b_save_cb;
gui_button_add(&b_save);
//Frame Coordinates: topleft = (1,40); bottomright = (318,238)
//Leave a 10px border for the area
//Area to drag the image around
a_area.hookedActions = PEN_DOWN | PEN_MOVE | PEN_ENTER | PEN_UP | PEN_LEAVE;
a_area.x1 = 11;
a_area.y1 = 50;
a_area.x2 = 308;
a_area.y2 = 228;
a_area.callback = touchCB;
touch_register_area(&a_area);
//Pixy stuff
pixy_connected = (pixy_init() == 0); //try to connect to pixy
if (pixy_connected && !subMenu) { //pixy is connected, but we are not coming from a submenu
pixy_pos.x = pixy_pos.y = 500; //reset servo positions to center
}
}
//Callback for when the screen is left/unloaded
static void leave(void* screen)
{
//remove buttons and touch area.
gui_button_remove(&b_back);
gui_button_remove(&b_save);
touch_unregister_area(&a_area);
}
//Callback for when the screen should be updated
//This is the main loop of the screen. This method will be called repeatedly
static void update(void* screen)
{
//Note: The only way to detect that pixy has been disconnected is if a command fails. There's no pixy_is_connected method yet :'(
if (!pixy_connected) { //Pixy not connected
pixy_close(); //Ensure that all pixy resources are freed (failsafe)
if (pixy_init() == 0) { //try to connect to pixy
pixy_connected = true;
if (!subMenu) { //we're not coming from a submenu
pixy_pos.x = pixy_pos.y = 500; //reset servo positions to center
}
printf("pixy (re)initialized\n");
}
}
if (pixy_connected) { //If we are connected (now)
pixy_service(); //Handle pending pixy events (e.g. color info retrival)
pixy_render_full_frame(1, 40); //render the pixy video at point (1,40)
//set the servo positions to the coordinates form the touch interrupt
pixy_rcs_set_position(0, pixy_pos.x);
pixy_rcs_set_position(1, pixy_pos.y);
}
}
//Declare screen callbacks
static SCREEN_STRUCT screen = {
enter,
leave,
update
};
SCREEN_STRUCT* get_screen_photomode()
{
return &screen;
}
-35
View File
@@ -1,35 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_photomode.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-05-15 timolang@gmail.com 27c09ba Redesigned main menu. Moved stuff from pixytest to a new helper file and to the new "photo mode"-screen.
*
**************************************************************************************************************************************/
#include "screen.h"
/**
* @addtogroup screens
*/
/*@{*/
/**
* @defgroup photomode Photo Mode (Screen)
* The Photo Mode Screen allows taking snapshots of the current pixy cam feed
*/
/*@{*/
/**
* Returns a pointer to the photomode screen
* \sa gui_screen_navigate
* @return
*/
SCREEN_STRUCT* get_screen_photomode();
/*@}*/
/*@}*/
-341
View File
@@ -1,341 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_photomode_save.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-05-16 timolang@gmail.com 62006e0 Documented pixy_helper and implemented/finished photo-mode screens! Snap some shots!
* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h
*
**************************************************************************************************************************************/
#include "screen_photomode_save.h"
#include "filesystem.h"
#include "button.h"
#include "tft.h"
#include "touch.h"
#include "pixy.h"
#include "pixy_frame.h"
#include <stdlib.h>
#include <string.h>
static BUTTON_STRUCT b_back; //Button to navigate back
static TOUCH_AREA_STRUCT a_area; //Touch area to select the save-file
//Callback for when the user presses the "back" button
static void b_back_cb(void* button)
{
gui_screen_back();
}
static int num_files_ok; //number of files into which we can write the image (size, flags ok)
static enum {init, error, showlist, picking, saving, done} state; //Current state of the screen state machine
static int fontheight; //The space between one line of text to the next
static int liststart; //The y-Coordinate of the Start of the File-List
static const char* picked_file; //The filename picked by the user, to save the image to
//Linked list structure to save all files which are suitable for saving.
typedef struct FILE_LIST_ENTRY_S {
char* filename; //Name of the file
struct FILE_LIST_ENTRY_S* next; //Pointer to the next entry in the list or NULL
} FILE_LIST_ENTRY;
static FILE_LIST_ENTRY* files_ok; //Pointer to the head of the list
//Callback for when the user selects a file to save the image into
static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction)
{
int y = touch_get_last_point().y - liststart; //Calculate the y-Coordinate of the touch point relative to the start of the file-list
int elem = y / fontheight; //Calculate the file index
if (elem < 0 | elem >= num_files_ok) {
return; //Check if the file index is valid (0,1,..,num_files_ok-1)
}
//Search for the corresponding entry in the linked list
FILE_LIST_ENTRY* current_entry = files_ok; //Start walking through the list, starting by the head of the list
for (int i = 0; i < elem; i++) { //Until we have reached the file (index)
current_entry = current_entry->next; //traverse to the next file
}
picked_file = current_entry->filename; //save the picked filename. It will be used by the statemachine in the main loop
touch_unregister_area(&a_area); //unregister the touch area, we no longer need it. No more interrupts will be fired.
state = saving; //Change the state of the statemachine
}
//Text-Lines to show if we have no matching files (num_files_ok==0)
static const char* nomatch_text [] = {
"Due to limitations of the filesystem",
"implementation you can only write to",
"existing files.",
"",
"The files need to have a .bmp",
"extension and must be at least",
"189410 bytes (185kb) large.",
"Unfortunately there were no such",
"files found in the root directory.",
"",
"Please create some files and come",
"back again.",
NULL
};
//Bitmap header for a 318x198x24bit windows bitmap. data starts at 0x7A (= after this header)
//This header has been taken from a white bitmap saved with gimp.
//Wikipedia has a pretty good description on the header: http://de.wikipedia.org/wiki/Windows_Bitmap
static unsigned char bmpheader_data[0x7A] = {
0x42, 0x4d, 0xe2, 0xe3, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x00,
0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00, 0xc6, 0x00,
0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xe3,
0x02, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
//Callback for when the screen is entered/loaded
static void enter(void* screen)
{
tft_clear(WHITE);
#define X_OFS 5
//Back button
b_back.base.x1 = X_OFS; //Start X of Button
b_back.base.y1 = 210; //Start Y of Button
b_back.base.x2 = AUTO; //Auto Calculate X2 with String Width
b_back.base.y2 = AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor = WHITE; //Set foreground color
b_back.bgcolor = HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font = 0; //Select Font
b_back.text = "Back"; //Set Text (For formatted strings take sprintf)
b_back.callback = b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
state = init; //Start with the init state
fontheight = tft_font_height(0) + 2; //Save the height of the used font, for fast access
files_ok = NULL; //initialize the linked list with 0 elements
num_files_ok = 0; //we have zero! elements
}
//Callback for when the screen should be updated
//This is the main loop of the screen. This method will be called repeatedly
static void update(void* screen)
{
switch (state) {
case init: { //Init State: The user just entered the screen
DIRECTORY_STRUCT* dir = filesystem_dir_open("."); //open root directory
if (dir == NULL) { //error while opening root directory
tft_print_line(X_OFS, 5, BLACK, TRANSPARENT, 0, "Error accessing Filesystem");
state = error;
break;
}
bool nomatch = true; //whether or not we have zero files which are suitable for saving
for (int i = 0; i < dir->num_files; i++) { //walk through all files in the directory
FILE_STRUCT* file = &(dir->files[i]); //Pointer to the current file/subdirectory
//Ignore directories, archives, hidden files, system files and files we cannot write to
if (file->fattrib & (F_SYS | F_HID | F_ARC | F_DIR | F_RDO)) {
continue;
}
//ignore files which are not large enough
if (file->fsize < 189410) {
continue; //size taken from an example bitmap (318x198x24)
}
nomatch = false; //at least one file matches
break;
}
if (nomatch) { //not one file is suitable for writing
int y = 5; //y-Coordinate where to start writing the error text
int i = 0;
while (nomatch_text[i] != NULL) { //for every line in the big error array
//Write the line's text and go to the next line
tft_print_line(X_OFS, y + i * fontheight, BLACK, TRANSPARENT, 0, nomatch_text[i]);
i++;
}
state = error;
} else { //we have a least one suitable file
state = showlist;
}
filesystem_dir_close(dir); //free directory struct
}
break;
case showlist: { //Show List State: Where we load and present the suitable file's to the user in a list
DIRECTORY_STRUCT* dir2 = filesystem_dir_open("."); //Open the directory again
if (dir2 == NULL) {
return; //Error on opening? This should never happen, since it's handled in the previous state
}
int y = 5; //y-Coordinate where to start drawing/writing text/list-elements
tft_print_line(X_OFS, y, BLACK, TRANSPARENT, 0, "Pick a file to save the image to");
y += fontheight + 5;
tft_print_line(X_OFS, y, BLUE, TRANSPARENT, 0, "Name Modified Size");
y += fontheight;
liststart = y; //store the y coordinate of the start of the list away (used in toucharea callback)
num_files_ok = 0; //we start with 0 matching files
FILE_LIST_ENTRY* current_entry = NULL; //We start with an empty list
for (int i = 0; i < dir2->num_files && num_files_ok < 10; i++) { //go through all the files of the directory, abort if we have 10 matches
FILE_STRUCT* file = &(dir2->files[i]);
//Ignore directories, archives, hidden files, system files and files we cannot write to
if (file->fattrib & (F_SYS | F_HID | F_ARC | F_DIR | F_RDO)) {
continue;
}
//ignore files which are not large enough
if (file->fsize < 189410) {
continue; //size taken from an example bitmap (318x198x24)
}
//Print out filename, modified date,time and file size
tft_print_formatted(X_OFS, y, BLACK,
TRANSPARENT, 0, "%-16s %02u.%02u.%02u %02u:%02u:%02u %u",
file->fname,
file->fdate.day,
file->fdate.month,
(file->fdate.year + 1980) % 100,
file->ftime.hour,
file->ftime.min,
file->ftime.sec * 2,
file->fsize);
if (current_entry == NULL) { //The list is empty
current_entry = malloc(sizeof(FILE_LIST_ENTRY)); //create new entry
files_ok = current_entry; //assign it to the list head
} else { //there's a least one entry in the list
current_entry->next = malloc(sizeof(FILE_LIST_ENTRY)); //append entry to previous entry
current_entry = current_entry->next; //newly created entry is the current now.
}
current_entry->next = NULL; //we're at the end of the list (for now)
current_entry->filename = malloc(strlen(file->fname) + 1); //allocate space for the filename + zero-termination
strcpy(current_entry->filename, file->fname); //copy filename (so that we can close the directory after scanning)
//since we have found a suitable file we need to increment the position in the list
num_files_ok++;
y += fontheight;
}
//Touch area for file-selection (in the list)
a_area.hookedActions = PEN_UP; //we're only interested in PEN_UP events
a_area.x1 = X_OFS; //Left border
a_area.y1 = liststart; //Start where the list started
a_area.x2 = 320 - X_OFS; //Right border
a_area.y2 = liststart + fontheight * num_files_ok; //stop at the end of the list
a_area.callback = touchCB; //execute our callback when PEN_UP occurs
touch_register_area(&a_area); //register the touch area and receive events from now on
filesystem_dir_close(dir2); //we no longer need the directory struct, since we have our own linked list now
state = picking;
}
break;
case picking: //Picking State: Where we wait on the users file choice
pixy_service(); //Handle pending pixy events
//do nothing and wait on user to pick a file
break;
case saving: { //Saving State: Where we save the image to the selected file
FILE_HANDLE* file = filesystem_file_open(picked_file); //try to open the selected file
if (file == NULL) { //opening the file failed
tft_print_formatted(X_OFS, 190, BLUE, TRANSPARENT, 0, "Could not open %s", picked_file);
state = error;
break;
}
filesystem_file_seek(file, 0); //seek to the start of the file (optional?)
if (filesystem_file_write(file, bmpheader_data, 0x7A) != F_OK) { //Writing the header failed
tft_print_formatted(X_OFS, 190, BLUE, TRANSPARENT, 0, "Error while writing to %s", picked_file);
filesystem_file_close(file);
state = error;
break;
}
if (pixy_save_full_frame(file) != 0) { //Writing the imagedata failed
tft_print_formatted(X_OFS, 190, BLUE, TRANSPARENT, 0, "Error while writing to %s", picked_file);
filesystem_file_close(file);
state = error;
break;
}
//if we reach this point, we have written all data out successfully
filesystem_file_close(file); //close/finalize the file
tft_print_formatted(X_OFS, 190, BLUE, TRANSPARENT, 0, "Image saved to %s", picked_file);
state = done;
}
break;
case error: //Error State: Where we show an error message and leave the user no other choice than to click the backbutton
case done: //Done State: When saving the file was successful
pixy_service(); //Handle pending pixy events
//wait on user to click the back button
break;
}
}
//Callback for when the screen is left/unloaded
static void leave(void* screen)
{
gui_button_remove(&b_back); //Remove/Free the back button
if (state == picking) { //The user left the screen in the "picking"-phase
touch_unregister_area(&a_area); //remove the touch area (for the list)
}
if (state == picking || state == saving || state == done) { //the user left the screen after we created the linked list
//Iterate through the linked list and free all resources
FILE_LIST_ENTRY* current_entry = files_ok; //start with the list head
while (current_entry != NULL) { //while we're not at the end
FILE_LIST_ENTRY* temp = current_entry->next; //save the next pointer because we free the current element on the next line
free((void*)(current_entry->filename)); //free filename
free(current_entry); //free element itself
current_entry = temp; //advance
}
}
}
//Declare screen callbacks
static SCREEN_STRUCT screen = {
enter,
leave,
update
};
SCREEN_STRUCT* get_screen_photomodesave()
{
return &screen;
}
-35
View File
@@ -1,35 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_photomode_save.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-05-16 timolang@gmail.com 62006e0 Documented pixy_helper and implemented/finished photo-mode screens! Snap some shots!
*
**************************************************************************************************************************************/
#include "screen.h"
/**
* @addtogroup screens
*/
/*@{*/
/**
* @defgroup photomodesave Photo Mode Save (Screen)
* The Photo Mode Save Screen helps the user saving a file to the filesystem
*/
/*@{*/
/**
* Returns a pointer to the photomode save screen
* \sa gui_screen_navigate
* @return
*/
SCREEN_STRUCT* get_screen_photomodesave();
/*@}*/
/*@}*/
-377
View File
@@ -1,377 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_pixytest.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
* 2015-05-02 timolang@gmail.com 3281616 Added some more touch functions. Improved pixy test. Drag the Image around!
* 2015-05-09 timolang@gmail.com 0b5173e Added reference tracking.
* 2015-05-15 timolang@gmail.com 27c09ba Redesigned main menu. Moved stuff from pixytest to a new helper file and to the new "photo mode"-screen.
* 2015-05-25 timolang@gmail.com 6a61769 Reimplemented pixytest screen. Added a lot of Test-Buttons.
* 2015-06-01 aaron@duckpond.ch caa7b5c Added IRQ for user button, fixed some touchproblems.
* 2015-06-03 timolang@gmail.com 74aa186 Made pixy_test screen working again. Had to disable pixy_service. Recalibrated initial touch values.
* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h
*
**************************************************************************************************************************************/
#include "screen_pixytest.h"
#include "button.h"
#include "numupdown.h"
#include "tft.h"
#include "touch.h"
#include "pixy.h"
#include "system.h"
#include "pixy_frame.h"
static volatile enum {detecting, idle, update_servos, update_ledcolor, update_ledcurrent} state; //Current state of the screen state machine
static BUTTON_STRUCT b_back;
static BUTTON_STRUCT b_servos_center;
static BUTTON_STRUCT b_servos_topleft;
static BUTTON_STRUCT b_servos_topright;
static BUTTON_STRUCT b_servos_bottomleft;
static BUTTON_STRUCT b_servos_bottomright;
static uint16_t servo_x;
static uint16_t servo_y;
static BUTTON_STRUCT b_led_off;
static BUTTON_STRUCT b_led_white;
static BUTTON_STRUCT b_led_red;
static BUTTON_STRUCT b_led_green;
static BUTTON_STRUCT b_led_blue;
static uint32_t led_color;
static uint32_t led_maxcurrent;
static NUMUPDOWN_STRUCT n_led_powerlimit;
static void b_back_cb(void* button)
{
gui_screen_back();
}
static void b_servos_center_cb(void* button)
{
if (state == idle) {
servo_x = 500;
servo_y = 500;
state = update_servos;
}
}
static void b_servos_topleft_cb(void* button)
{
if (state == idle) {
servo_x = 0;
servo_y = 0;
state = update_servos;
}
}
static void b_servos_topright_cb(void* button)
{
if (state == idle) {
servo_x = 1000;
servo_y = 0;
state = update_servos;
}
}
static void b_servos_bottomleft_cb(void* button)
{
if (state == idle) {
servo_x = 0;
servo_y = 1000;
state = update_servos;
}
}
static void b_servos_bottomright_cb(void* button)
{
if (state == idle) {
servo_x = 1000;
servo_y = 1000;
state = update_servos;
}
}
static void b_led_off_cb(void* button)
{
if (state == idle) {
led_color = 0x000000;
state = update_ledcolor;
}
}
static void b_led_white_cb(void* button)
{
if (state == idle) {
led_color = 0xFFFFFF;
state = update_ledcolor;
}
}
static void b_led_red_cb(void* button)
{
if (state == idle) {
led_color = 0xFF0000;
state = update_ledcolor;
}
}
static void b_led_green_cb(void* button)
{
if (state == idle) {
led_color = 0x00FF00;
state = update_ledcolor;
}
}
static void b_led_blue_cb(void* button)
{
if (state == idle) {
led_color = 0x0000FF;
state = update_ledcolor;
}
}
static void n_led_powerlimit_cb(void* numupdown, int16_t value)
{
if (state == idle) {
led_maxcurrent = value;
state = update_ledcurrent;
}
}
static void enter(void* screen)
{
tft_clear(WHITE);
//Back button
b_back.base.x1 = 10; //Start X of Button
b_back.base.y1 = 210; //Start Y of Button
b_back.base.x2 = AUTO; //Auto Calculate X2 with String Width
b_back.base.y2 = AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor = WHITE; //Set foreground color
b_back.bgcolor = HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font = 0; //Select Font
b_back.text = "Back"; //Set Text (For formatted strings take sprintf)
b_back.callback = b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
//Servo stuff
#define SERVO_BUTTON_Y 10
#define SERVO_BUTTON_SPACING 5
tft_print_line(5, SERVO_BUTTON_Y, BLACK, TRANSPARENT, 0, "Servos:");
b_servos_center.base.x1 = 55;
b_servos_center.base.y1 = SERVO_BUTTON_Y - 3;
b_servos_center.base.x2 = AUTO;
b_servos_center.base.y2 = AUTO;
b_servos_center.txtcolor = WHITE;
b_servos_center.bgcolor = HEX(0xAE1010);
b_servos_center.font = 0;
b_servos_center.text = "Center";
b_servos_center.callback = b_servos_center_cb;
gui_button_add(&b_servos_center);
b_servos_topleft.base.x1 = b_servos_center.base.x2 + SERVO_BUTTON_SPACING;
b_servos_topleft.base.y1 = SERVO_BUTTON_Y - 3;
b_servos_topleft.base.x2 = AUTO;
b_servos_topleft.base.y2 = AUTO;
b_servos_topleft.txtcolor = WHITE;
b_servos_topleft.bgcolor = HEX(0xAE1010);
b_servos_topleft.font = 0;
b_servos_topleft.text = "ToLe";
b_servos_topleft.callback = b_servos_topleft_cb;
gui_button_add(&b_servos_topleft);
b_servos_topright.base.x1 = b_servos_topleft.base.x2 + SERVO_BUTTON_SPACING;
b_servos_topright.base.y1 = SERVO_BUTTON_Y - 3;
b_servos_topright.base.x2 = AUTO;
b_servos_topright.base.y2 = AUTO;
b_servos_topright.txtcolor = WHITE;
b_servos_topright.bgcolor = HEX(0xAE1010);
b_servos_topright.font = 0;
b_servos_topright.text = "ToRi";
b_servos_topright.callback = b_servos_topright_cb;
gui_button_add(&b_servos_topright);
b_servos_bottomleft.base.x1 = b_servos_topright.base.x2 + SERVO_BUTTON_SPACING;
b_servos_bottomleft.base.y1 = SERVO_BUTTON_Y - 3;
b_servos_bottomleft.base.x2 = AUTO;
b_servos_bottomleft.base.y2 = AUTO;
b_servos_bottomleft.txtcolor = WHITE;
b_servos_bottomleft.bgcolor = HEX(0xAE1010);
b_servos_bottomleft.font = 0;
b_servos_bottomleft.text = "BoLe";
b_servos_bottomleft.callback = b_servos_bottomleft_cb;
gui_button_add(&b_servos_bottomleft);
b_servos_bottomright.base.x1 = b_servos_bottomleft.base.x2 + SERVO_BUTTON_SPACING;
b_servos_bottomright.base.y1 = SERVO_BUTTON_Y - 3;
b_servos_bottomright.base.x2 = AUTO;
b_servos_bottomright.base.y2 = AUTO;
b_servos_bottomright.txtcolor = WHITE;
b_servos_bottomright.bgcolor = HEX(0xAE1010);
b_servos_bottomright.font = 0;
b_servos_bottomright.text = "BoRi";
b_servos_bottomright.callback = b_servos_bottomright_cb;
gui_button_add(&b_servos_bottomright);
//Led Color stuff
#define LED_COLOR_BUTTON_Y 35
#define LED_COLOR_BUTTON_SPACING 5
tft_print_line(5, LED_COLOR_BUTTON_Y, BLACK, TRANSPARENT, 0, "Led Color:");
b_led_off.base.x1 = 85;
b_led_off.base.y1 = LED_COLOR_BUTTON_Y - 3;
b_led_off.base.x2 = AUTO;
b_led_off.base.y2 = AUTO;
b_led_off.txtcolor = WHITE;
b_led_off.bgcolor = BLACK;
b_led_off.font = 0;
b_led_off.text = "Off";
b_led_off.callback = b_led_off_cb;
gui_button_add(&b_led_off);
b_led_white.base.x1 = b_led_off.base.x2 + LED_COLOR_BUTTON_SPACING;
b_led_white.base.y1 = LED_COLOR_BUTTON_Y - 3;
b_led_white.base.x2 = AUTO;
b_led_white.base.y2 = AUTO;
b_led_white.txtcolor = BLACK;
b_led_white.bgcolor = HEX(0xEEEEEE);
b_led_white.font = 0;
b_led_white.text = "White";
b_led_white.callback = b_led_white_cb;
gui_button_add(&b_led_white);
b_led_red.base.x1 = b_led_white.base.x2 + LED_COLOR_BUTTON_SPACING;
b_led_red.base.y1 = LED_COLOR_BUTTON_Y - 3;
b_led_red.base.x2 = AUTO;
b_led_red.base.y2 = AUTO;
b_led_red.txtcolor = WHITE;
b_led_red.bgcolor = HEX(0xEE0000);
b_led_red.font = 0;
b_led_red.text = "Red";
b_led_red.callback = b_led_red_cb;
gui_button_add(&b_led_red);
b_led_green.base.x1 = b_led_red.base.x2 + LED_COLOR_BUTTON_SPACING;
b_led_green.base.y1 = LED_COLOR_BUTTON_Y - 3;
b_led_green.base.x2 = AUTO;
b_led_green.base.y2 = AUTO;
b_led_green.txtcolor = WHITE;
b_led_green.bgcolor = HEX(0x00EE00);
b_led_green.font = 0;
b_led_green.text = "Green";
b_led_green.callback = b_led_green_cb;
gui_button_add(&b_led_green);
b_led_blue.base.x1 = b_led_green.base.x2 + LED_COLOR_BUTTON_SPACING;
b_led_blue.base.y1 = LED_COLOR_BUTTON_Y - 3;
b_led_blue.base.x2 = AUTO;
b_led_blue.base.y2 = AUTO;
b_led_blue.txtcolor = WHITE;
b_led_blue.bgcolor = HEX(0x0000EE);
b_led_blue.font = 0;
b_led_blue.text = "Blue";
b_led_blue.callback = b_led_blue_cb;
gui_button_add(&b_led_blue);
//Led MaxPower stuff
#define LED_POWER_BUTTON_Y 70
tft_print_line(5, LED_POWER_BUTTON_Y, BLACK, TRANSPARENT, 0, "Led Maximum Current:");
//Num up down test
n_led_powerlimit.x = 160;
n_led_powerlimit.y = LED_POWER_BUTTON_Y - 7;
n_led_powerlimit.fgcolor = WHITE;
n_led_powerlimit.value = 10;
n_led_powerlimit.max = 40;
n_led_powerlimit.min = 0;
n_led_powerlimit.callback = n_led_powerlimit_cb;
gui_numupdown_add(&n_led_powerlimit);
state = detecting;
}
static void leave(void* screen)
{
gui_button_remove(&b_back);
gui_button_remove(&b_servos_center);
gui_button_remove(&b_servos_topleft);
gui_button_remove(&b_servos_topright);
gui_button_remove(&b_servos_bottomleft);
gui_button_remove(&b_servos_bottomright);
gui_button_remove(&b_led_off);
gui_button_remove(&b_led_white);
gui_button_remove(&b_led_red);
gui_button_remove(&b_led_green);
gui_button_remove(&b_led_blue);
gui_numupdown_remove(&n_led_powerlimit);
}
static void update(void* screen)
{
switch (state) {
case detecting: //Detecting State: Where we try to connect to the pixy
if (pixy_init() == 0) { //Pixy connection ok
int32_t response;
int return_value;
return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS);
pixy_led_set_max_current(10);
state = idle; //Go to next state
}
break;
case idle:
pixy_service();
break;
case update_servos:
pixy_rcs_set_position(0, servo_x);
pixy_rcs_set_position(1, servo_y);
state = idle;
break;
case update_ledcolor: {
int32_t response;
int return_value;
return_value = pixy_command("led_set", INT32(led_color), END_OUT_ARGS, &response, END_IN_ARGS);
state = idle;
}
break;
case update_ledcurrent:
pixy_led_set_max_current(led_maxcurrent);
state = idle;
break;
}
}
static SCREEN_STRUCT screen = {
enter,
leave,
update
};
SCREEN_STRUCT* get_screen_pixytest()
{
return &screen;
}
-37
View File
@@ -1,37 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_pixytest.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
* 2015-05-10 timolang@gmail.com 21edc56 Added doxyfile (doxygen) for the common folder. Started with doxygen comments for app and tft module.
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
*
**************************************************************************************************************************************/
#include "screen.h"
/**
* @addtogroup screens
*/
/*@{*/
/**
* @defgroup pixytest Pixytest (Screen)
* The Pixy-Test Screen tests the pixy module.
*/
/*@{*/
/**
* Returns a pointer to the pixytest screen
* \sa gui_screen_navigate
* @return
*/
SCREEN_STRUCT* get_screen_pixytest();
/*@}*/
/*@}*/
-421
View File
@@ -1,421 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_tracking.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-05-16 timolang@gmail.com e46314b Added Tracking Screen and implemented "Reference Tracking" and "Color Region Selection"
* 2015-05-25 timolang@gmail.com 8088014 Updated Tracking Screen so that the implementations are separated into different method groups.
* 2015-06-06 aaron@duckpond.ch 8c264c2 Comment refactoring, updated PID values
* 2015-06-06 aaron@duckpond.ch a04cda9 Refactured comments and implemented a bugfix for the PID controller
* 2015-06-07 aaron@duckpond.ch 802d3df Fixed pid controller and refactored code
* 2015-06-07 aaron@duckpond.ch 3d98ca9 Minor changes
* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h
*
**************************************************************************************************************************************/
#include "screen_tracking.h"
#include "pixy_control.h"
#include "button.h"
#include "checkbox.h"
#include "tft.h"
#include "touch.h"
#include "pixy.h"
#include "system.h"
#include "pixy_frame.h"
static BUTTON_STRUCT b_back; //Button to navigate back
static BUTTON_STRUCT b_select; //Button to start the color region selection
static CHECKBOX_STRUCT c_frame_toggle; //Checkbox to toggle video data on/off
static TOUCH_AREA_STRUCT a_area; //Touch area for the color region selection
//Callback for when the user presses the "back" button
static void b_back_cb(void* button)
{
gui_screen_back(); //navigate back to the previous screen
}
static volatile bool frame_visible = false; //Whether or not the video data should be displayed
static void c_frame_toggle_cb(void* checkbox, bool checked)
{
frame_visible = checked; //Set the visibility of the frame to the checked state of the checkbox
//Frame will be drawn in the main loop below
}
static enum {detecting, init, tracking, preselecting, abortselecting, selecting, selected, error} state; //Current state of the screen state machine
static POINT_STRUCT point1; //First point of the rectangle selected by the user (color region selection)
static POINT_STRUCT point2; //End point of the rectangle selected by the user (color region selection)
static bool point1_valid; //Whether or not we have a valid first point
//Callback for when the user presses the "select color" button
static void b_select_cb(void* button)
{
if (state == selecting) { //we're currently selecting a color region
state = abortselecting; //Abort selecting!!
} else if (state == tracking) { //we're currently watching the tracking
state = preselecting; //start selecting
}
}
//Video Region properties
//The camera records with 320*200px, but we need to keep a 1px border because of color interpolation (bayer format)
#define FRAME_START_X 1 //x-Coordinate of the top-left point of the frame rectangle on display
#define FRAME_START_Y 41 //y-Coordinate of the top-left point of the frame rectangle on display
#define FRAME_WIDTH 318 //Width of the video frame
#define FRAME_HEIGHT 198 //Height of the video frame
#define FRAME_END_X FRAME_START_X +FRAME_WIDTH-1 //x-Coordinate of the bottom-right point of the frame rectangle
#define FRAME_END_Y FRAME_START_Y +FRAME_HEIGHT-1 //y-Coordinate of the bottom-right point of the frame rectangle
//Callback for when the user touches the frame area to select a color region.
//Note: It doesn't matter in which direction the user draws the rectangle, we'll normalize the coordinates later
static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction)
{
POINT_STRUCT p = touch_get_last_point();
switch (triggeredAction) {
case PEN_DOWN: //The user just put down the pen
point1.x = p.x - FRAME_START_X; //Calculate x-Coordinate relative to frame start
point1.y = p.y - FRAME_START_Y; //Calculate y-Coordinate relative to frame start
point1_valid = true; //The point1 is now valid
break;
case PEN_UP: //The user took the pen away
if (point1_valid) { //only execute if point1 is valid
point2.x = p.x - FRAME_START_X; //Calculate x-Coordinate relative to frame start
point2.y = p.y - FRAME_START_Y; //Calculate y-Coordinate relative to frame start
state = selected;
}
break;
}
}
//Prototype for tracking start/stop methods
typedef void (*TRACKING_VOID_CALLBACK)(void* tracking_config);
//Prototype for tracking update method
typedef void (*TRACKING_BLOCK_CALLBACK)(void* tracking_config, struct Block* blocks, int num_blocks);
//Structure to save callbacks and settings of a tracking implementation
typedef struct {
TRACKING_VOID_CALLBACK start;
TRACKING_VOID_CALLBACK stop;
TRACKING_BLOCK_CALLBACK update;
} TRACKING_CONFIG_STRUCT;
//Methods for our tracking implementation ahead
static int16_t servo_x = 0;
static int16_t servo_y = 0;
//Method/Callback to start our tracking
void tracking_our_start(void* tracking_config)
{
//Activate pixy's data send program
int32_t response;
int return_value;
servo_x = servo_y = 500; // set a default value of 500
pixy_rcs_set_position(0, servo_x); // set default
pixy_rcs_set_position(1, servo_y); // set default
return_value = pixy_command("runprog", INT8(0), END_OUT_ARGS, &response, END_IN_ARGS);
}
//Method/Callback to stop our tracking
void tracking_our_stop(void* tracking_config)
{
//Stop pixy's data send programm
int32_t response;
int return_value;
return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS);
}
//Method/Callback to calculate one step of our tracking
void tracking_our_update(void* tracking_config, struct Block* blocks, int num_blocks)
{
if (num_blocks <= 0) { // Check if there are blocks available
return; // When there are none, do nothing
}
uint16_t x = blocks[0].x; // Get x coordinate of the biggest object
uint16_t y = blocks[0].y; // Get y coordinate of the biggest object
int16_t xset = 0;
int16_t yset = 0;
xset = (servo_x + pixy_PID_X((FRAME_WIDTH / 2), x)); // calculate the PID output for x
yset = (servo_y - pixy_PID_Y((FRAME_HEIGHT / 2), y)); // calculate the PID output for y
xset = (xset < 0) ? 0 : xset; // x lower boundary check
xset = (xset > 1000) ? 1000 : xset; // x upper boundary check
yset = (yset < 0) ? 0 : yset; // y lower boundary check
yset = (yset > 1000) ? 1000 : yset; // y upper boundary check
servo_x = xset; // update the global, static variable for x
servo_y = yset; // update the global, statuc variable for y
pixy_rcs_set_position(0, servo_x); // set the new x position
pixy_rcs_set_position(1, servo_y); // set the new y position
}
//Variable which stores all the callbacks and settings for our tracking implementation
static TRACKING_CONFIG_STRUCT tracking_our = {
tracking_our_start,
tracking_our_stop,
tracking_our_update
};
//Methods for reference tracking implementation ahead
//Method/Callback to start reference tracking
void tracking_reference_start(void* tracking_config)
{
//Run reference tracking
int32_t response;
int return_value;
return_value = pixy_command("runprog", INT8(2), END_OUT_ARGS, &response, END_IN_ARGS);
}
//Method/Callback to stop reference tracking
void tracking_reference_stop(void* tracking_config)
{
//Stop reference tracking
int32_t response;
int return_value;
return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS);
}
//Method/Callback to calculate one step of the reference tracking
void tracking_reference_update(void* tracking_config, struct Block* blocks, int num_blocks)
{
//Nothing to do here. Pixy does it all.
}
//Variable which stores all the callbacks and settings for the reference tracking implementation
static TRACKING_CONFIG_STRUCT tracking_reference = {
tracking_reference_start,
tracking_reference_stop,
tracking_reference_update
};
//Pointer to the currently active tracking implementation. See also tracking_set_mode
static TRACKING_CONFIG_STRUCT* tracking_current;
//Method to set the current tracking implementation. This function is exported and should be called before getting the screen
void tracking_set_mode(enum Tracking_Implementation impl)
{
//Depending on the enum value let tracking_current point to a different setting/callback structure
switch (impl) {
case OUR_TRACKING:
tracking_current = &tracking_our;
break;
case REFERENCE_TRACKING:
tracking_current = &tracking_reference;
break;
default:
tracking_current = NULL;
break;
}
}
//Callback for when the screen is entered/loaded
static void enter(void* screen)
{
tft_clear(WHITE);
//"Back" button
b_back.base.x1 = 5; //Start X of Button
b_back.base.y1 = 5; //Start Y of Button
b_back.base.x2 = AUTO; //Auto Calculate X2 with String Width
b_back.base.y2 = AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor = WHITE; //Set foreground color
b_back.bgcolor = HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font = 0; //Select Font
b_back.text = "Back"; //Set Text (For formatted strings take sprintf)
b_back.callback = b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
//"Select color" button
b_select.base.x1 = 150;
b_select.base.y1 = 5;
b_select.base.x2 = AUTO;
b_select.base.y2 = AUTO;
b_select.txtcolor = WHITE;
b_select.bgcolor = HEX(0xAE1010);
b_select.font = 0;
b_select.text = "Select Color";
b_select.callback = b_select_cb;
gui_button_add(&b_select);
//"Frame visible" checkbox
c_frame_toggle.base.x1 = 50;
c_frame_toggle.base.x2 = 50 + 16;
c_frame_toggle.base.y1 = 5;
c_frame_toggle.base.y2 = 5 + 16;
c_frame_toggle.checked = frame_visible;
c_frame_toggle.fgcolor = CHECKBOX_WIN_FG_COLOR;
c_frame_toggle.callback = c_frame_toggle_cb;
gui_checkbox_add(&c_frame_toggle);
tft_print_line(73, 8, BLACK, TRANSPARENT, 0, "Show Video");
//Area to select a "color region"
a_area.hookedActions = PEN_DOWN | PEN_UP;
a_area.x1 = FRAME_START_X;
a_area.y1 = FRAME_START_Y;
a_area.x2 = FRAME_END_X;
a_area.y2 = FRAME_END_Y;
a_area.callback = touchCB;
//Do not register it here, we do that later
if (tracking_current == NULL) {
state = error;
} else {
state = detecting; //Start with the detecting state
}
}
//Callback for when the screen is left/unloaded
static void leave(void* screen)
{
//Remove buttons and checkbox
gui_button_remove(&b_back);
gui_button_remove(&b_select);
gui_checkbox_remove(&c_frame_toggle);
if (state == selecting) { //the user left the screen in the "selecting" phase
touch_unregister_area(&a_area); //remove the touch area
}
if (state == tracking) { //the user left the screen in the "tracking" phase
tracking_current->stop(tracking_current); //stop tracking
pixy_led_set_RGB(0, 0, 0);
}
}
//Callback for when the screen should be updated
//This is the main loop of the screen. This method will be called repeatedly
static void update(void* screen)
{
switch (state) {
case detecting: //Detecting State: Where we try to connect to the pixy
if (pixy_init() == 0) { //Pixy connection ok
state = init; //Go to next state
}
break;
case init: //Init State: Where we start the tracking
tracking_current->start(tracking_current);
state = tracking;
break;
case tracking: //Tracking state: Where we render the frame and the tracked objects
pixy_service(); //Receive events (e.g. block-data) from pixy
if (pixy_blocks_are_new()) { //There are new blocks available
if (frame_visible) { //If the user want's us to draw the video data
pixy_render_full_frame(FRAME_START_X, FRAME_START_Y);
} else { //the user want's a colored background
tft_fill_rectangle(FRAME_START_X, FRAME_START_Y, FRAME_END_X, FRAME_END_Y, RGB(200, 200, 200));
}
#define BLOCK_BUFFER_SIZE 5 //The maximum amount of blocks that we want to receive
struct Block blocks[BLOCK_BUFFER_SIZE]; //Storage to receive blocks from pixy
int blocks_received = pixy_get_blocks(BLOCK_BUFFER_SIZE, blocks); //Try to receive up to BLOCK_BUFFER_SIZE Blocks from pixy
if (blocks_received >= 0) { //block receiving ok
tracking_current->update(tracking_current, blocks, blocks_received); //apply tracking
//Draw blocks
for (int i = 0; i < blocks_received; i++) { //for each received block
struct Block* block = &(blocks[i]);
//block.x and block.y are the center coordinates of the object relative to the camera origin.
uint16_t x = block->x - 1 + FRAME_START_X - block->width / 2; //Calculate x-Coordinate on the display
uint16_t y = block->y - 1 + FRAME_START_Y - block->height / 2; //Calculate y-Coordinate on the display
tft_draw_rectangle(x, y, x + block->width - 1, y + block->height - 1, WHITE); //Draw a white rectangle
}
}
}
break;
case preselecting: { //Pre-Selecting State: Where we set up the color region selection
tracking_current->stop(tracking_current); //Stop tracking
pixy_render_full_frame(FRAME_START_X, FRAME_START_Y); //Render one frame
touch_register_area(&a_area); //Register touch area and receive events from now on
point1_valid = false; //we start with an invalid point1
b_select.text = "Abort"; //Change the button text to "Abort"
gui_button_redraw(&b_select); //redraw button
state = selecting; //The user can now select a region
}
break;
case selected: { //Selected State: Where we send the users selection to pixy
//Ensure that (x1,y1) represent the top-left point and (x2,y2) the bottom-right.
unsigned int tmp;
if (point1.x > point2.x) {
tmp = point1.x;
point1.x = point2.x;
point2.x = tmp;
}
if (point1.y > point2.y) {
tmp = point1.y;
point1.y = point2.y;
point2.y = tmp;
}
//Send pixy the selected region
pixy_cc_set_region(1, point1.x, point1.y, point2.x - point1.x, point2.y - point1.y);
}
//no break here: We want the following code to be executed as well
case abortselecting: { //Abort-Selecting State: Where we deinitialize the stuff we used for region selection
touch_unregister_area(&a_area); //Remove the touch area. We'll no longer receive touch events
b_select.text = "Select Color"; //Change the button text back to "Select Color"
gui_button_redraw(&b_select); //redraw button
tracking_current->start(tracking_current); //Start tracking again
state = tracking;
}
break;
case selecting: //Selecting State: Where we wait on the user to select a color region
pixy_service(); //receive pixy events
//wait on user to select the image area
break;
case error: //Error State: Where we show an error message and leave the user no other choice than to click the backbutton
//wait on user to click the back button
break;
}
}
//Declare screen callbacks
static SCREEN_STRUCT screen = {
enter,
leave,
update
};
SCREEN_STRUCT* get_screen_tracking()
{
return &screen;
}
-50
View File
@@ -1,50 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_tracking.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-05-16 timolang@gmail.com e46314b Added Tracking Screen and implemented "Reference Tracking" and "Color Region Selection"
*
**************************************************************************************************************************************/
#include "screen.h"
/**
* @addtogroup screens
*/
/*@{*/
/**
* @defgroup tracking Tracking (Screen)
* The Tracking-Screen shows the object-tracking and allows some configuration
*/
/*@{*/
/**
* Enum which contains the available tracking implementations
*/
enum Tracking_Implementation {
OUR_TRACKING, //!< Our own tracking PID implementation
REFERENCE_TRACKING//!< Pixy's internal tracking implementation
};
/**
* Sets the current Mode/Tracking Implementation. Call this before using the screen obtained by get_screen_tracking()
* @param impl The new mode
*/
void tracking_set_mode(enum Tracking_Implementation impl);
/**
* Returns a pointer to the tracking screen
* \sa gui_screen_navigate
* @return
*/
SCREEN_STRUCT* get_screen_tracking();
/*@}*/
/*@}*/
-56
View File
@@ -1,56 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/filesystem/filesystem.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-05-10 timolang@gmail.com e2bce8f Added filesystem module, tests and implementation for it in emulator.
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
*
**************************************************************************************************************************************/
#include "filesystem.h"
#include "ll_filesystem.h"
bool filesystem_init()
{
return ll_filesystem_init();
}
DIRECTORY_STRUCT* filesystem_dir_open(const char* path)
{
return ll_filesystem_dir_open(path);
}
void filesystem_dir_close(DIRECTORY_STRUCT* dir)
{
ll_filesystem_dir_close(dir);
}
FILE_HANDLE* filesystem_file_open(const char* filename)
{
return ll_filesystem_file_open(filename);
}
void filesystem_file_close(FILE_HANDLE* handle)
{
ll_filesystem_file_close(handle);
}
FILE_STATUS filesystem_file_seek(FILE_HANDLE* handle, uint32_t offset)
{
return ll_filesystem_file_seek(handle, offset);
}
FILE_STATUS filesystem_file_read(FILE_HANDLE* handle, uint8_t* buf, uint32_t size)
{
return ll_filesystem_file_read(handle, buf, size);
}
FILE_STATUS filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t size)
{
return ll_filesystem_file_write(handle, buf, size);
}
-161
View File
@@ -1,161 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/filesystem/filesystem.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator
* 2015-05-10 timolang@gmail.com e2bce8f Added filesystem module, tests and implementation for it in emulator.
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
*
**************************************************************************************************************************************/
#ifndef FILESYSTEM_H
#define FILESYSTEM_H
#include <stdbool.h>
#include <stdint.h>
/**
* @defgroup filesystem Filesystem
* The Filesystem Module provides access to files and directories of a the native filesystem.
*/
/*@{*/
/**
* File Attributes used by implementation
* See http://en.wikipedia.org/wiki/Design_of_the_FAT_file_system#attributes for detailed description
*/
typedef enum {
F_RDO = 0x01, //!< File is readonly. You cannot write to it
F_HID = 0x02, //!< File is hidden
F_SYS = 0x04, //!< File is a system file
F_DIR = 0x10, //!< It's a directory and not a file
F_ARC = 0x20 //!< File has the archive flag set (probably unused)
} FILE_ATTRIBUTES;
/**
* Structure which represents last modified date of a file / directory
*/
typedef struct {
unsigned year : 7; //!< year from 1980 (0..127)
unsigned month: 4; //!< month (1..12)
unsigned day: 5; //!< day (1..31)
} FILE_DATE_STRUCT;
/**
* Structure which represents last modified time of a file / directory
*/
typedef struct {
unsigned hour : 5; //!< hour (0..23)
unsigned min: 6; //!< minute (0..59
unsigned sec: 5; //!< second/2 (0..29)
} FILE_TIME_STRUCT;
/**
* Structure which represents a file/directory entry. \sa DIRECTORY_STRUCT
*/
typedef struct {
uint32_t fsize; //!< File size in bytes. 0 for directories
FILE_DATE_STRUCT fdate; //!< Last modified date
FILE_TIME_STRUCT ftime; //!< Last modified time
uint8_t fattrib; //!< File/Directory Attributes
char* fname; //!< File/Directory name
} FILE_STRUCT;
/**
* Structure which represents an open directory with all it's entries. \sa filesystem_dir_open
*/
typedef struct {
const char* path; //!< Directory path (absolute)
uint16_t num_files; //!< Number of files/directories in this directory
FILE_STRUCT* files; //!< An array with \ref num_files FILE_STRUCT entries
} DIRECTORY_STRUCT;
/**
* Structure which represents an open file. \sa filesystem_file_open
*/
typedef struct {
const char* fname; //!< The absolute file name
uint32_t fpos; //!< The current byte-position in the file. \sa filesystem_file_seek
uint32_t fsize; //!< The total file size in bytes
} FILE_HANDLE;
/**
* Enum to represent the success or error-code of the filesystem_file_* functions
*/
typedef enum {
F_OK, //!< Everything ok
F_EOF, //!< The write/read operation tried to write/read past the end of the file. This is not a fatal error.
F_EACCESS, //!< The file can not be read/written due to access problems. This is a fatal error.
F_INVALIDPARAM,//!< You passed invalid parameters to the function
F_DISKERROR //!< A lowlevel disk-error occoured. This is a fatal error.
} FILE_STATUS;
/**
* Initializes the filesystem.
* Call this method before using any filesystem_* functions
* @return true on success
*/
bool filesystem_init();
/**
* Opens a directory and returns a structure which contains all files/subdirectories. \sa filesystem_dir_close()
* @param path The absolute path to the directory to open/read
* @return A Pointer to an initialized DIRECTORY_STRUCT on success, NULL on error
*/
DIRECTORY_STRUCT* filesystem_dir_open(const char* path);
/**
* Closes a previously opened directory. Free's all allocated resources.
* @param dir A Pointer to a DIRECTORY_STRUCT obtained by filesystem_dir_open().
*/
void filesystem_dir_close(DIRECTORY_STRUCT* dir);
/**
* Opens a file for read/writing. \note Depending on the implementation you may only open one file at a time
* @param filename The absolute file path
* @return A Pointer to a FILE_HANDLE on success, NULL on error.
*/
FILE_HANDLE* filesystem_file_open(const char* filename);
/**
* Closes a file.
* @param handle The FILE_HANDLE obtained by filesystem_file_open()
*/
void filesystem_file_close(FILE_HANDLE* handle);
/**
* Set's the read/write position to a new position
* @param handle The FILE_HANDLE obtained by filesystem_file_open()
* @param offset The new read/write position in bytes (absolute).
* @return \ref F_OK on success, an error Code otherwise.
*/
FILE_STATUS filesystem_file_seek(FILE_HANDLE* handle, uint32_t offset);
/**
* Reads some bytes from an open file.
* @param handle The FILE_HANDLE obtained by filesystem_file_open()
* @param buf The Buffer to write the bytes to
* @param size The number of bytes to read
* @return \ref F_OK on success, \ref F_EOF if less than \p size bytes could be read, an error Code otherwise.
*/
FILE_STATUS filesystem_file_read(FILE_HANDLE* handle, uint8_t* buf, uint32_t size);
/**
* Writes some bytes to a open file.
* \note Depending on the implementation the file may not be shrinked or expanded.
* @param handle The FILE_HANDLE obtained by filesystem_file_open()
* @param buf The Buffer to take the bytes from
* @param size The number of bytes to write
* @return \ref F_OK on success, \ref F_EOF if less than \p size bytes could be written, an error Code otherwise.
*/
FILE_STATUS filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t size);
/*@}*/
#endif /* FILESYSTEM_H */
-188
View File
@@ -1,188 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/gui/button.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com 7c9eabc Added button support.
* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules.
*
**************************************************************************************************************************************/
#include "tft.h"
#include "touch.h"
#include "button.h"
#include <string.h>
/* The Idea is as follows:
* When the user add's a button we create a touch area for that region and wait for PEN_DOWN events.
* Once the user puts the pen down in this area we'll redraw the button with different shadows (feedback)
* and we'll now wait on PEN_UP or PEN_LEAVE events.
* If the user takes the pen away while in the area (PEN_UP), we call the provided user callback
* Otherwise (PEN_LEAVE) we only restore the initial shadows
*/
/* Possible improvements:
* Move the button by 1 pixel while he is pressed, to create a "full 3d" experience
* Add events for the case when the button is pressed for a long time, without release
*/
//Method to calculate the shadow colors used to create the "3d" effect
void calculate_shadows(uint16_t bgcolor, uint16_t* light_shadow, uint16_t* dark_shadow)
{
#define BRIGHTNESS_VAL 3 //How much the Brightness is in/decreased for button shadows (3 -> Add/Subtract 1/3 off Full Value)
uint16_t c_light, c_dark; //c_light and c_dark will be filled with a lighter and a darker color as the background color (for the shadows)
uint8_t r, g, b;
//separate the channels of the 16-bit rgb565 color
r = (bgcolor & 0xF800) >> 11;
g = (bgcolor & 0x07E0) >> 5;
b = (bgcolor & 0x001F) >> 0;
//For the light shadow color:
if ((r + 0x1F / BRIGHTNESS_VAL) > 0x1F) { //Adding one third would exceed the maximum of the red channel
c_light = 0xF800; //Use full red
} else { //adding one third to the red channel is fine
c_light = (r + 0x1F / BRIGHTNESS_VAL) << 11; //Use same red as in the background, but add one third
}
if ((g + 0x3F / BRIGHTNESS_VAL) > 0x3F) { //same for the green channel
c_light |= 0x07E0;
} else {
c_light |= (g + 0x3F / BRIGHTNESS_VAL) << 5;
}
if ((b + 0x1F / BRIGHTNESS_VAL) > 0x1F) { //and the blue channel
c_light |= 0x0018;
} else {
c_light |= (b + 0x1F / BRIGHTNESS_VAL) << 0;
}
//For the dark shadow color
if (r > (0x1F / BRIGHTNESS_VAL)) { //Subtracting one third would NOT exceed the minimum of the red channel
c_dark = (r - 0x1F / BRIGHTNESS_VAL) << 11; //Use same red as in the background, but subtract one third
} else { //Subtracting one third would give us a number below zero
c_dark = 0x0000; //use no red channel
}
if (g > (0x3F / BRIGHTNESS_VAL)) { //Same for the green channel
c_dark |= (g - 0x3F / BRIGHTNESS_VAL) << 5;
}
if (b > (0x1F / BRIGHTNESS_VAL)) { //and the blue channel
c_dark |= (b - 0x1F / BRIGHTNESS_VAL) << 0;
}
//Assign the calculated shadows to out parameters
if (light_shadow != NULL) {
*light_shadow = c_light;
}
if (dark_shadow != NULL) {
*dark_shadow = c_dark;
}
}
//Callback which is called when the user touches the touch-area we created for the button
void buttons_cb(void* touchArea, TOUCH_ACTION triggeredAction)
{
TOUCH_AREA_STRUCT* area = (TOUCH_AREA_STRUCT*)touchArea;
BUTTON_STRUCT* button = (BUTTON_STRUCT*)touchArea;
uint16_t c_light, c_dark; //c_light and c_dark will be filled with a lighter and a darker color as the background color (for the shadows)
calculate_shadows(button->bgcolor, &c_light, &c_dark);
switch (triggeredAction) {
case PEN_DOWN: //If the user touches the area for the "first time"
area->hookedActions = PEN_UP | PEN_LEAVE; //for the future we only want PEN_UP and PEN_LEAVE events
//Draw shadows
tft_draw_line(button->base.x1 + 1, button->base.y1, button->base.x2 - 1, button->base.y1, c_dark); //North
tft_draw_line(button->base.x1, button->base.y1 + 1, button->base.x1, button->base.y2 - 1, c_dark); //West
tft_draw_line(button->base.x1 + 1, button->base.y2, button->base.x2 - 1, button->base.y2, c_light); //South
tft_draw_line(button->base.x2, button->base.y1 + 1, button->base.x2, button->base.y2 - 1, c_light); //East
break;
case PEN_UP: //If the user took the pen away, while in the area (=button pressed!)
case PEN_LEAVE: //or the user "slided out" of the area
area->hookedActions = PEN_DOWN; //for the future we only want PEN_DOWN events
//Draw inverse shadows
tft_draw_line(button->base.x1 + 1, button->base.y1, button->base.x2 - 1, button->base.y1, c_light); //North
tft_draw_line(button->base.x1, button->base.y1 + 1, button->base.x1, button->base.y2 - 1, c_light); //West
tft_draw_line(button->base.x1 + 1, button->base.y2, button->base.x2 - 1, button->base.y2, c_dark); //South
tft_draw_line(button->base.x2, button->base.y1 + 1, button->base.x2, button->base.y2 - 1, c_dark); //East
if (triggeredAction == PEN_UP && button->callback != NULL) { //If the button got "pressed" instead of left, and the user provided a callback
button->callback(button); //execute the user callback
}
break;
default:
break;
}
}
bool gui_button_add(BUTTON_STRUCT* button)
{
if (touch_have_empty(1)) { //Check if the touch module can handle one additional area
//Calculate width and height of the button text
unsigned int strwidth = tft_font_width(button->font) * strlen(button->text);
unsigned char strheight = tft_font_height(button->font);
button->base.hookedActions = PEN_DOWN; //At first we are interested in PEN_DOWN events
button->base.callback = buttons_cb; //Use our own callback for the touch area events
if (button->base.x2 == AUTO) { //The user wants us to calculate the button width automatically
//Use string width + half of a character width as button width
button->base.x2 = button->base.x1 - 1 + strwidth + (tft_font_width(button->font) / 2);
} else if ((button->base.x2 - button->base.x1 + 1) < (strwidth + 2)) { //the provided width is too small to fit the entire text
return false; //report error
}
if (button->base.y2 == AUTO) { //The user wants us to calculate the button height automatically
//Use one and a half character heights as button height
button->base.y2 = button->base.y1 - 1 + strheight + (strheight / 2);
} else if ((button->base.y2 - button->base.y1 + 1) < (strheight + 2)) { //the provided height is too small to fit the text
return false;
}
gui_button_redraw(button); //call the redraw method, which will take care of drawing the entire button
return touch_register_area(&button->base); //Register the touch area and receive events for this button, from now on
}
return false; //no more touch areas left
}
void gui_button_redraw(BUTTON_STRUCT* button)
{
//Calculate text dimensions and shadow colors
unsigned int strwidth = tft_font_width(button->font) * strlen(button->text);
unsigned char strheight = tft_font_height(button->font);
uint16_t c_light, c_dark;
calculate_shadows(button->bgcolor, &c_light, &c_dark);
//Draw the background and the 4 lines (shadow colors)
tft_fill_rectangle(button->base.x1 + 1, button->base.y1 + 1, button->base.x2 - 1, button->base.y2 - 1, button->bgcolor);
tft_draw_line(button->base.x1 + 1, button->base.y1, button->base.x2 - 1, button->base.y1, c_light); //North
tft_draw_line(button->base.x1, button->base.y1 + 1, button->base.x1, button->base.y2 - 1, c_light); //West
tft_draw_line(button->base.x1 + 1, button->base.y2, button->base.x2 - 1, button->base.y2, c_dark); //South
tft_draw_line(button->base.x2, button->base.y1 + 1, button->base.x2, button->base.y2 - 1, c_dark); //East
//Draw the text
tft_print_line(button->base.x1 + (button->base.x2 - button->base.x1 + 1 - strwidth) / 2, button->base.y1 + (button->base.y2 - button->base.y1 + 1 - strheight) / 2, button->txtcolor, button->bgcolor, button->font, button->text);
}
void gui_button_remove(BUTTON_STRUCT* button)
{
//We only need to unregister the touch area, as we have not allocated anything else
touch_unregister_area((TOUCH_AREA_STRUCT*)button);
}
-89
View File
@@ -1,89 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/gui/button.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com 7c9eabc Added button support.
* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure
* 2015-05-12 timolang@gmail.com 1402598 Added doxygen stuff for button module and some minor changes to touch, screen_main and tft module.
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules.
*
**************************************************************************************************************************************/
#ifndef BUTTON_H
#define BUTTON_H
#include "touch.h"
/**
* @defgroup gui Gui
* The Gui Module
*/
/*@{*/
/**
* @defgroup button Button
* The Button Gui-Element is a clickable, rectangular box with a label inside.
* When it is pressed and released you will be notified via the provided callback.
*/
/*@}*/
/**
* @addtogroup button
*/
/*@{*/
/**
* Prototype for Event Listeners (called when the button is pressed)
* \note You should NOT execute long running things in this callback nor should you update the gui. But you can call gui_screen_navigate() for instance.
* @param button The pointer to the BUTTON_STRUCT where to corresponding Button was pressed
*/
typedef void (*BUTTON_CALLBACK)(void* button);
/**
* Structure to configure the Button
*/
typedef struct {
TOUCH_AREA_STRUCT base; //!< Basic geometry of the button. You only need to set the x1, y1, x2, y2 members of this struct.
uint16_t bgcolor; //!< The 16-bit background color of the button
BUTTON_CALLBACK callback; //!< Callback which is executed when the button is pressed
uint16_t txtcolor; //!< The 16-bit text color
uint8_t font; //!< The number of the font to use
const char* text; //!< The label of the button
} BUTTON_STRUCT;
#define AUTO 0 //!< Use this value instead of x2, y2 in the BUTTON_STRUCT to autocalculate the button width/height
/**
* Adds a button. Your Callback will be called from now on, if the button was pressed
* @param button A Pointer to the preinitialized BUTTON_STRUCT
* @return true on success
*/
bool gui_button_add(BUTTON_STRUCT* button);
/**
* Removes the button. You will no longer receive events for this button. This function will not overdraw the region where the button was located.
* @param button A Pointer to the BUTTON_STRUCT
*/
void gui_button_remove(BUTTON_STRUCT* button);
/**
* Redraws the button. Call this method if you have to redraw the entire screen or if you want to draw a button on top of an image.
* @param button A Pointer to the BUTTON_STRUCT
*/
void gui_button_redraw(BUTTON_STRUCT* button);
/*@}*/
#endif /* BUTTON_H */
-144
View File
@@ -1,144 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/gui/checkbox.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com b300ac5 Added Checkbox support
* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules.
*
**************************************************************************************************************************************/
#include "tft.h"
#include "touch.h"
#include "checkbox.h"
#include <stdio.h>
/* The idea is as follows:
* When the user creates a checkbox we create a touch area for that region and wait for PEN_DOWN events.
* Once the user puts the pen down in this area we'll redraw the checkbox with different shadows (feedback)
* and we'll now wait on PEN_UP or PEN_LEAVE events.
* If the user takes the pen away while in the area (PEN_UP), we toggle the checkbox and we call the provided user callback
* Otherwise (PEN_LEAVE) we only restore the initial shadows
*/
#define ACTIVE_COLOR RGB(251,208,123) //shadow color (inside of border)
#define BORDER_COLOR RGB(29,82,129) //1px border color
#define BACKGROUND_COLOR WHITE //Background color
//Callback which is called when the user touches the touch-area we created for the checkbox
void checkboxes_cb(void* touchArea, TOUCH_ACTION triggeredAction)
{
TOUCH_AREA_STRUCT* area = (TOUCH_AREA_STRUCT*)touchArea;
CHECKBOX_STRUCT* checkbox = (CHECKBOX_STRUCT*)touchArea;
switch (triggeredAction) {
case PEN_DOWN: //If the user touches the area for the "first time"
area->hookedActions = PEN_UP | PEN_LEAVE; //for the future we only want PEN_UP and PEN_LEAVE events
//Draw active shadows
tft_draw_rectangle(checkbox->base.x1 + 1, checkbox->base.y1 + 1, checkbox->base.x2 - 1, checkbox->base.y2 - 1, ACTIVE_COLOR);
tft_draw_rectangle(checkbox->base.x1 + 2, checkbox->base.y1 + 2, checkbox->base.x2 - 2, checkbox->base.y2 - 2, ACTIVE_COLOR);
break;
case PEN_UP: //If the user took the pen away, while in the area (=toggle checkbox!)
checkbox->checked = !checkbox->checked; //Toggle checkbox state
gui_checkbox_update(checkbox); //redraw/overdraw tickmark
if (checkbox->callback != NULL) { //The user provided a callback
checkbox->callback(checkbox, checkbox->checked); //Call the provided callback with the new checked state
}
// no break statement here!
case PEN_LEAVE: //if the user "slided out" of the area
area->hookedActions = PEN_DOWN; //for the future we only want PEN_DOWN events
//Draw inactive shadows
tft_draw_rectangle(checkbox->base.x1 + 1, checkbox->base.y1 + 1, checkbox->base.x2 - 1, checkbox->base.y2 - 1, BACKGROUND_COLOR);
tft_draw_rectangle(checkbox->base.x1 + 2, checkbox->base.y1 + 2, checkbox->base.x2 - 2, checkbox->base.y2 - 2, BACKGROUND_COLOR);
break;
default:
break;
}
}
bool gui_checkbox_add(CHECKBOX_STRUCT* checkbox)
{
if (touch_have_empty(1)) { //Check if the touch module can handle one additional area
unsigned char size = 0;
checkbox->base.hookedActions = PEN_DOWN; //At first we are interested in PEN_DOWN events
checkbox->base.callback = checkboxes_cb; //Use our own callback for the touch area events
//Check the size of the checkbox
if (checkbox->base.x2 > checkbox->base.x1) {
size = checkbox->base.x2 - checkbox->base.x1; //use width a as size
}
if (checkbox->base.y2 > checkbox->base.y1) {
if ((checkbox->base.y2 - checkbox->base.y1) > size) { //height is larger than size
size = checkbox->base.y2 - checkbox->base.y1; //use height as size
}
}
if (size == 0) { //no size found (maybe swap x2 and x1 or y2 and y1 ?)
return false; //signal error
}
if ((size & 0x01)) { //the size is an odd number
size++; //make size an even number
}
//Correct x2,y2 so that the checkbox is quadratic
checkbox->base.x2 = checkbox->base.x1 + size;
checkbox->base.y2 = checkbox->base.y1 + size;
gui_checkbox_redraw(checkbox);//Call redraw method, which will take care of the drawing of the entire checkbox
return touch_register_area(&checkbox->base); //Register the touch area and receive events for this checkbox, from now on
}
return false; //no more touch areas left
}
void gui_checkbox_redraw(CHECKBOX_STRUCT* checkbox)
{
//Draw background and border
tft_fill_rectangle(checkbox->base.x1 + 1, checkbox->base.y1 + 1, checkbox->base.x2 - 1, checkbox->base.y2 - 1, BACKGROUND_COLOR);
tft_draw_rectangle(checkbox->base.x1, checkbox->base.y1, checkbox->base.x2, checkbox->base.y2, BORDER_COLOR);
if (checkbox->checked) { //checkbox is currently checked
gui_checkbox_update(checkbox); //Call update method which will draw the tickmark
}
}
void gui_checkbox_remove(CHECKBOX_STRUCT* checkbox)
{
//We only need to unregister the touch area, as we have not allocated anything else
touch_unregister_area((TOUCH_AREA_STRUCT*)checkbox);
}
void gui_checkbox_update(CHECKBOX_STRUCT* checkbox)
{
unsigned int c = (checkbox->checked) ? checkbox->fgcolor : BACKGROUND_COLOR; //color to use for the tickmark
//helper points inside the checkbox
unsigned int xcent = checkbox->base.x1 + (checkbox->base.x2 - checkbox->base.x1) * 6 / 14;
unsigned int yleft = checkbox->base.y2 - (xcent - checkbox->base.x1) - 1 ;
unsigned int yright = checkbox->base.y2 - (checkbox->base.x2 - xcent) - 1 ;
unsigned int ybot = checkbox->base.y2 - 4;
//Draw tickmark as a 3pixel wide line
tft_draw_line(checkbox->base.x1 + 3, yleft - 1, xcent, ybot - 1, c);
tft_draw_line(checkbox->base.x1 + 3, yleft, xcent, ybot , c);
tft_draw_line(checkbox->base.x1 + 3, yleft + 1, xcent, ybot + 1, c);
xcent++;
ybot--;
tft_draw_line(xcent, ybot - 1, checkbox->base.x2 - 3, yright - 1, c);
tft_draw_line(xcent, ybot, checkbox->base.x2 - 3, yright + 0, c);
tft_draw_line(xcent, ybot + 1, checkbox->base.x2 - 3, yright + 1, c);
}
-86
View File
@@ -1,86 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/gui/checkbox.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com b300ac5 Added Checkbox support
* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules.
*
**************************************************************************************************************************************/
#ifndef CHECKBOX_H
#define CHECKBOX_H
#include "touch.h"
/**
* @addtogroup gui
*/
/*@{*/
/**
* @defgroup checkbox Checkbox
* The Checkbox Gui-Element is a clickable, rectangular box with an optional tickmark inside of it.
* When the checkbox is pressed and released it's tick state changes and you will be notified via the provided callback.
*/
/*@}*/
/**
* @addtogroup checkbox
*/
/*@{*/
/**
* Prototype for Event Listeners (called when the checkbox state has changed)
* \note You should NOT execute long running things in this callback nor should you update the gui. But you can call gui_screen_navigate() for instance.
* @param checkbox The pointer to the CHECKBOX_STRUCT where to corresponding Checkbox has changed the state
* @param checked A boolean which indicates whether the checkbox is now checked or not.
*/
typedef void (*CHECKBOX_CALLBACK)(void* checkbox, bool checked);
/**
* Structure to configure the Checkbox
*/
typedef struct {
TOUCH_AREA_STRUCT base; //!< Basic geometry of the Checkbox. You only need to set the x1, y1, x2, y2 members of this struct.
uint16_t fgcolor; //!< The 16-bit color of the tickmark
bool checked; //!< A boolean which indicates whether or not the checkbox is currently checked.
CHECKBOX_CALLBACK callback; //!< Callback which is executed when the checkbox changes state
} CHECKBOX_STRUCT;
/**
* Adds a checkbox. Your Callback will be called from now on, if the checkbox changes state
* @param checkbox A Pointer to the preinitialized CHECKBOX_STRUCT
* @return true on success
*/
bool gui_checkbox_add(CHECKBOX_STRUCT* checkbox);
/**
* Removes the checkbox. You will no longer receive events for this checkbox. This function will not overdraw the region where the checkbox was located.
* @param checkbox A Pointer to the CHECKBOX_STRUCT
*/
void gui_checkbox_remove(CHECKBOX_STRUCT* checkbox);
/**
* Updates the checkbox. Call this function when you change the state of the checkbox through code.
* @param checkbox A Pointer to the CHECKBOX_STRUCT
*/
void gui_checkbox_update(CHECKBOX_STRUCT* checkbox);
/**
* Redraws the checkbox. Call this method if you have to redraw the entire screen or if you want to draw a checkbox on top of an image.
* @param checkbox A Pointer to the CHECKBOX_STRUCT
*/
void gui_checkbox_redraw(CHECKBOX_STRUCT* checkbox);
#define CHECKBOX_WIN_FG_COLOR RGB(32,161,34)
/*@}*/
#endif /* CHECKBOX_H */
-169
View File
@@ -1,169 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/gui/numupdown.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-30 timolang@gmail.com 76ea9d8 Added num up down support.
* 2015-04-30 timolang@gmail.com b491b78 Made numupdown horizontal
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules.
*
**************************************************************************************************************************************/
#include "tft.h"
#include "touch.h"
#include "button.h"
#include "numupdown.h"
#include <stdio.h> //for sprintf
#include <stddef.h> //for offsetof macro
#include <stdlib.h> //for abs
/* The idea is as follows:
* When the user add's a numupdown we create two buttons, one with a plus and one with a minus sign in it
* When the user presses one of the buttons we check and increase the value and execute the provided user callback
*/
#define BASE_COLOR RGB(90,90,90) //Background color for the whole element
//Callback which is called when the user presses the "plus" button
void button_up_cb(void* button)
{
//Get the pointer to the numupdown: subtract the offset of the buttonUp member in the struct from the button pointer
NUMUPDOWN_STRUCT* element = button - offsetof(NUMUPDOWN_STRUCT, buttonUp);
if (element->value < element->max) { //old value lies below the maximum
element->value++; //let's increase the value
gui_numupdown_update(element); //and redraw everything
if (element->callback != NULL) { //the user provided a callback
element->callback(element, element->value); //Call the user callback with the new value
}
}
}
//Callback which is called when the user presses the "minus" button
void button_down_cb(void* button)
{
//Get the pointer to the numupdown: subtract the offset of the buttonDown member in the struct from the button pointer
NUMUPDOWN_STRUCT* element = button - offsetof(NUMUPDOWN_STRUCT, buttonDown);
if (element->value > element->min) { //old value lies above the minimum
element->value--; //let's decrease the value
gui_numupdown_update(element); //and redraw everything
if (element->callback != NULL) { //the user provided a callback
element->callback(element, element->value); //Call the user callback with the new value
}
}
}
//Method to calculate the number of characters needed to print the provided number in decimal notation (with optional sign)
static uint8_t calc_text_width(int16_t val)
{
uint8_t width = 1 + (val < 0); //1 if positive, 2 if negative (to let space for sign)
val = abs(val); //Make the number positive
while (val >= 10) { //while we have two or more digits
val /= 10; //remove one digit
width++; //add one character
}
return width;
}
bool gui_numupdown_add(NUMUPDOWN_STRUCT* numupdown)
{
if (touch_have_empty(2)) { //Check if the touch module can handle two additional areas
if (numupdown->min > numupdown->max) { //min is bigger than max?
return false; //invalid parameter
}
if (numupdown->value < numupdown->min) { //value is smaller than min?
numupdown->value = numupdown->min; //normalize value
} else if (numupdown->value > numupdown->max) { //value is bigger than max?
numupdown->value = numupdown->max; //normalize value
}
uint8_t tw1 = calc_text_width(numupdown->max); //Calculate character width to render maximum value
uint8_t tw2 = calc_text_width(numupdown->min); //Calculate character width to render minimum value
if (tw2 > tw1) {
tw1 = tw2; //ensure tw1 contains the larger number of the two
}
uint8_t width = tft_font_width(0) * (tw1 + 1); //Calculate width of the number area
//Add "minus" button to the left side of the number area
numupdown->buttonDown.base.x1 = numupdown->x;
numupdown->buttonDown.base.y1 = numupdown->y;
numupdown->buttonDown.base.x2 = AUTO;
numupdown->buttonDown.base.y2 = numupdown->y + tft_font_height(0) * 2;
numupdown->buttonDown.text = "-";
numupdown->buttonDown.font = 0;
numupdown->buttonDown.bgcolor = BASE_COLOR;
numupdown->buttonDown.txtcolor = WHITE;
numupdown->buttonDown.callback = button_down_cb;
gui_button_add(&numupdown->buttonDown);
//Add "plus" button to the right side of the number area
numupdown->buttonUp.base.x1 = numupdown->buttonDown.base.x2 + width + 2;
numupdown->buttonUp.base.y1 = numupdown->y;
numupdown->buttonUp.base.x2 = AUTO;
numupdown->buttonUp.base.y2 = numupdown->y + tft_font_height(0) * 2;
numupdown->buttonUp.text = "+";
numupdown->buttonUp.font = 0;
numupdown->buttonUp.bgcolor = BASE_COLOR;
numupdown->buttonUp.txtcolor = WHITE;
numupdown->buttonUp.callback = button_up_cb;
gui_button_add(&numupdown->buttonUp);
//Draw background and label of the number area
tft_fill_rectangle(numupdown->buttonDown.base.x2 + 2, numupdown->y, numupdown->buttonDown.base.x2 + width, numupdown->buttonUp.base.y2, BASE_COLOR);
tft_print_formatted(numupdown->buttonDown.base.x2 + 2 + tft_font_width(0) / 2, numupdown->y + tft_font_height(0) / 2, numupdown->fgcolor, BASE_COLOR, 0, "%*d", tw1, numupdown->value);
return true;
}
return false; //not enough touch areas left
}
void gui_numupdown_remove(NUMUPDOWN_STRUCT* numupdown)
{
//remove the two buttons, we have no other allocated resources
gui_button_remove(&numupdown->buttonUp);
gui_button_remove(&numupdown->buttonDown);
}
void gui_numupdown_redraw(NUMUPDOWN_STRUCT* numupdown)
{
//redraw the two buttons
gui_button_redraw(&numupdown->buttonUp);
gui_button_redraw(&numupdown->buttonDown);
//call update method which will take care of the number-area rendering
gui_numupdown_update(numupdown);
}
void gui_numupdown_update(NUMUPDOWN_STRUCT* numupdown)
{
//Calculate the number area width again (see above)
uint8_t tw1 = calc_text_width(numupdown->max);
uint8_t tw2 = calc_text_width(numupdown->min);
if (tw2 > tw1) {
tw1 = tw2;
}
uint8_t width = tft_font_width(0) * (tw1 + 1);
//Draw background and label of the number area
tft_fill_rectangle(numupdown->buttonDown.base.x2 + 2, numupdown->y, numupdown->buttonDown.base.x2 + width, numupdown->buttonUp.base.y2, BASE_COLOR);
tft_print_formatted(numupdown->buttonDown.base.x2 + 2 + tft_font_width(0) / 2, numupdown->y + tft_font_height(0) / 2, numupdown->fgcolor, BASE_COLOR, 0, "%*d", tw1, numupdown->value);
}
-88
View File
@@ -1,88 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/gui/numupdown.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-30 timolang@gmail.com 76ea9d8 Added num up down support.
* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
*
**************************************************************************************************************************************/
#ifndef NUMUPDOWN_H
#define NUMUPDOWN_H
#include "button.h"
/**
* @addtogroup gui
*/
/*@{*/
/**
* @defgroup numupdown NummericUpDown
* The NummericUpDown Gui Element
*/
/*@}*/
/**
* @addtogroup numupdown
*/
/*@{*/
/**
* Prototype for Event Listeners (called when the NummericUpDown value has changed)
* \note You should NOT execute long running things in this callback nor should you update the gui. But you can call gui_screen_navigate() for instance.
* @param numupdown The pointer to the NUMUPDOWN_STRUCT where to corresponding NummericUpDown has changed it's value
* @param value The new value of the NummericUpDown
*/
typedef void (*NUMUPDOWN_CALLBACK)(void* numupdown, int16_t value);
/**
* Structure to configure the NummericUpDown
*/
typedef struct {
uint16_t x; //!< The x-Coordinate of the Top-Left Starting Point.
uint16_t y; //!< The y-Coordinate of the Top-Left Starting Point.
uint16_t fgcolor; //!< The 16-bit color of the value-text
int16_t value; //!< The current/default value
int16_t min; //!< The minimum possible value (inclusive)
int16_t max; //!< The maximum possible value (inclusive)
NUMUPDOWN_CALLBACK callback; //!< Callback which is executed when the value changes
BUTTON_STRUCT buttonUp; //!< For internal use, don't change, don't initialize
BUTTON_STRUCT buttonDown; //!< For internal use, don't change, don't initialize
} NUMUPDOWN_STRUCT;
/**
* Adds a NummericUpDown. Your Callback will be called from now on, if the numupdown's value changes
* @param numupdown A Pointer to the preinitialized NUMUPDOWN_STRUCT
* @return true on success
*/
bool gui_numupdown_add(NUMUPDOWN_STRUCT* numupdown);
/**
* Removes the NummericUpDown. You will no longer receive events for this numupdown. This function will not overdraw the region where the numupdown was located.
* @param numupdown A Pointer to the NUMUPDOWN_STRUCT
*/
void gui_numupdown_remove(NUMUPDOWN_STRUCT* numupdown);
/**
* Updates the NummericUpDown. Call this function when you change the value/min/max of the numupdown through code.
* @param numupdown A Pointer to the NUMUPDOWN_STRUCT
*/
void gui_numupdown_update(NUMUPDOWN_STRUCT* numupdown);
/**
* Redraws the NummericUpDown. Call this method if you have to redraw the entire screen or if you want to draw a numupdown on top of an image.
* @param numupdown A Pointer to the NUMUPDOWN_STRUCT
*/
void gui_numupdown_redraw(NUMUPDOWN_STRUCT* numupdown);
/*@}*/
#endif /* NUMUPDOWN_H */
-110
View File
@@ -1,110 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/gui/screen.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
* 2015-04-27 timolang@gmail.com 77e6d0e Fixed screen implementation.
* 2015-05-10 timolang@gmail.com b6ab7c8 Fixed compiler warning in tft and screen module.
* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules.
* 2015-06-01 timolang@gmail.com eb573bc Finalized calibration. Fixed a bug in screen module.
* 2015-06-06 timolang@gmail.com c06661d Fixed some outdated comments in source code. Documented Gui Module in docu.
*
**************************************************************************************************************************************/
#include "screen.h"
/* The idea is as follows:
* We only call screen callbacks from the gui_screen_update() method, which is called from the applications main loop.
* Instructions to switch the screen will be delayed until the gui_screen_update() method is called again.
* This makes it safe to change the screen from an touch interrupt (e.g. button callback)
*/
/* Possible Improvements:
* Ensure that you can not navigate to a screen which is already in the history (because it will corrupt the list)
*/
static SCREEN_STRUCT* screen_list = NULL; //Head of the linked list which stores the screen history.
static SCREEN_STRUCT* screen_current = NULL; //Pointer to the current screen (= tail of the list)
static volatile SCREEN_STRUCT* screen_goto = NULL; //Screen we should navigate to once we enter the gui_screen_update() method again
SCREEN_STRUCT* gui_screen_get_current()
{
return screen_current;
}
void gui_screen_update()
{
if (screen_goto != NULL) { //we received the task to switch the screen
SCREEN_STRUCT* go = (SCREEN_STRUCT*) screen_goto; //Backup volatile variable
screen_goto = NULL; //reset the "goto instruction", since we're processing it now
if (go->next != NULL) { //The screen is not the last in the list, so we're going back
if (go->next != screen_current) { //this condition should always be false
return; //list corrupted?
}
screen_current->on_leave(screen_current); //let the current screen free/unregister it's resources
go->next = NULL; //remove the current screen from the list
} else { //we're going forward (to a new screen)
if (screen_current != NULL) { //this is not the first screen
screen_current->on_leave(screen_current); //let the current screen free/unregister it's resources
screen_current->next = go; //append the new screen to the end of the list
} else { //first screen ever seen
screen_list = go; //set the new screen as list-head
}
}
go->on_enter(go); //let the new screen allocate/register it's resources
screen_current = go; //the new screen is now the current screen. Transition done
}
if (screen_current != NULL) { //A screen has been set
screen_current->on_update(screen_current); //Update current screen
}
}
bool gui_screen_navigate(SCREEN_STRUCT* screen)
{
if (screen == NULL || screen == screen_current || screen == screen_goto) { //invalid argument passed
return false;
}
screen->next = NULL; //this will become the new tail of the list, so the next pointer must be NULL
screen_goto = screen; //"send message" to main loop, to switch the screen
return true;
}
bool gui_screen_back()
{
if (screen_list == NULL) { //the list head is emtpy, nothing to go back to
return false;
}
SCREEN_STRUCT* current = screen_list;
SCREEN_STRUCT* last = NULL;
//Find second last element in list
while (current->next != NULL) {
last = current;
current = current->next;
}
if (last == NULL) {
return false; //There's only a single screen, there's no going back here
}
if (current != screen_current) {
return false; //The last entry in the list is not the current screen. List corrupted?
}
screen_goto = last; //"send message" to main loop, to switch the screen
return true;
}
-94
View File
@@ -1,94 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/gui/screen.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
* 2015-04-27 timolang@gmail.com 77e6d0e Fixed screen implementation.
* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules.
* 2015-06-06 timolang@gmail.com c06661d Fixed some outdated comments in source code. Documented Gui Module in docu.
*
**************************************************************************************************************************************/
#ifndef SCREEN_H
#define SCREEN_H
#include <stdio.h>
#include <stdbool.h>
/**
* @addtogroup gui
*/
/*@{*/
/**
* @defgroup screen Screen
* The Screen Submodule provides an api to navigate between different "screens" on the UI.
* Each screen must provide an enter, update and a leave method; which will be called from this module at the right time.
* The implemented screens of the application are documented in the \ref screens module.
*/
/*@}*/
/**
* @addtogroup screen
*/
/*@{*/
/**
* Prototype for Event Listeners (called when the screen is entered, left or should be updated)
* @param screen The pointer to the SCREEN_STRUCT where the event occurred
*/
typedef void (*SCREEN_CALLBACK)(void* screen);
/**
* Structure to configure the Screen
*/
typedef struct SCREEN_S {
SCREEN_CALLBACK on_enter; //!< The Callback which is called when the screen is entered. Add/Register all UI-Elements here
SCREEN_CALLBACK on_leave; //!< The Callback which is called when the screen is left. Remove/Unregister all UI-Elements here
SCREEN_CALLBACK on_update; //!< The Callback which is called repeatedly when the screen should be updated. Update/Redraw all UI-Elements here
struct SCREEN_S* next; //!< Used internally. do not modify, do not initialize
} SCREEN_STRUCT;
/**
* Navigate to the given screen as soon as the app enters the main loop again (and gui_screen_update() is called)
* It's safe to call this method from an interrupt
* @note Do not pass a screen which is already in your history of screens!
* @param screen A Pointer to the preinitialized SCREEN_STRUCT
* @return true on success
*/
bool gui_screen_navigate(SCREEN_STRUCT* screen);
/**
* Navigate one screen back as soon as the app enters the main loop again.
* It's safe to call this method from an interrupt
* @return true on success
*/
bool gui_screen_back();
/**
* Returns the currently active screen
* @return A Pointer to the active SCREEN_STRUCT
*/
SCREEN_STRUCT* gui_screen_get_current();
//Updates/switches the screens. Call this from the app main loop, as fast as you can.
/**
* Updates the current screen. Switches the screen if gui_screen_navigate() or gui_screen_back() have been called since the last call to this method.
* This method should be called repeatedly from the main loop (e.g. app_process())
*/
void gui_screen_update();
/*@}*/
#endif /* SCREEN_H */
-44
View File
@@ -1,44 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/lowlevel/ll_filesystem.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-05-10 timolang@gmail.com e2bce8f Added filesystem module, tests and implementation for it in emulator.
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
*
**************************************************************************************************************************************/
#include "filesystem.h"
/**
* @addtogroup lowlevel
*/
/*@{*/
/**
* @defgroup ll_filesystem Filesystem (LowLevel)
* Low level functions for the \ref filesystem module
*/
/*@}*/
/**
* @addtogroup ll_filesystem
*/
/*@{*/
bool ll_filesystem_init();
DIRECTORY_STRUCT* ll_filesystem_dir_open(const char* path);
void ll_filesystem_dir_close(DIRECTORY_STRUCT* dir);
FILE_HANDLE* ll_filesystem_file_open(const char* filename);
void ll_filesystem_file_close(FILE_HANDLE* handle);
FILE_STATUS ll_filesystem_file_seek(FILE_HANDLE* handle, uint32_t offset);
FILE_STATUS ll_filesystem_file_read(FILE_HANDLE* handle, uint8_t* buf, uint32_t size);
FILE_STATUS ll_filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t size);
/*@}*/
-47
View File
@@ -1,47 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/lowlevel/ll_system.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop.
* 2015-04-03 timolang@gmail.com cab8609 Integrated pixy into emulator. Pixy is no longer in the common/libs folder but in emulator/libs and discovery/libs
* 2015-04-03 timolang@gmail.com 9a1d12a Refactored discovery, to use new project structure. Almost ready.
* 2015-04-25 timolang@gmail.com 3d1e4b2 Simplified code a bit. Emulator does not work stable when replugging pixy.
* 2015-04-25 timolang@gmail.com 0858b0d Fixed some bugs when receiving large data.
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
*
**************************************************************************************************************************************/
#include <stdbool.h>
#include <stdint.h>
/**
* @defgroup lowlevel LowLevel
* The Low-Level platform abstraction layer
*/
/*@{*/
/**
* @defgroup ll_system System (LowLevel)
* Low level functions of the \ref system Module
*/
/*@}*/
/**
* @addtogroup ll_system
*/
/*@{*/
bool ll_system_init();
void ll_system_delay(uint32_t msec);
void ll_system_process();
void ll_system_toggle_led();
/*@}*/
-60
View File
@@ -1,60 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/lowlevel/ll_tft.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator
* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop.
* 2015-04-03 timolang@gmail.com 9a1d12a Refactored discovery, to use new project structure. Almost ready.
* 2015-04-03 timolang@gmail.com 1aa9194 Fixed Drawing of rects in Emulator. Got frames from pixy to emulator. Slooooow.
* 2015-04-27 aaron@duckpond.ch aed90ef Drawcircle added (emulator)
* 2015-04-27 timolang@gmail.com e249fb2 Added font support
* 2015-04-27 aaron@duckpond.ch f0a6c3b Implemented init functions for gpio, fsmc and display
* 2015-04-27 aaron@duckpond.ch 0b61f21 Fixed misplacement of prototypes in ll_tft.h and implemented a propper init function.
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
*
**************************************************************************************************************************************/
#include <stdint.h>
#include <stdbool.h>
/**
* @addtogroup lowlevel
*/
/*@{*/
/**
* @defgroup ll_tft TFT (LowLevel)
* Low level functions for the \ref tft module
*/
/*@}*/
/**
* @addtogroup ll_tft
*/
/*@{*/
// init functions
bool ll_tft_init();
// draw functions
void ll_tft_clear(uint16_t color);
void ll_tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
void ll_tft_draw_pixel(uint16_t x, uint16_t y, uint16_t color);
void ll_tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
void ll_tft_fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
void ll_tft_draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t* dat);
void ll_tft_draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color);
uint8_t ll_tft_num_fonts();
uint8_t ll_tft_font_height(uint8_t fontnum);
uint8_t ll_tft_font_width(uint8_t fontnum);
void ll_tft_draw_char(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, char c);
/*@}*/
-37
View File
@@ -1,37 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/lowlevel/ll_touch.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com 259d446 Added touch support to emulator. Implemented basic touch function.
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
*
**************************************************************************************************************************************/
#include <stdint.h>
#include <stdbool.h>
/**
* @addtogroup lowlevel
*/
/*@{*/
/**
* @defgroup ll_touch Touch (LowLevel)
* Low level functions for the \ref touch module
*/
/*@}*/
/**
* @addtogroup ll_touch
*/
/*@{*/
bool ll_touch_init();
/*@}*/
-294
View File
@@ -1,294 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#ifndef __PIXY_H__
#define __PIXY_H__
#include <stdint.h>
#include "pixydefs.h"
// Pixy C API //
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @defgroup pixy Pixy
* The Pixy Module
*/
/*@{*/
#define PIXY_MAX_SIGNATURE 7
// Pixy x-y position values
#define PIXY_MIN_X 0
#define PIXY_MAX_X 319
#define PIXY_MIN_Y 0
#define PIXY_MAX_Y 199
// RC-servo values
#define PIXY_RCS_MIN_POS 0
#define PIXY_RCS_MAX_POS 1000
#define PIXY_RCS_CENTER_POS ((PIXY_RCS_MAX_POS-PIXY_RCS_MIN_POS)/2)
// Block types
#define PIXY_BLOCKTYPE_NORMAL 0
#define PIXY_BLOCKTYPE_COLOR_CODE 1
struct Block
{
/*void print(char *buf)
{
int i, j;
char sig[6], d;
bool flag;
if (type==PIXY_BLOCKTYPE_COLOR_CODE)
{
// convert signature number to an octal string
for (i=12, j=0, flag=false; i>=0; i-=3)
{
d = (signature>>i)&0x07;
if (d>0 && !flag)
flag = true;
if (flag)
sig[j++] = d + '0';
}
sig[j] = '\0';
sprintf(buf, "CC block! sig: %s (%d decimal) x: %d y: %d width: %d height: %d angle %d", sig, signature, x, y, width, height, angle);
}
else // regular block. Note, angle is always zero, so no need to print
sprintf(buf, "sig: %d x: %d y: %d width: %d height: %d", signature, x, y, width, height);
}*/
uint16_t type;
uint16_t signature;
uint16_t x;
uint16_t y;
uint16_t width;
uint16_t height;
int16_t angle;
};
/**
@brief Creates a connection with Pixy and listens for Pixy messages.
@return 0 Success
@return PIXY_ERROR_USB_IO USB Error: I/O
@return PIXY_ERROR_NOT_FOUND USB Error: Pixy not found
@return PIXY_ERROR_USB_BUSY USB Error: Busy
@return PIXY_ERROR_USB_NO_DEVICE USB Error: No device
*/
int pixy_init();
/**
@brief Indicates when new block data from Pixy is received.
@return 1 New Data: Block data has been updated.
@return 0 Stale Data: Block data has not changed since pixy_get_blocks() was
last called.
*/
int pixy_blocks_are_new();
/**
@brief Copies up to 'max_blocks' number of Blocks to the address pointed
to by 'blocks'.
@param[in] max_blocks Maximum number of Blocks to copy to the address pointed to
by 'blocks'.
@param[out] blocks Address of an array in which to copy the blocks to.
The array must be large enough to write 'max_blocks' number
of Blocks to.
@return Non-negative Success: Number of blocks copied
@return PIXY_ERROR_USB_IO USB Error: I/O
@return PIXY_ERROR_NOT_FOUND USB Error: Pixy not found
@return PIXY_ERROR_USB_BUSY USB Error: Busy
@return PIXY_ERROR_USB_NO_DEVICE USB Error: No device
@return PIXY_ERROR_INVALID_PARAMETER Invalid pararmeter specified
*/
int pixy_get_blocks(uint16_t max_blocks, struct Block * blocks);
int pixy_service();
/**
@brief Send a command to Pixy.
@param[in] name Chirp remote procedure call identifier string.
@return -1 Error
*/
int pixy_command(const char *name, ...);
/**
@brief Terminates connection with Pixy.
*/
void pixy_close();
/**
@brief Send description of pixy error to stdout.
@param[in] error_code Pixy error code
*/
void pixy_error(int error_code);
/**
@brief Set color of pixy LED.
@param[in] red Brightness value for red LED element. [0, 255] 0 = Off, 255 = On
@param[in] green Brightness value for green LED element. [0, 255] 0 = Off, 255 = On
@param[in] blue Brightness value for blue LED element. [0, 255] 0 = Off, 255 = On
@return 0 Success
@return Negative Error
*/
int pixy_led_set_RGB(uint8_t red, uint8_t green, uint8_t blue);
/**
@brief Set pixy LED maximum current.
@param[in] current Maximum current (microamps).
@return 0 Success
@return Negative Error
*/
int pixy_led_set_max_current(uint32_t current);
/**
@brief Get pixy LED maximum current.
@return Non-negative Maximum LED current value (microamps).
@return Negative Error
*/
int pixy_led_get_max_current();
/**
@brief Enable or disable pixy camera auto white balance.
@param value 1: Enable white balance.
0: Disable white balance.
@return 0 Success
@return Negative Error
*/
int pixy_cam_set_auto_white_balance(uint8_t value);
/**
@brief Get pixy camera auto white balance setting.
@return 1 Auto white balance is enabled.
@return 0 Auto white balance is disabled.
@return Negative Error
*/
int pixy_cam_get_auto_white_balance();
/**
@brief Get pixy camera white balance()
@return Composite value for RGB white balance:
white balance = green_value + (red_value << 8) + (blue << 16)
*/
uint32_t pixy_cam_get_white_balance_value();
/**
@brief Set pixy camera white balance.
@param[in] red Red white balance value.
@param[in] green Green white balance value.
@param[in] blue Blue white balance value.
@return 0 Success
@return Negative Error
*/
int pixy_cam_set_white_balance_value(uint8_t red, uint8_t green, uint8_t blue);
/**
@brief Enable or disable pixy camera auto exposure compensation.
@param[in] enable 0: Disable auto exposure compensation.
1: Enable auto exposure compensation.
@return 0 Success
@return Negative Error
*/
int pixy_cam_set_auto_exposure_compensation(uint8_t enable);
/**
@brief Get pixy camera auto exposure compensation setting.
@return 1 Auto exposure compensation enabled.
@return 0 Auto exposure compensation disabled.
@return Negative Error
*/
int pixy_cam_get_auto_exposure_compensation();
/**
@brief Set pixy camera exposure compensation.
@param[in] gain Camera gain.
@param[in] comp Camera exposure compensation.
@return 0 Success
@return Negative Error
*/
int pixy_cam_set_exposure_compensation(uint8_t gain, uint16_t comp);
/**
@brief Get pixy camera exposure compensation.
@param[out] gain Camera gain.
@param[out] comp Camera exposure compensation.
@return 0 Success
@return Negative Error
*/
int pixy_cam_get_exposure_compensation(uint8_t * gain, uint16_t * comp);
/**
@brief Set pixy camera brightness.
@param[in] brightness Brightness value.
@return 0 Success
@return Negative Error
*/
int pixy_cam_set_brightness(uint8_t brightness);
/**
@brief Get pixy camera brightness.
@return Non-negative Brightness value.
@return Negative Error
*/
int pixy_cam_get_brightness();
/**
@brief Get pixy servo axis position.
@param channel Channel value. Range: [0, 1]
@return Position of channel. Range: [0, 999]
@return Negative Error
*/
int pixy_rcs_get_position(uint8_t channel);
/**
@brief Set pixy servo axis position.
@param channel Channel value. Range: [0, 1]
@param position Position value of the channel. Range: [0, 999]
@return 0 Success
@return Negative Error
*/
int pixy_rcs_set_position(uint8_t channel, uint16_t position);
/**
@brief Set pixy servo pulse width modulation (PWM) frequency.
@param frequency Range: [20, 300] Hz Default: 50 Hz
*/
int pixy_rcs_set_frequency(uint16_t frequency);
/**
@brief Get pixy firmware version.
@param[out] major Major version component
@param[out] minor Minor version component
@param[out] build Build identifier
@return 0 Success
@return Negative Error
*/
int pixy_get_firmware_version(uint16_t * major, uint16_t * minor, uint16_t * build);
/*@}*/
#ifdef __cplusplus
}
#endif
#endif
-92
View File
@@ -1,92 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#ifndef __PIXYDEFS_H__
#define __PIXYDEFS_H__
//#include "libusb.h"
//#define PIXY_VID 0xB1AC
//#define PIXY_DID 0xF000
//#define PIXY_DFU_VID 0x1FC9
//#define PIXY_DFU_DID 0x000C
//#define PIXY_ERROR_USB_IO LIBUSB_ERROR_IO
//#define PIXY_ERROR_USB_NOT_FOUND LIBUSB_ERROR_NOT_FOUND
//#define PIXY_ERROR_USB_BUSY LIBUSB_ERROR_BUSY
//#define PIXY_ERROR_USB_NO_DEVICE LIBUSB_ERROR_NO_DEVICE
#define PIXY_ERROR_INVALID_PARAMETER -150
#define PIXY_ERROR_CHIRP -151
#define PIXY_ERROR_INVALID_COMMAND -152
#define CRP_ARRAY 0x80 // bit
#define CRP_FLT 0x10 // bit
#define CRP_NO_COPY (0x10 | 0x20)
#define CRP_NULLTERM_ARRAY (0x20 | CRP_ARRAY) // bits
#define CRP_INT8 0x01
#define CRP_UINT8 0x01
#define CRP_INT16 0x02
#define CRP_UINT16 0x02
#define CRP_INT32 0x04
#define CRP_UINT32 0x04
#define CRP_FLT32 (CRP_FLT | 0x04)
#define CRP_FLT64 (CRP_FLT | 0x08)
#define CRP_STRING (CRP_NULLTERM_ARRAY | CRP_INT8)
#define CRP_TYPE_HINT 0x64 // type hint identifier
#define CRP_INTS8 (CRP_INT8 | CRP_ARRAY)
#define CRP_INTS16 (CRP_INT16 | CRP_ARRAY)
#define CRP_INTS32 (CRP_INT32 | CRP_ARRAY)
#define CRP_UINTS8 CRP_INTS8
#define CRP_UINTS8_NO_COPY (CRP_INTS8 | CRP_NO_COPY)
#define CRP_UINTS16_NO_COPY (CRP_INTS16 | CRP_NO_COPY)
#define CRP_UINTS32_NO_COPY (CRP_INTS32 | CRP_NO_COPY)
#define CRP_UINTS16 CRP_INTS16
#define CRP_UINTS32 CRP_INTS32
#define CRP_FLTS32 (CRP_FLT32 | CRP_ARRAY)
#define CRP_FLTS64 (CRP_FLT64 | CRP_ARRAY)
// regular call args
#define INT8(v) CRP_INT8, v
#define UINT8(v) CRP_INT8, v
#define INT16(v) CRP_INT16, v
#define UINT16(v) CRP_INT16, v
#define INT32(v) CRP_INT32, v
#define UINT32(v) CRP_INT32, v
#define FLT32(v) CRP_FLT32, v
#define FLT64(v) CRP_FLT64, v
#define STRING(s) CRP_STRING, s
#define INTS8(len, a) CRP_INTS8, len, a
#define UINTS8(len, a) CRP_INTS8, len, a
#define UINTS8_NO_COPY(len) CRP_UINTS8_NO_COPY, len
#define UINTS16_NO_COPY(len) CRP_UINTS16_NO_COPY, len
#define UINTS32_NO_COPY(len) CRP_UINTS32_NO_COPY, len
#define INTS16(len, a) CRP_INTS16, len, a
#define UINTS16(len, a) CRP_INTS16, len, a
#define INTS32(len, a) CRP_INTS32, len, a
#define UINTS32(len, a) CRP_INTS32, len, a
#define FLTS32(len, a) CRP_FLTS32, len, a
#define FLTS64(len, a) CRP_FLTS64, len, a
#ifndef END
#ifdef __x86_64__
#define END (int64_t)0
#else
#define END 0
#endif
#endif
#define END_OUT_ARGS END
#define END_IN_ARGS END
#endif
-39
View File
@@ -1,39 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/system/system.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop.
* 2015-04-03 timolang@gmail.com cab8609 Integrated pixy into emulator. Pixy is no longer in the common/libs folder but in emulator/libs and discovery/libs
* 2015-04-25 timolang@gmail.com 3d1e4b2 Simplified code a bit. Emulator does not work stable when replugging pixy.
* 2015-04-25 timolang@gmail.com 0858b0d Fixed some bugs when receiving large data.
*
**************************************************************************************************************************************/
#include "system.h"
#include "ll_system.h"
bool system_init()
{
return ll_system_init();
}
void system_delay(uint32_t msec)
{
ll_system_delay(msec);
}
void system_process()
{
ll_system_process();
}
void system_toggle_led()
{
ll_system_toggle_led();
}
-56
View File
@@ -1,56 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/system/system.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop.
* 2015-04-03 timolang@gmail.com cab8609 Integrated pixy into emulator. Pixy is no longer in the common/libs folder but in emulator/libs and discovery/libs
* 2015-04-25 timolang@gmail.com 3d1e4b2 Simplified code a bit. Emulator does not work stable when replugging pixy.
* 2015-04-25 timolang@gmail.com 0858b0d Fixed some bugs when receiving large data.
* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
*
**************************************************************************************************************************************/
#ifndef SYSTEM_H
#define SYSTEM_H
#include <stdbool.h>
#include <stdint.h>
/**
* @defgroup system System
* The System Module provides access to delay functions, leds and provides a system init function
*/
/*@{*/
/**
* Initializes the system. Call this method at the start of your app_init() function and before using any system_* functions
* @return true on success
*/
bool system_init();
/**
* Sleeps for a certain amount of time
* @param msec The number of milliseconds to sleep
*/
void system_delay(uint32_t msec);
/**
* Executes pending system events (like handling usb, timers etc). Call this somewhere in app_process().
*/
void system_process();
/**
* Toggles a Status Led. Use this function for debugging or to show activity
*/
void system_toggle_led();
/*@}*/
#endif /* SYSTEM_H */
-183
View File
@@ -1,183 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/tft/tft.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator
* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop.
* 2015-04-03 timolang@gmail.com 1aa9194 Fixed Drawing of rects in Emulator. Got frames from pixy to emulator. Slooooow.
* 2015-04-27 aaron@duckpond.ch aed90ef Drawcircle added (emulator)
* 2015-04-27 timolang@gmail.com e249fb2 Added font support
* 2015-04-30 timolang@gmail.com 76ea9d8 Added num up down support.
* 2015-05-10 timolang@gmail.com b6ab7c8 Fixed compiler warning in tft and screen module.
* 2015-05-15 timolang@gmail.com b08a897 Added tft method to draw a bmp from filesystem. Added another font to emulator.
* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules.
*
**************************************************************************************************************************************/
#include "tft.h"
#include "ll_tft.h"
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include "filesystem.h"
/* The idea is as follows:
* Most of the tft_* functions can be forwarded to the lowlevel implementation.
* The exceptions are commented below.
* Make sure to have a look at the doxygen comments for the lowlevel functions and for the tft_* functions
*/
/* Possible improvements:
* For formatted printing implement putchar, instead of writing into a buffer and drawing that buffer afterwards
*/
bool tft_init()
{
return ll_tft_init();
}
void tft_clear(uint16_t color)
{
ll_tft_clear(color);
}
void tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{
ll_tft_draw_line(x1, y1, x2, y2, color);
}
void tft_draw_pixel(uint16_t x, uint16_t y, uint16_t color)
{
ll_tft_draw_pixel(x, y, color);
}
void tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{
//could be implemented with 4 lines instead of introducing a ll func
ll_tft_draw_rectangle(x1, y1, x2, y2, color);
}
void tft_fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{
ll_tft_fill_rectangle(x1, y1, x2, y2, color);
}
void tft_draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t* dat)
{
ll_tft_draw_bitmap_unscaled(x, y, width, height, dat);
}
void tft_draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color)
{
ll_tft_draw_circle(x, y, r, color);
}
uint8_t tft_num_fonts()
{
return ll_tft_num_fonts();
}
uint8_t tft_font_height(uint8_t fontnum)
{
return ll_tft_font_height(fontnum);
}
uint8_t tft_font_width(uint8_t fontnum)
{
return ll_tft_font_width(fontnum);
}
//Print line can be done with multiple calls to draw_char
void tft_print_line(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, const char* text)
{
if (font >= ll_tft_num_fonts()) {
return; //invalid font index
}
for (int i = 0; i < strlen(text); i++) { //for each char in the line
ll_tft_draw_char(x, y, color, bgcolor, font, text[i]); //draw the char
x += ll_tft_font_width(font); //and increase the x position
}
}
//Printing a formatted line can be done by printing the line in a buffer using "sprintf" and then calling print_line
void tft_print_formatted(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, const char* format, ...)
{
static char buffer[128]; //buffer to save the formatted text into
//Since we have variable arguments, we need to forward them. We have to use vsprintf instead of sprintf for that.
va_list args;
va_start(args, format); //start the varg-list
vsprintf(buffer, format, args); //let vsprintf render the formatted string
tft_print_line(x, y, color, bgcolor, font, buffer); //print the string as normal text
va_end(args); //end the varg-list
}
bool tft_draw_bitmap_file_unscaled(uint16_t x, uint16_t y, const char* filename)
{
//This method reads a .bmp file from the filesystem and tries to draw it.
//Note: The bmp implementation is not complete, it has some limitations and it makes assumptions. See doxygen comment for this method.
//Source Copied and adapted from: http://stackoverflow.com/a/17040962/2606757
FILE_HANDLE* file = filesystem_file_open(filename); //try to open the file
if (file == NULL) { //file opening failed
return false;
}
unsigned char info[54];
if (filesystem_file_read(file, info, 54) != F_OK) { //try to read the 54 byte header
filesystem_file_close(file);
return false; //reading the header failed
}
// extract image height and width from header
uint32_t width = *(uint32_t*)&info[18]; //width in pixel
uint32_t height = *(uint32_t*)&info[22]; //height in pixel
uint16_t depth = *(uint16_t*)&info[28]; //bit's per pixel (color depth)
depth /= 8; //we want the number of bytes per pixel
filesystem_file_seek(file, *(uint32_t*)&info[10]); //seek to the place where img data begins
uint32_t row_padded = (width * depth + 3) & (~3); //row size must be aligned to 4 bytes
unsigned char data [row_padded]; //allocate space for one row (incl. padding)
for (int i = 0; i < height; i++) { //for each row
filesystem_file_read(file, data, row_padded); //read row into buffer
for (int j = 0; j < width * depth; j += depth) { //for each pixel
unsigned char a, r, g, b;
if (depth == 4) { //a,r,g,b 8bit each
a = data[j];
r = data[j + 1];
g = data[j + 2];
b = data[j + 3];
} else if (depth == 3) { // b,g,r, 8bit each
a = 255;
r = data[j + 2];
g = data[j + 1];
b = data[j];
}
if (a != 0) {
//bmp's are stored "bottom-up", so we start drawing at the bottom
tft_draw_pixel(x + j / depth, y + height - 1 - i, RGB(r, g, b));
}
}
}
filesystem_file_close(file);
return true;
}
-197
View File
@@ -1,197 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/tft/tft.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator
* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop.
* 2015-04-03 timolang@gmail.com 1aa9194 Fixed Drawing of rects in Emulator. Got frames from pixy to emulator. Slooooow.
* 2015-04-27 aaron@duckpond.ch aed90ef Drawcircle added (emulator)
* 2015-04-27 timolang@gmail.com e249fb2 Added font support
* 2015-04-30 timolang@gmail.com 76ea9d8 Added num up down support.
* 2015-05-04 aaron@duckpond.ch c224d40 Changed display init
* 2015-05-10 timolang@gmail.com 21edc56 Added doxyfile (doxygen) for the common folder. Started with doxygen comments for app and tft module.
* 2015-05-11 timolang@gmail.com a175a2f Added doxygen docu for touch module
* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure
* 2015-05-12 timolang@gmail.com 1402598 Added doxygen stuff for button module and some minor changes to touch, screen_main and tft module.
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
* 2015-05-15 timolang@gmail.com b08a897 Added tft method to draw a bmp from filesystem. Added another font to emulator.
*
**************************************************************************************************************************************/
#ifndef TFT_H
#define TFT_H
#include<stdbool.h>
#include<stdint.h>
/**
* @defgroup tft TFT
* The TFT Modul provides access to the display
*/
/**
* @addtogroup tft
*/
/*@{*/
/**
* Creates a 16bit color from 8bit * 3 colors (r,g,b)
* @return
*/
#define RGB(r,g,b) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | (((b) & 0xF8) >> 3))
#define RED RGB(255,0,0)
#define GREEN RGB(0,255,0)
#define BLUE RGB(0,0,255)
#define WHITE 0xF7BE
#define BLACK RGB(0,0,0)
/**
* Creates a 16bit color from a 24bit hex rgb color code
* @return
*/
#define HEX(h) (RGB(((h)>>16),((h)>>8),(h)))
/**
* Transparent color
* @return
*/
#define TRANSPARENT ((uint16_t)0x80C2)
/**
* Initializes the display.
* Call this method before using any tft_* functions
* @return true on success
*/
bool tft_init();
/**
* Clears the entire display with the given color. Overpaints everything which was there before.
* @param color The 16-bit color to clear the display with.
*/
void tft_clear(uint16_t color);
/**
* Draws a line onto the display. The pixels specified by start/end point are inclusive!
* @param x1 The x-Coordinate of the start-point
* @param y1 The y-Coordinate of the start-point
* @param x2 The x-Coordinate of the end-point
* @param y2 The y-Coordinate of the end-point
* @param color The 16-bit color to draw the line with
*/
void tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
/**
* Draws a pixel onto the display.
* @param x The x-Coordinate of the pixel
* @param y The y-Coordinate of the pixel
* @param color The 16-bit color to draw the pixel with
*/
void tft_draw_pixel(uint16_t x, uint16_t y, uint16_t color);
/**
* Draws the outline of a rectangle onto the display.
* The outline is one pixel wide and goes through the specified start and endpoint.
* @param x1 The x-Coordinate of the start-point
* @param y1 The y-Coordinate of the start-point
* @param x2 The x-Coordinate of the end-point
* @param y2 The y-Coordinate of the end-point
* @param color The 16-bit color to draw the pixel with
*/
void tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
/**
* Draws a filled rectangle onto the display. The start,end points are inclusive
* @param x1 The x-Coordinate of the start-point
* @param y1 The y-Coordinate of the start-point
* @param x2 The x-Coordinate of the end-point
* @param y2 The y-Coordinate of the end-point
* @param color The 16-bit color to draw the pixel with
*/
void tft_fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
/**
* Draws a bitmap onto the display without scaling/cropping.
* The bitmap must be provided as an array of 16-bit colors
* @param x The x-coordinate of the top-left corner to draw the bitmap at
* @param y The y-coordinate of the top-left corner to draw the bitmap at
* @param width The width of the bitmap in pixels
* @param height The height of the bitmap in pixels
* @param dat A pointer to a uint16_t array containing the colors for each pixel. Starting in the topleft and going from left to right, line by line.
*/
void tft_draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t* dat);
/**
* Draws a bitmap from the filesystem onto the display without scaling/cropping
* The bitmap must be saved in the windows bitmap format (.bmp) without compression and with 24 (b,g,r) or 32 (a,r,g,b) bits per pixel
* @param x The x-coordinate of the top-left corner to draw the bitmap at
* @param y The y-coordinate of the top-left corner to draw the bitmap at
* @param filename The absolute path to the .bmp file
* @return true on success
*/
bool tft_draw_bitmap_file_unscaled(uint16_t x, uint16_t y, const char* filename);
/**
* Draws the outline of a circle onto the display
* @param x The x-Coordinate of the center point
* @param y The y-Coordinate of the center point
* @param r The Radius in Pixels
* @param color The 16-Bit color to draw the circle with
*/
void tft_draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color);
/**
* Queries the number of available fonts
* @return
*/
uint8_t tft_num_fonts();
/**
* Get the height of a font
* @param fontnum The number of the font, from 0 .. (num_fonts -1)
* @return The height in pixel
*/
uint8_t tft_font_height(uint8_t fontnum);
/**
* Get the width of a font
* @param fontnum The number of the font, from 0 .. (num_fonts -1)
* @return The width in pixel
*/
uint8_t tft_font_width(uint8_t fontnum);
/**
* Prints a unformatted/preformatted string onto the display
* @param x The x-Coordinate of the Top-Left corner where the text should be drawn
* @param y The y-Coordinate of the Top-Left corner where the text should be drawn
* @param color The 16-bit foreground color of the text
* @param bgcolor The 16-bit background color of the text. You may pass TRANSPARENT as Color
* @param font The Fontnum to use for drawing
* @param text The text to draw
*/
void tft_print_line(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, const char* text);
/**
* Prints a formatted text (like printf) onto the display
* @param x The x-Coordinate of the Top-Left corner where the text should be drawn
* @param y The y-Coordinate of the Top-Left corner where the text should be drawn
* @param color The 16-bit foreground color of the text
* @param bgcolor The 16-bit background color of the text. You may pass TRANSPARENT as Color
* @param font The Fontnum to use for drawing
* @param format The format string (like printf)
* @param ... The arguments to format (like printf)
*/
void tft_print_formatted(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, const char* format, ...);
/*@}*/
#endif /* TFT_H */
-121
View File
@@ -1,121 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/touch/screen_calibrate.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-06-01 timolang@gmail.com 06227da Added calibrate screen (WIP). fixed bug in emulator drawing.
* 2015-06-01 timolang@gmail.com eb573bc Finalized calibration. Fixed a bug in screen module.
*
**************************************************************************************************************************************/
#include "screen_calibrate.h"
#include "tft.h"
#include "touch.h"
extern volatile bool calibration; //from touch.c
static void enter(void* screen)
{
tft_clear(BLACK);
}
static void leave(void* screen)
{
}
static void update(void* screen)
{
int x1, y1, x2, y2, dx, dy;
tft_print_line(50, 50, WHITE, BLACK, 1, "Calibration:");
tft_print_line(50, 120, WHITE, BLACK, 0, "Hit the markers exactly!");
//-----------------First Point--------------------
tft_draw_line(CCENTER, CBEGIN, CCENTER, CEND, WHITE); //Draw Cross
tft_draw_line(CBEGIN, CCENTER, CEND, CCENTER, WHITE); //Draw Cross
calibration = 1; //TouchX + TouchY Values will not be converted to Pixels
while (calibration); //Wait on PenUp
POINT_STRUCT p1 = touch_get_last_point();
x1 = p1.x;
y1 = p1.y;
tft_fill_rectangle(CBEGIN, CBEGIN, CEND, CEND, BLACK); //Clear Cross
//-----------------Second Point-------------------
tft_draw_line(DWIDTH - CCENTER, DHEIGHT - CBEGIN, DWIDTH - CCENTER, DHEIGHT - CEND, WHITE);
tft_draw_line(DWIDTH - CBEGIN, DHEIGHT - CCENTER, DWIDTH - CEND, DHEIGHT - CCENTER, WHITE);
calibration = 1;
while (calibration);
POINT_STRUCT p2 = touch_get_last_point();
x2 = p2.x;
y2 = p2.y;
tft_fill_rectangle(DWIDTH - CBEGIN, DHEIGHT - CBEGIN, DWIDTH - CEND, DHEIGHT - CEND, BLACK);
//-----------------Third Point--------------------
tft_draw_line(CCENTER, DHEIGHT - CBEGIN, CCENTER, DHEIGHT - CEND, WHITE);
tft_draw_line(CBEGIN, DHEIGHT - CCENTER, CEND, DHEIGHT - CCENTER, WHITE);
calibration = 1;
while (calibration);
POINT_STRUCT p3 = touch_get_last_point();
x1 += p3.x; //Add(!) values. We'll build the average later
y2 += p3.y;
tft_fill_rectangle(CBEGIN, DHEIGHT - CBEGIN, CEND, DHEIGHT - CEND, BLACK);
//------------------4. Point---------------------
tft_draw_line(DWIDTH - CCENTER, CBEGIN, DWIDTH - CCENTER, CEND, WHITE);
tft_draw_line(DWIDTH - CBEGIN, CCENTER, DWIDTH - CEND, CCENTER, WHITE);
calibration = 1;
while (calibration);
POINT_STRUCT p4 = touch_get_last_point();
x2 += p4.x;
y1 += p4.y;
tft_fill_rectangle(DWIDTH - CBEGIN, CBEGIN, DWIDTH - CEND, CEND, BLACK);
//-------------------Calculation---------------------
x1++; //Add 1 and divide by 2 later = +0.5 (for correct rounding)
y1++;
x2++;
y2++;
x1 >>= 1; //Divide by 2
y1 >>= 1;
x2 >>= 1;
y2 >>= 1;
dx = (x2 - x1); //Build the Difference
dy = (y2 - y1);
touch_set_calibration_values(x1, dx, y1, dy);
tft_print_line(50, 120, WHITE, BLACK, 0, "Calibration Done. Press anywhere");
calibration = 1;
while (calibration);
gui_screen_back();
}
static SCREEN_STRUCT screen = {
enter,
leave,
update
};
SCREEN_STRUCT* get_screen_calibrate()
{
return &screen;
}
-47
View File
@@ -1,47 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/touch/screen_calibrate.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-06-01 timolang@gmail.com 06227da Added calibrate screen (WIP). fixed bug in emulator drawing.
* 2015-06-01 timolang@gmail.com eb573bc Finalized calibration. Fixed a bug in screen module.
*
**************************************************************************************************************************************/
#include "screen.h"
/**
* @addtogroup touch
*/
/*@{*/
/**
* @defgroup calibrate Calibrate (Screen)
* The calibrate screen for the touch module
*/
/*@{*/
/**
* Returns a pointer to the calibrate screen
* \sa gui_screen_navigate
* @return
*/
SCREEN_STRUCT* get_screen_calibrate();
/*@}*/
/*@}*/
//TODO: Move this define to a common accessible, but private header file (they are used by screen_calibrate.c and touch.c)
#define CCENTER 20 //Pixel Distance from Sides for Calibration Cross
#define CLENGTH 10 //Length of the Calibration Cross Lines
#define CBEGIN (CCENTER-CLENGTH/2)
#define CEND (CCENTER + CLENGTH/2)
#define DWIDTH 320 //TODO: move define to tft module or make a function out of it
#define DHEIGHT 240 //TODO: move define to tft module or make a function out of it
-214
View File
@@ -1,214 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/touch/touch.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com 259d446 Added touch support to emulator. Implemented basic touch function.
* 2015-05-02 timolang@gmail.com 3281616 Added some more touch functions. Improved pixy test. Drag the Image around!
* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules.
* 2015-06-01 timolang@gmail.com 06227da Added calibrate screen (WIP). fixed bug in emulator drawing.
* 2015-06-01 timolang@gmail.com eb573bc Finalized calibration. Fixed a bug in screen module.
* 2015-06-06 timolang@gmail.com c06661d Fixed some outdated comments in source code. Documented Gui Module in docu.
*
**************************************************************************************************************************************/
#include "touch.h"
#include "ll_touch.h"
#include "screen_calibrate.h"
#include <stdio.h>
/* The idea is as follows:
* The user can add "touch-areas" which basically represent a rectangles on the screen.
* Once the user touches such a rectangle with the pen, we forward events to his provided callback.
* Touch events are provided to us from the low level implementation via touch_add_raw_event().
* We then need to check which touch areas are effected by that event
*/
/* Possible improvements:
* Exchange pointer-list "areas" with a linked list. This would ensure that we can always accept new regions
*/
#define NUM_AREAS 50 //Number of Touch Areas we can manage
TOUCH_AREA_STRUCT* areas[NUM_AREAS] = {NULL}; //list with pointers to all managed touch area's
volatile POINT_STRUCT pos; //the last touch point
volatile TOUCH_STATE oldState = TOUCH_UP; //the last touch state
volatile bool calibration = false; //whether or not we're currently calibrating
bool use_calibration = false; //Whether or not the current platform needs calibration and recalc of the values
//Calibration parameters (dummy values).
int cal_xs = 10;
int cal_dx = 100;
int cal_ys = 10;
int cal_dy = 100;
void touch_set_calibration_values(int xs, int dx, int ys, int dy)
{
cal_xs = xs;
cal_ys = ys;
cal_dx = dx;
cal_dy = dy;
}
bool touch_init()
{
return ll_touch_init();
}
void touch_set_value_convert_mode(bool uc)
{
use_calibration = uc;
}
bool touch_add_raw_event(uint16_t touchX, uint16_t touchY, TOUCH_STATE state)
{
//Update current and old position/state
bool penDown = (state == TOUCH_DOWN);
bool oldPenDown = (oldState == TOUCH_DOWN);
oldState = state;
if (calibration) { //If in Calibration mode
if (penDown) {
pos.x = touchX;
pos.y = touchY;
} else {
if (oldPenDown) { //Run only if we got at least one pen down
calibration = 0; //Calibration finish (Touch X and Y are the values from the last measure, where the pen was down)
}
}
return true;
}
//If we reach this point we're not in calibration mode and we need to process the event and call the registred handlers..
if (use_calibration) { //the underlying touch hardware uses calibration
//Calculate the real touch position out of the passed ones, and the calibration values
pos.x = touchX = (((long)(DWIDTH - 2 * CCENTER) * 2 * (long)((long)touchX - cal_xs) / cal_dx + 1) >> 1) + CCENTER;
pos.y = touchY = (((long)(DHEIGHT - 2 * CCENTER) * 2 * (long)((long)touchY - cal_ys) / cal_dy + 1) >> 1) + CCENTER;
} else { //no conversion needed for the underlying hardware
pos.x = touchX;
pos.y = touchY;
}
if (penDown) { //pen is down now
//tft_draw_pixel(touchX,touchY,WHITE);
if (!oldPenDown) { //pen wasn't down before (positive edge) => First Touch
for (int z = 0; z < NUM_AREAS; z++) { // For every touch area
//Check if pos is inside area
if (areas[z] != NULL && touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2) {
areas[z]->flags = 1; //Save PenInside=1
if (areas[z]->hookedActions & PEN_DOWN) { //The user wants to receive pen down events
areas[z]->callback(areas[z], PEN_DOWN); //Send event to user callback
}
}
}
} else { //Pen was down before => Second, Third event in row
for (int z = 0; z < NUM_AREAS; z++) { // For every touch area
if (areas[z] != NULL) {
//Check if pos is inside area
if (touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2) {
if (areas[z]->flags == 0) { //Pen was not inside before (PenInside==0)
areas[z]->flags = 1; //Pen is inside now (PenInside=1)
if (areas[z]->hookedActions & PEN_ENTER) { //The user wants to receive pen enter events
areas[z]->callback(areas[z], PEN_ENTER);
}
}
} else if (areas[z]->flags) { //Pos not inside area, but it was before (PenInside==1)
areas[z]->flags = 0; //Pen is no longer inside (PenInside=0)
if (areas[z]->hookedActions & PEN_LEAVE) { //The user wants to receive pen leave events
areas[z]->callback(areas[z], PEN_LEAVE);
}
}
}
}
}
for (int z = 0; z < NUM_AREAS; z++) { // For every touch area
if (areas[z] != NULL && (areas[z]->hookedActions & PEN_MOVE)) { //User want's to receive pen move events
//Check if pos is inside area
if (touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2) {
areas[z]->callback(areas[z], PEN_MOVE);
}
}
}
} else { //pen is not down now
if (oldPenDown) { //but it was down before (negative edge)
for (int z = 0; z < NUM_AREAS; z++) { // For every touch area
//Check if pos is inside area
if (areas[z] != NULL && touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2) {
areas[z]->flags = 0; //The pen is no longer inside (PenInside = 0);
if (areas[z]->hookedActions & PEN_UP) { //user want's to receive pen up events
areas[z]->callback(areas[z], PEN_UP);
}
}
}
}
}
return true;
}
bool touch_have_empty(unsigned char num)
{
//go through pointer array and check for free spaces
for (unsigned char i = 0; i < NUM_AREAS; i++) {
if (areas[i] == NULL) {
num--; //a free space was found, we need one less
}
if (num == 0) {
return true; //enough free spaces found
}
}
return false; //not enough free spaces found
}
bool touch_register_area(TOUCH_AREA_STRUCT* area)
{
//go through pointer array and check for free space
for (unsigned char i = 0; i < NUM_AREAS; i++) {
if (areas[i] == NULL) { //free space found
area->flags = 0; //we start with empty flags (PenInside=0)
areas[i] = area; //save pointer into list
return true;
}
}
return false; //no free space found
}
void touch_unregister_area(TOUCH_AREA_STRUCT* area)
{
if (area == NULL) {
return;
}
//go through pointer array and find the area to remove
for (unsigned char i = 0; i < NUM_AREAS; i++) {
if (areas[i] == area) { //area found in pointer array at pos i
areas[i] = NULL; //set pointer in list to NULL again
break;
}
}
}
POINT_STRUCT touch_get_last_point()
{
return pos;
}
-153
View File
@@ -1,153 +0,0 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/touch/touch.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator
* 2015-04-27 timolang@gmail.com 259d446 Added touch support to emulator. Implemented basic touch function.
* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
* 2015-05-02 timolang@gmail.com 3281616 Added some more touch functions. Improved pixy test. Drag the Image around!
* 2015-05-11 timolang@gmail.com a175a2f Added doxygen docu for touch module
* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure
* 2015-05-12 timolang@gmail.com 1402598 Added doxygen stuff for button module and some minor changes to touch, screen_main and tft module.
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
* 2015-06-01 timolang@gmail.com 06227da Added calibrate screen (WIP). fixed bug in emulator drawing.
* 2015-06-01 timolang@gmail.com eb573bc Finalized calibration. Fixed a bug in screen module.
*
**************************************************************************************************************************************/
#ifndef TOUCH_H
#define TOUCH_H
#include<stdbool.h>
#include<stdint.h>
/**
* @defgroup touch Touch
* The Touch module provides access to the touch controller, and executes a callback if a certain region is touched
*/
/**
* @addtogroup touch
*/
/*@{*/
/**
Enum to describe the current Touch State. \sa touch_add_raw_event
*/
typedef enum {
TOUCH_UP, //!< The display is currently not touched
TOUCH_DOWN //!< The display is currently touched at some point
} TOUCH_STATE ;
/**
* Enum to describe the hooked actions for which you want to receive events for.
* You can OR-combine them. \sa touch_register_area
*/
typedef enum {
NONE = 0x00, //!< Do not receive any events
PEN_DOWN = 0x01, //!< Receive an event when the pen goes down inside the region
PEN_UP = 0x02, //!< Receive an event when the pen goes up inside the region
PEN_ENTER = 0x04, //!< Receive an event when the pen enters the region (pen was down before)
PEN_LEAVE = 0x08, //!< Receive an event when the pen leaves the region (pen was inside region before)
PEN_MOVE = 0x10 //!< Receive an event when the pen moves inside the region (pen is down)
} TOUCH_ACTION;
/**
* Prototype for Event Listeners (called for every occurring, hooked action)
* \note You should NOT execute long running things in this callback nor should you update the gui. But you can call gui_screen_navigate() for instance.
* @param touchArea The pointer to the TOUCH_AREA_STRUCT in which the event occurred
* @param triggeredAction The Action which occurred
*/
typedef void (*TOUCH_CALLBACK)(void* touchArea, TOUCH_ACTION triggeredAction);
/**
* Structure to configure a Touch Area
*/
typedef struct {
TOUCH_ACTION hookedActions; //!< Actions to listen to
uint16_t x1; //!< Top Left X-Coordinate of Area
uint16_t y1; //!< Top Left Y-Coordinate of Area
uint16_t x2; //!< Bottom Right X-Coordinate of Area
uint16_t y2; //!< Bottom Right Y-Coordinate of Area
TOUCH_CALLBACK callback; //!< Callback which is executed when an event occurred in this Area.
uint8_t flags; //!< For internal use, don't change, don't initialize
} TOUCH_AREA_STRUCT;
/**
* Struct which represents a 2D point on the display
*/
typedef struct {
uint16_t x; //!< The X-Coordinate of the point
uint16_t y; //!< The Y-Coordinate of the point
} POINT_STRUCT;
/**
* Initializes the Touch Controller.
* Call this method before using any touch_* functions
* @return true on success
*/
bool touch_init();
/**
* Processes a native touch event.
* Call this function when the pen goes down (\ref TOUCH_DOWN), when it moves (\ref TOUCH_DOWN) and also when it goes up again (\ref TOUCH_UP)!
* It's safe to call this function from an (SPI)-Interrupt.
* @param x The x-Coordinate of the touch event
* @param y The y-Coordinate of the touch event
* @param state Whether the pen is up or down
* @return True on success
*/
bool touch_add_raw_event(uint16_t x, uint16_t y, TOUCH_STATE state);
/**
* Checks whether or not we have memory to manage and track additional \p num TOUCH_AREA_STRUCT%s
* @param num The number of touch areas you would like to allocate
* @return True if there's enough memory to allocate num TOUCH_AREAs
*/
bool touch_have_empty(unsigned char num);
/**
* Registers a new touch Area. You will receive events for this area from now on.
* @param area A pointer to the configured TOUCH_AREA_STRUCT
* @return True if everything was successful and the corresponding Touch Area will be monitored from now on
*/
bool touch_register_area(TOUCH_AREA_STRUCT* area);
/**
* Unregisters a touch area. You will no longer receive events for this area
* @param area A pointer to the TOUCH_AREA_STRUCT instance
*/
void touch_unregister_area(TOUCH_AREA_STRUCT* area);
/**
* Gets the last touched point
* @return The Coordinates of the last touched points
*/
POINT_STRUCT touch_get_last_point();
/**
* Set's the new calibration values
* @param xs x offset (to calibration point 1)
* @param dx x difference (between calibration point 1 and 2)
* @param ys y offset (to calibration point 1)
* @param dy y difference (between calibration point 1 and 2)
*/
void touch_set_calibration_values(int xs, int dx, int ys, int dy);
/**
* Set's the new value convert mode. Per default use_calibration is false.
* @param use_calibration whether or not the current platform needs display calibration
*/
void touch_set_value_convert_mode(bool use_calibration);
/*@}*/
#endif /* TOUCH_H */
-2
View File
@@ -1,2 +0,0 @@
obj
*.a
-59
View File
@@ -1,59 +0,0 @@
#2015 by tmoe, id10101 (and the internet :) )
TARGET=libpixy
#Tools
CROSS_COMPILE=arm-none-eabi-
CC=$(CROSS_COMPILE)g++
AR=$(CROSS_COMPILE)ar
RMDIR = rm -rf
RM=rm -f
MKDIR=mkdir -p
#Directories
SRC_DIR=./src
INC_DIR=../../../common/pixy
OBJ_DIR=./obj
#Architecture flags
FP_FLAGS?=-mfpu=fpv4-sp-d16 -mfloat-abi=softfp
ARCH_FLAGS=-mthumb -mcpu=cortex-m4 $(FP_FLAGS)
#Compiler, Linker Options
CPPFLAGS=-I$(INC_DIR) -D__LINUX__=1 -DHOST=1 #-DDEBUG=1
CFLAGS=$(ARCH_FLAGS) -O0 -g -fdata-sections -ffunction-sections
#CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork
#CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
#Finding Input files
CFILES=$(shell find $(SRC_DIR) -name '*.cpp')
#Generate corresponding obj names
COBJS=$(CFILES:.cpp=.o)
OBJS=$(patsubst $(SRC_DIR)/%,$(OBJ_DIR)/%,$(COBJS))
#Keep the objects files
.SECONDARY: $(OBJS)
#Mark targets which are not "file-targets"
.PHONY: all clean
# List of all binaries to build
all: $(TARGET).a
#objects to lib
%.a : $(OBJS)
@echo Linking...
$(AR) rcs $@ $^
#C files to objects
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
@echo Compiling $<...
$(MKDIR) $(OBJ_DIR)
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
#Clean Obj files and builded stuff
clean:
$(RMDIR) $(OBJ_DIR)
$(RM) $(TARGET).a
-150
View File
@@ -1,150 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include "pixy.h"
#define BLOCK_BUFFER_SIZE 25
// Pixy Block buffer //
struct Block blocks[BLOCK_BUFFER_SIZE];
static bool run_flag = true;
void handle_SIGINT(int unused)
{
// On CTRL+C - abort! //
run_flag = false;
}
int main(int argc, char * argv[])
{
int i = 0;
int index;
int blocks_copied;
int pixy_init_status;
char buf[128];
// Catch CTRL+C (SIGINT) signals //
signal(SIGINT, handle_SIGINT);
printf("Hello Pixy:\n libpixyusb Version: %s\n", __LIBPIXY_VERSION__);
// Connect to Pixy //
pixy_init_status = pixy_init();
// Was there an error initializing pixy? //
if(pixy_init_status != 0)
{
// Error initializing Pixy //
printf("pixy_init(): ");
pixy_error(pixy_init_status);
return pixy_init_status;
}
// Request Pixy firmware version //
{
uint16_t major;
uint16_t minor;
uint16_t build;
int return_value;
return_value = pixy_get_firmware_version(&major, &minor, &build);
if (return_value) {
// Error //
printf("Failed to retrieve Pixy firmware version. ");
pixy_error(return_value);
return return_value;
} else {
// Success //
printf(" Pixy Firmware Version: %d.%d.%d\n", major, minor, build);
}
}
#if 0
// Pixy Command Examples //
{
int32_t response;
int return_value;
// Execute remote procedure call "cam_setAWB" with one output (host->pixy) parameter (Value = 1)
//
// Parameters: Notes:
//
// pixy_command("cam_setAWB", String identifier for remote procedure
// 0x01, Length (in bytes) of first output parameter
// 1, Value of first output parameter
// 0, Parameter list seperator token (See value of: END_OUT_ARGS)
// &response, Pointer to memory address for return value from remote procedure call
// 0); Parameter list seperator token (See value of: END_IN_ARGS)
//
// Enable auto white balance //
pixy_command("cam_setAWB", UINT8(0x01), END_OUT_ARGS, &response, END_IN_ARGS);
// Execute remote procedure call "cam_getAWB" with no output (host->pixy) parameters
//
// Parameters: Notes:
//
// pixy_command("cam_setAWB", String identifier for remote procedure
// 0, Parameter list seperator token (See value of: END_OUT_ARGS)
// &response, Pointer to memory address for return value from remote procedure call
// 0); Parameter list seperator token (See value of: END_IN_ARGS)
//
// Get auto white balance //
return_value = pixy_command("cam_getAWB", END_OUT_ARGS, &response, END_IN_ARGS);
// Set auto white balance back to disabled //
pixy_command("cam_setAWB", UINT8(0x00), END_OUT_ARGS, &response, END_IN_ARGS);
}
#endif
printf("Detecting blocks...\n");
while(run_flag)
{
// Wait for new blocks to be available //
while(!pixy_blocks_are_new() && run_flag) {
pixy_service();
}
// Get blocks from Pixy //
blocks_copied = pixy_get_blocks(BLOCK_BUFFER_SIZE, &blocks[0]);
if(blocks_copied < 0) {
// Error: pixy_get_blocks //
printf("pixy_get_blocks(): ");
pixy_error(blocks_copied);
}
// Display received blocks //
printf("frame %d:\n", i);
for(index = 0; index != blocks_copied; ++index) {
blocks[index].print(buf);
printf(" %s\n", buf);
}
i++;
}
pixy_close();
}
-549
View File
@@ -1,549 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
//#include <new>
#ifdef PIXY
#include "pixy_init.h"
#include "exec.h"
#else
#include "debug.h"
#endif
#include "blob.h"
#ifdef DEBUG
#ifndef HOST
#include <textdisp.h>
#else
#include <stdio.h>
#endif
#define DBG_BLOB(x) x
#else
#define DBG_BLOB(x)
#endif
bool CBlob::recordSegments= false;
// Set to true for testing code only. Very slow!
bool CBlob::testMoments= false;
// Skip major/minor axis computation when this is false
bool SMoments::computeAxes= false;
int CBlob::leakcheck=0;
#ifdef INCLUDE_STATS
void SMoments::GetStats(SMomentStats &stats) const {
stats.area= area;
stats.centroidX = (float)sumX / (float)area;
stats.centroidY = (float)sumY / (float)area;
if (computeAxes) {
// Find the eigenvalues and eigenvectors for the 2x2 covariance matrix:
//
// | sum((x-|x|)^2) sum((x-|x|)*(y-|y|)) |
// | sum((x-|x|)*(y-|y|)) sum((y-|y|)^2) |
// Values= 0.5 * ((sumXX+sumYY) +- sqrt((sumXX+sumYY)^2-4(sumXXsumYY-sumXY^2)))
// .5 * (xx+yy) +- sqrt(xx^2+2xxyy+yy^2-4xxyy+4xy^2)
// .5 * (xx+yy) +- sqrt(xx^2-2xxyy+yy^2 + 4xy^2)
// sum((x-|x|)^2) =
// sum(x^2) - 2sum(x|x|) + sum(|x|^2) =
// sum(x^2) - 2|x|sum(x) + n|x|^2 =
// sumXX - 2*centroidX*sumX + centroidX*sumX =
// sumXX - centroidX*sumX
// sum((x-|x|)*(y-|y|))=
// sum(xy) - sum(x|y|) - sum(y|x|) + sum(|x||y|) =
// sum(xy) - |y|sum(x) - |x|sum(y) + n|x||y| =
// sumXY - centroidY*sumX - centroidX*sumY + sumX * centroidY =
// sumXY - centroidX*sumY
float xx= sumXX - stats.centroidX*sumX;
float xyTimes2= 2*(sumXY - stats.centroidX*sumY);
float yy= sumYY - stats.centroidY*sumY;
float xxMinusyy = xx-yy;
float xxPlusyy = xx+yy;
float sq = sqrt(xxMinusyy * xxMinusyy + xyTimes2*xyTimes2);
float eigMaxTimes2= xxPlusyy+sq;
float eigMinTimes2= xxPlusyy-sq;
stats.angle= 0.5*atan2(xyTimes2, xxMinusyy);
//float aspect= sqrt(eigMin/eigMax);
//stats.majorDiameter= sqrt(area/aspect);
//stats.minorDiameter= sqrt(area*aspect);
//
// sqrt(eigenvalue/area) is the standard deviation
// Draw the ellipse with radius of twice the standard deviation,
// which is a diameter of 4 times, which is 16x inside the sqrt
stats.majorDiameter= sqrt(8.0*eigMaxTimes2/area);
stats.minorDiameter= sqrt(8.0*eigMinTimes2/area);
}
}
void SSegment::GetMomentsTest(SMoments &moments) const {
moments.Reset();
int y= row;
for (int x= startCol; x <= endCol; x++) {
moments.area++;
moments.sumX += x;
moments.sumY += y;
if (SMoments::computeAxes) {
moments.sumXY += x*y;
moments.sumXX += x*x;
moments.sumYY += y*y;
}
}
}
#endif
///////////////////////////////////////////////////////////////////////////
// CBlob
CBlob::CBlob()
{
DBG_BLOB(leakcheck++);
// Setup pointers
firstSegment= NULL;
lastSegmentPtr= &firstSegment;
// Reset blob data
Reset();
}
CBlob::~CBlob()
{
DBG_BLOB(leakcheck--);
// Free segments, if any
Reset();
}
void
CBlob::Reset()
{
// Clear blob data
moments.Reset();
// Empty bounds
right = -1;
left = top = 0x7fff;
lastBottom.row = lastBottom.invalid_row;
nextBottom.row = nextBottom.invalid_row;
// Delete segments if any
SLinkedSegment *tmp;
while(firstSegment!=NULL) {
tmp = firstSegment;
firstSegment = tmp->next;
delete tmp;
}
lastSegmentPtr= &firstSegment;
}
void
CBlob::NewRow()
{
if (nextBottom.row != nextBottom.invalid_row) {
lastBottom= nextBottom;
nextBottom.row= nextBottom.invalid_row;
}
}
void
CBlob::Add(const SSegment &segment)
{
// Enlarge bounding box if necessary
UpdateBoundingBox(segment.startCol, segment.row, segment.endCol);
// Update next attachment "surface" at bottom of blob
if (nextBottom.row == nextBottom.invalid_row) {
// New row.
nextBottom= segment;
} else {
// Same row. Add to right side of nextBottom.
nextBottom.endCol= segment.endCol;
}
SMoments segmentMoments;
segment.GetMoments(segmentMoments);
moments.Add(segmentMoments);
if (testMoments) {
#ifdef INCLUDE_STATS
SMoments test;
segment.GetMomentsTest(test);
assert(test == segmentMoments);
#endif
}
if (recordSegments) {
// Add segment to the _end_ of the linked list
*lastSegmentPtr= new /*(std::nothrow)*/ SLinkedSegment(segment);
if (*lastSegmentPtr==NULL)
return;
lastSegmentPtr= &((*lastSegmentPtr)->next);
}
}
// This takes futileResister and assimilates it into this blob
//
// Takes advantage of the fact that we are always assembling top to
// bottom, left to right.
//
// Be sure to call like so:
// leftblob.Assimilate(rightblob);
//
// This lets us assume two things:
// 1) The assimilated blob contains no segments on the current row
// 2) The assimilated blob lastBottom surface is to the right
// of this blob's lastBottom surface
void
CBlob::Assimilate(CBlob &futileResister)
{
moments.Add(futileResister.moments);
UpdateBoundingBox(futileResister.left,
futileResister.top,
futileResister.right);
// Update lastBottom
if (futileResister.lastBottom.endCol > lastBottom.endCol) {
lastBottom.endCol= futileResister.lastBottom.endCol;
}
if (recordSegments) {
// Take segments from futileResister, append on end
*lastSegmentPtr= futileResister.firstSegment;
lastSegmentPtr= futileResister.lastSegmentPtr;
futileResister.firstSegment= NULL;
futileResister.lastSegmentPtr= &futileResister.firstSegment;
// Futile resister is left with no segments
}
}
// Only updates left, top, and right. bottom is updated
// by UpdateAttachmentSurface below
void
CBlob::UpdateBoundingBox(int newLeft, int newTop, int newRight)
{
if (newLeft < left ) left = newLeft;
if (newTop < top ) top = newTop;
if (newRight > right) right= newRight;
}
///////////////////////////////////////////////////////////////////////////
// CBlobAssembler
CBlobAssembler::CBlobAssembler()
{
activeBlobs= currentBlob= finishedBlobs= NULL;
previousBlobPtr= &activeBlobs;
currentRow=-1;
maxRowDelta=1;
m_blobCount=0;
}
CBlobAssembler::~CBlobAssembler()
{
// Flush any active blobs into finished blobs
EndFrame();
// Free any finished blobs
Reset();
}
// Call once for each segment in the color channel
int CBlobAssembler::Add(const SSegment &segment) {
if (segment.row != currentRow) {
// Start new row
currentRow= segment.row;
RewindCurrent();
}
// Try to link this to a previous blob
while (currentBlob) {
if (segment.startCol > currentBlob->lastBottom.endCol) {
// Doesn't connect. Keep searching more blobs to the right.
AdvanceCurrent();
} else {
if (segment.endCol < currentBlob->lastBottom.startCol) {
// Doesn't connect to any blob. Stop searching.
break;
} else {
// Found a blob to connect to
currentBlob->Add(segment);
// Check to see if we attach to multiple blobs
while(currentBlob->next &&
segment.endCol >= currentBlob->next->lastBottom.startCol) {
// Can merge the current blob with the next one,
// assimilate the next one and delete it.
// Uncomment this for verbose output for testing
// cout << "Merging blobs:" << endl
// << " curr: bottom=" << currentBlob->bottom
// << ", " << currentBlob->lastBottom.startCol
// << " to " << currentBlob->lastBottom.endCol
// << ", area " << currentBlob->moments.area << endl
// << " next: bottom=" << currentBlob->next->bottom
// << ", " << currentBlob->next->lastBottom.startCol
// << " to " << currentBlob->next->lastBottom.endCol
// << ", area " << currentBlob->next->moments.area << endl;
CBlob *futileResister = currentBlob->next;
// Cut it out of the list
currentBlob->next = futileResister->next;
// Assimilate it's segments and moments
currentBlob->Assimilate(*(futileResister));
// Uncomment this for verbose output for testing
// cout << " NEW curr: bottom=" << currentBlob->bottom
// << ", " << currentBlob->lastBottom.startCol
// << " to " << currentBlob->lastBottom.endCol
// << ", area " << currentBlob->moments.area << endl;
// Delete it
delete futileResister;
BlobNewRow(&currentBlob->next);
}
return 0;
}
}
}
// Could not attach to previous blob, insert new one before currentBlob
CBlob *newBlob= new /*(std::nothrow)*/ CBlob();
if (newBlob==NULL)
{
DBG("blobs %d\nheap full", m_blobCount);
return -1;
}
m_blobCount++;
newBlob->next= currentBlob;
*previousBlobPtr= newBlob;
previousBlobPtr= &newBlob->next;
newBlob->Add(segment);
return 0;
}
// Call at end of frame
// Moves all active blobs to finished list
void CBlobAssembler::EndFrame() {
while (activeBlobs) {
activeBlobs->NewRow();
CBlob *tmp= activeBlobs->next;
activeBlobs->next= finishedBlobs;
finishedBlobs= activeBlobs;
activeBlobs= tmp;
}
}
int CBlobAssembler::ListLength(const CBlob *b) {
int len= 0;
while (b) {
len++;
b=b->next;
}
return len;
}
// Split a list of blobs into two halves
void CBlobAssembler::SplitList(CBlob *all,
CBlob *&firstHalf, CBlob *&secondHalf) {
firstHalf= secondHalf= all;
CBlob *ptr= all, **nextptr= &secondHalf;
while (1) {
if (!ptr->next) break;
ptr= ptr->next;
nextptr= &(*nextptr)->next;
if (!ptr->next) break;
ptr= ptr->next;
}
secondHalf= *nextptr;
*nextptr= NULL;
}
// Merge maxelts elements from old1 and old2 into newptr
void CBlobAssembler::MergeLists(CBlob *&old1, CBlob *&old2,
CBlob **&newptr, int maxelts) {
int n1= maxelts, n2= maxelts;
while (1) {
if (n1 && old1) {
if (n2 && old2 && old2->moments.area > old1->moments.area) {
// Choose old2
*newptr= old2;
newptr= &(*newptr)->next;
old2= *newptr;
--n2;
} else {
// Choose old1
*newptr= old1;
newptr= &(*newptr)->next;
old1= *newptr;
--n1;
}
}
else if (n2 && old2) {
// Choose old2
*newptr= old2;
newptr= &(*newptr)->next;
old2= *newptr;
--n2;
} else {
// Done
return;
}
}
}
#ifdef DEBUG
void len_error() {
printf("len error, wedging!\n");
while(1);
}
#endif
// Sorts finishedBlobs in order of descending area using an in-place
// merge sort (time n log n)
void CBlobAssembler::SortFinished() {
// Divide finishedBlobs into two lists
CBlob *old1, *old2;
if(finishedBlobs == NULL) {
return;
}
DBG_BLOB(int initial_len= ListLength(finishedBlobs));
DBG_BLOB(printf("BSort: Start 0x%x, len=%d\n", finishedBlobs,
initial_len));
SplitList(finishedBlobs, old1, old2);
// First merge lists of length 1 into sorted lists of length 2
// Next, merge sorted lists of length 2 into sorted lists of length 4
// And so on. Terminate when only one merge is performed, which
// means we're completely sorted.
for (int blocksize= 1; old2; blocksize <<= 1) {
CBlob *new1=NULL, *new2=NULL, **newptr1= &new1, **newptr2= &new2;
while (old1 || old2) {
DBG_BLOB(printf("BSort: o1 0x%x, o2 0x%x, bs=%d\n",
old1, old2, blocksize));
DBG_BLOB(printf(" n1 0x%x, n2 0x%x\n",
new1, new2));
MergeLists(old1, old2, newptr1, blocksize);
MergeLists(old1, old2, newptr2, blocksize);
}
*newptr1= *newptr2= NULL; // Terminate lists
old1= new1;
old2= new2;
}
finishedBlobs= old1;
DBG_BLOB(AssertFinishedSorted());
DBG_BLOB(int final_len= ListLength(finishedBlobs));
DBG_BLOB(printf("BSort: DONE 0x%x, len=%d\n", finishedBlobs,
ListLength(finishedBlobs)));
DBG_BLOB(if (final_len != initial_len) len_error());
}
// Assert that finishedBlobs is in fact sorted. For testing only.
void CBlobAssembler::AssertFinishedSorted() {
if (!finishedBlobs) return;
CBlob *i= finishedBlobs;
CBlob *j= i->next;
while (j) {
assert(i->moments.area >= j->moments.area);
i= j;
j= i->next;
}
}
void CBlobAssembler::Reset() {
assert(!activeBlobs);
currentBlob= NULL;
currentRow=-1;
m_blobCount=0;
while (finishedBlobs) {
CBlob *tmp= finishedBlobs->next;
delete finishedBlobs;
finishedBlobs= tmp;
}
DBG_BLOB(printf("after CBlobAssember::Reset, leakcheck=%d\n", CBlob::leakcheck));
}
// Manage currentBlob
//
// We always want to guarantee that both currentBlob
// and currentBlob->next have had NewRow() called, and have
// been validated to remain on the active list. We could just
// do this for all activeBlobs at the beginning of each row,
// but it's less work to only do it on demand as segments come in
// since it might allow us to skip blobs for a given row
// if there are no segments which might overlap.
// BlobNewRow:
//
// Tell blob there is a new row of data, and confirm that the
// blob should still be on the active list by seeing if too many
// rows have elapsed since the last segment was added.
//
// If blob should no longer be on the active list, remove it and
// place on the finished list, and skip to the next blob.
//
// Call this either zero or one time per blob per row, never more.
//
// Pass in the pointer to the "next" field pointing to the blob, so
// we can delete the blob from the linked list if it's not valid.
void
CBlobAssembler::BlobNewRow(CBlob **ptr)
{
short left, top, right, bottom;
while (*ptr) {
CBlob *blob= *ptr;
blob->NewRow();
if (currentRow - blob->lastBottom.row > maxRowDelta) {
// Too many rows have elapsed. Move it to the finished list
*ptr= blob->next; // cut out of current list
// check to see if it meets height and area constraints
blob->getBBox(left, top, right, bottom);
if (bottom-top>1) //&& blob->GetArea()>=MIN_COLOR_CODE_AREA)
{
// add to finished blobs
blob->next= finishedBlobs;
finishedBlobs= blob;
}
else
delete blob;
} else {
// Blob is valid
return;
}
}
}
void
CBlobAssembler::RewindCurrent()
{
BlobNewRow(&activeBlobs);
previousBlobPtr= &activeBlobs;
currentBlob= *previousBlobPtr;
if (currentBlob) BlobNewRow(&currentBlob->next);
}
void
CBlobAssembler::AdvanceCurrent()
{
previousBlobPtr= &(currentBlob->next);
currentBlob= *previousBlobPtr;
if (currentBlob) BlobNewRow(&currentBlob->next);
}
-357
View File
@@ -1,357 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#ifndef _BLOB_H
#define _BLOB_H
// TODO
//
// *** Priority 1
//
// *** Priority 2:
//
// *** Priority 3:
//
// *** Priority 4:
//
// Think about heap management of CBlobs
// Think about heap management of SLinkedSegments
//
// *** Priority 5 (maybe never do):
//
// Try small and large SMoments structure (small for segment)
// Try more efficient SSegment structure for lastBottom, nextBottom
//
// *** DONE
//
// DONE Compute elongation, major/minor axes (SMoments::GetStats)
// DONE Make XRC LUT
// DONE Use XRC LUT
// DONE Optimize blob assy
// DONE Start compiling
// DONE Conditionally record segments
// DONE Ask rich about FP, trig
// Take segmented image in (DONE in imageserver.cc, ARW 10/7/04)
// Produce colored segmented image out (DONE in imageserver.cc, ARW 10/7/04)
// Draw blob stats in image out (DONE for centroid, bounding box
// in imageserver.cc, ARW 10/7/04)
// Delete segments when deleting blob (DONE, ARW 10/7/04)
// Check to see if we attach to multiple blobs (DONE, ARW 10/7/04)
// Sort blobs according to area (DONE, ARW 10/7/04)
// DONE Sort blobs according to area
// DONE Clean up code
#include <stdlib.h>
#include <assert.h>
//#include <memory.h>
#include <math.h>
//#define INCLUDE_STATS
// Uncomment this for verbose output for testing
//#include <iostream.h>
struct SMomentStats {
int area;
// X is 0 on the left side of the image and increases to the right
// Y is 0 on the top of the image and increases to the bottom
float centroidX, centroidY;
// angle is 0 to PI, in radians.
// 0 points to the right (positive X)
// PI/2 points downward (positive Y)
float angle;
float majorDiameter;
float minorDiameter;
};
// Image size is 352x278
// Full-screen blob area is 97856
// Full-screen centroid is 176,139
// sumX, sumY is then 17222656, 13601984; well within 32 bits
struct SMoments {
// Skip major/minor axis computation when this is false
static bool computeAxes;
int area; // number of pixels
void Reset() {
area = 0;
#ifdef INCLUDE_STATS
sumX= sumY= sumXX= sumYY= sumXY= 0;
#endif
}
#ifdef INCLUDE_STATS
int sumX; // sum of pixel x coords
int sumY; // sum of pixel y coords
// XX, XY, YY used for major/minor axis calculation
long long sumXX; // sum of x^2 for each pixel
long long sumYY; // sum of y^2 for each pixel
long long sumXY; // sum of x*y for each pixel
#endif
void Add(const SMoments &moments) {
area += moments.area;
#ifdef INCLUDE_STATS
sumX += moments.sumX;
sumY += moments.sumY;
if (computeAxes) {
sumXX += moments.sumXX;
sumYY += moments.sumYY;
sumXY += moments.sumXY;
}
#endif
}
#ifdef INCLUDE_STATS
void GetStats(SMomentStats &stats) const;
bool operator==(const SMoments &rhs) const {
if (area != rhs.area) return 0;
if (sumX != rhs.sumX) return 0;
if (sumY != rhs.sumY) return 0;
if (computeAxes) {
if (sumXX != rhs.sumXX) return 0;
if (sumYY != rhs.sumYY) return 0;
if (sumXY != rhs.sumXY) return 0;
}
return 1;
}
#endif
};
struct SSegment {
unsigned char model : 3 ; // which color channel
unsigned short row : 9 ;
unsigned short startCol : 10; // inclusive
unsigned short endCol : 10; // inclusive
const static short invalid_row= 0x1ff;
// Sum 0^2 + 1^2 + 2^2 + ... + n^2 is (2n^3 + 3n^2 + n) / 6
// Sum (a+1)^2 + (a+2)^2 ... b^2 is (2(b^3-a^3) + 3(b^2-a^2) + (b-a)) / 6
//
// Sum 0+1+2+3+...+n is (n^2 + n)/2
// Sum (a+1) + (a+2) ... b is (b^2-a^2 + b-a)/2
void GetMoments(SMoments &moments) const {
int s= startCol - 1;
int e= endCol;
moments.area = (e-s);
#ifdef INCLUDE_STATS
int e2= e*e;
int y= row;
int s2= s*s;
moments.sumX = ( (e2-s2) + (e-s) ) / 2;
moments.sumY = (e-s) * y;
if (SMoments::computeAxes) {
int e3= e2*e;
int s3= s2*s;
moments.sumXY= moments.sumX*y;
moments.sumXX= (2*(e3-s3) + 3*(e2-s2) + (e-s)) / 6;
moments.sumYY= moments.sumY*y;
}
#endif
}
#ifdef INCLUDE_STATS
void GetMomentsTest(SMoments &moments) const;
#endif
};
struct SLinkedSegment {
SSegment segment;
SLinkedSegment *next;
SLinkedSegment(const SSegment &segmentInit) :
segment(segmentInit), next(NULL) {}
};
class CBlob {
// These are at the beginning for fast inclusion checking
public:
static int leakcheck;
CBlob *next; // next ptr for linked list
// Bottom of blob, which is the surface we'll attach more segments to
// If bottom of blob contains multiple segments, this is the smallest
// segment containing the multiple segments
SSegment lastBottom;
// Next bottom of blob, currently under construction
SSegment nextBottom;
// Bounding box, inclusive. nextBottom.row contains the "bottom"
short left, top, right;
void getBBox(short &leftRet, short &topRet,
short &rightRet, short &bottomRet) {
leftRet= left;
topRet= top;
rightRet= right;
bottomRet= lastBottom.row;
}
// Segments which compose the blob
// Only recorded if CBlob::recordSegments is true
// firstSegment points to first segment in linked list
SLinkedSegment *firstSegment;
// lastSegmentPtr points to the next pointer field _inside_ the
// last element of the linked list. This is the field you would
// modify in order to append to the end of the list. Therefore
// **lastSegmentPtr should always equal to NULL.
// When the list is empty, lastSegmentPtr actually doesn't point inside
// a SLinkedSegment structure at all but instead at the firstSegment
// field above, which in turn is NULL.
SLinkedSegment **lastSegmentPtr;
SMoments moments;
static bool recordSegments;
// Set to true for testing code only. Very slow!
static bool testMoments;
CBlob();
~CBlob();
int GetArea() const {
return(moments.area);
}
// Clear blob data and free segments, if any
void Reset();
void NewRow();
void Add(const SSegment &segment);
// This takes futileResister and assimilates it into this blob
//
// Takes advantage of the fact that we are always assembling top to
// bottom, left to right.
//
// Be sure to call like so:
// leftblob.Assimilate(rightblob);
//
// This lets us assume two things:
// 1) The assimilated blob contains no segments on the current row
// 2) The assimilated blob lastBottom surface is to the right
// of this blob's lastBottom surface
void Assimilate(CBlob &futileResister);
// Only updates left, top, and right. bottom is updated
// by UpdateAttachmentSurface below
void UpdateBoundingBox(int newLeft, int newTop, int newRight);
};
// Strategy for using CBlobAssembler:
//
// Make one CBlobAssembler for each color channel.
// CBlobAssembler ignores the model index, so you need to be sure to
// only pass the correct segments to each CBlobAssembler.
//
// At the beginning of a frame, call Reset() on each assembler
// As segments appear, call Add(segment)
// At the end of a frame, call EndFrame() on each assembler
// Get blobs from finishedBlobs. Blobs will remain valid until
// the next call to Reset(), at which point they will be deleted.
//
// To get statistics for a blob, do the following:
// SMomentStats stats;
// blob->moments.GetStats(stats);
// (See imageserver.cc: draw_blob() for an example)
class CBlobAssembler {
short currentRow;
// Active blobs, in left to right order
// (Active means we are still potentially adding segments)
CBlob *activeBlobs;
// Current candidate for adding a segment to. This is a member
// of activeBlobs, and scans left to right as we search the active blobs.
CBlob *currentBlob;
// Pointer to pointer to current candidate, which is actually the pointer
// to the "next" field inside the previous candidate, or a pointer to
// the activeBlobs field of this object if the current candidate is the
// first element of the activeBlobs list. Used for inserting and
// deleting blobs.
CBlob **previousBlobPtr;
public:
// Blobs we're no longer adding to
CBlob *finishedBlobs;
short maxRowDelta;
static bool keepFinishedSorted;
public:
CBlobAssembler();
~CBlobAssembler();
// Call prior to starting a frame
// Deletes any previously created blobs
void Reset();
// Call once for each segment in the color channel
int Add(const SSegment &segment);
// Call at end of frame
// Moves all active blobs to finished list
void EndFrame();
int ListLength(const CBlob *b);
// Split a list of blobs into two halves
void SplitList(CBlob *all, CBlob *&firstHalf, CBlob *&secondHalf);
// Merge maxelts elements from old1 and old2 into newptr
void MergeLists(CBlob *&old1, CBlob *&old2, CBlob **&newptr, int maxelts);
// Sorts finishedBlobs in order of descending area using an in-place
// merge sort (time n log n)
void SortFinished();
// Assert that finishedBlobs is in fact sorted. For testing only.
void AssertFinishedSorted();
protected:
// Manage currentBlob
//
// We always want to guarantee that both currentBlob
// and currentBlob->next have had NewRow() called, and have
// been validated to remain on the active list. We could just
// do this for all activeBlobs at the beginning of each row,
// but it's less work to only do it on demand as segments come in
// since it might allow us to skip blobs for a given row
// if there are no segments which might overlap.
// BlobNewRow:
//
// Tell blob there is a new row of data, and confirm that the
// blob should still be on the active list by seeing if too many
// rows have elapsed since the last segment was added.
//
// If blob should no longer be on the active list, remove it and
// place on the finished list, and skip to the next blob.
//
// Call this either zero or one time per blob per row, never more.
//
// Pass in the pointer to the "next" field pointing to the blob, so
// we can delete the blob from the linked list if it's not valid.
void BlobNewRow(CBlob **ptr);
void RewindCurrent();
void AdvanceCurrent();
int m_blobCount;
};
#endif // _BLOB_H
File diff suppressed because it is too large Load Diff
-111
View File
@@ -1,111 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#ifndef BLOBS_H
#define BLOBS_H
#include <stdint.h>
#include "blob.h"
#include "pixytypes.h"
#include "colorlut.h"
#include "qqueue.h"
#define MAX_BLOBS 100
#define MAX_BLOBS_PER_MODEL 20
#define MAX_MERGE_DIST 5
#define MIN_AREA 20
#define MIN_COLOR_CODE_AREA 10
#define MAX_CODED_DIST 6
#define MAX_COLOR_CODE_MODELS 5
#define BL_BEGIN_MARKER 0xaa55
#define BL_BEGIN_MARKER_CC 0xaa56
enum ColorCodeMode
{
DISABLED = 0,
ENABLED = 1,
CC_ONLY = 2,
MIXED = 3 // experimental
};
class Blobs
{
public:
Blobs(Qqueue *qq, uint8_t *lut);
~Blobs();
int blobify();
uint16_t getBlock(uint8_t *buf, uint32_t buflen);
uint16_t getCCBlock(uint8_t *buf, uint32_t buflen);
BlobA *getMaxBlob(uint16_t signature=0);
void getBlobs(BlobA **blobs, uint32_t *len, BlobB **ccBlobs, uint32_t *ccLen);
int setParams(uint16_t maxBlobs, uint16_t maxBlobsPerModel, uint32_t minArea, ColorCodeMode ccMode);
int runlengthAnalysis();
#ifndef PIXY
void getRunlengths(uint32_t **qvals, uint32_t *len);
#endif
ColorLUT m_clut;
Qqueue *m_qq;
private:
int handleSegment(uint8_t signature, uint16_t row, uint16_t startCol, uint16_t length);
void endFrame();
uint16_t combine(uint16_t *blobs, uint16_t numBlobs);
uint16_t combine2(uint16_t *blobs, uint16_t numBlobs);
uint16_t compress(uint16_t *blobs, uint16_t numBlobs);
bool closeby(BlobA *blob0, BlobA *blob1);
int16_t distance(BlobA *blob0, BlobA *blob1);
void sort(BlobA *blobs[], uint16_t len, BlobA *firstBlob, bool horiz);
int16_t angle(BlobA *blob0, BlobA *blob1);
int16_t distance(BlobA *blob0, BlobA *blob1, bool horiz);
void processCC();
void cleanup(BlobA *blobs[], int16_t *numBlobs);
void cleanup2(BlobA *blobs[], int16_t *numBlobs);
bool analyzeDistances(BlobA *blobs0[], int16_t numBlobs0, BlobA *blobs[], int16_t numBlobs, BlobA **blobA, BlobA **blobB);
void mergeClumps(uint16_t scount0, uint16_t scount1);
void printBlobs();
CBlobAssembler m_assembler[CL_NUM_SIGNATURES];
uint16_t *m_blobs;
uint16_t m_numBlobs;
BlobB *m_ccBlobs;
uint16_t m_numCCBlobs;
bool m_mutex;
uint16_t m_maxBlobs;
uint16_t m_maxBlobsPerModel;
uint16_t m_blobReadIndex;
uint16_t m_ccBlobReadIndex;
uint32_t m_minArea;
uint16_t m_mergeDist;
uint16_t m_maxCodedDist;
ColorCodeMode m_ccMode;
BlobA *m_maxBlob;
#ifndef PIXY
uint32_t m_numQvals;
uint32_t *m_qvals;
#endif
};
#endif // BLOBS_H
-108
View File
@@ -1,108 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#include "calc.h"
void hsvc(uint8_t r, uint8_t g, uint8_t b, uint8_t *h, uint8_t *s, uint8_t *v, uint8_t *c)
{
uint8_t min, max, delta;
int hue;
min = MIN(r, g);
min = MIN(min, b);
max = MAX(r, g);
max = MAX(max, b);
*v = max;
delta = max - min;
if (max>50)
{
//if (delta>50)
*s = ((int)delta<<8)/max;
//else
// *s = 0;
}
else
*s = 0;
if (max==0 || delta==0)
{
*s = 0;
*h = 0;
*c = 0;
return;
}
if (r==max)
hue = (((int)g - (int)b)<<8)/delta; // between yellow & magenta
else if (g==max)
hue = (2<<8) + (((int)b - (int)r)<<8)/delta; // between cyan & yellow
else
hue = (4<<8) + (((int)r - (int)g)<<8)/delta; // between magenta & cyan
if(hue < 0)
hue += 6<<8;
hue /= 6;
*h = hue;
*c = delta;
}
uint32_t lighten(uint32_t color, uint8_t factor)
{
uint32_t r, g, b;
rgbUnpack(color, &r, &g, &b);
r += factor;
g += factor;
b += factor;
return rgbPack(r, g, b);
}
uint32_t rgbPack(uint32_t r, uint32_t g, uint32_t b)
{
if (r>0xff)
r = 0xff;
if (g>0xff)
g = 0xff;
if (b>0xff)
b = 0xff;
return (r<<16) | (g<<8) | b;
}
void rgbUnpack(uint32_t color, uint32_t *r, uint32_t *g, uint32_t *b)
{
*b = color&0xff;
color >>= 8;
*g = color&0xff;
color >>= 8;
*r = color&0xff;
}
uint32_t saturate(uint32_t color)
{
float m;
uint32_t max, r, g, b;
rgbUnpack(color, &r, &g, &b);
max = MAX(r, g);
max = MAX(max, b);
// saturate while maintaining ratios
m = 255.0f/max;
r = (uint8_t)(m*r);
g = (uint8_t)(m*g);
b = (uint8_t)(m*b);
return rgbPack(r, g, b);
}
-35
View File
@@ -1,35 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#ifndef CALC_H
#define CALC_H
#include <inttypes.h>
#ifdef MAX
#undef MAX
#endif
#ifdef MIN
#undef MIN
#endif
#define MAX(a, b) (a>b ? a : b)
#define MIN(a, b) (a<b ? a : b)
void hsvc(uint8_t r, uint8_t g, uint8_t b, uint8_t *h, uint8_t *s, uint8_t *v, uint8_t *c);
uint32_t lighten(uint32_t color, uint8_t factor);
uint32_t saturate(uint32_t color);
uint32_t rgbPack(uint32_t r, uint32_t g, uint32_t b);
void rgbUnpack(uint32_t color, uint32_t *r, uint32_t *g, uint32_t *b);
#endif // CALC_H
File diff suppressed because it is too large Load Diff
-291
View File
@@ -1,291 +0,0 @@
#ifndef CHIRP_HPP
#define CHIRP_HPP
#include <stdint.h>
#include <stdlib.h>
#include <stdarg.h>
#include "link.h"
#define ALIGN(v, n) v = v&((n)-1) ? (v&~((n)-1))+(n) : v
#define FOURCC(a, b, c, d) (((uint32_t)a<<0)|((uint32_t)b<<8)|((uint32_t)c<<16)|((uint32_t)d<<24))
#define CRP_RES_OK 0
#define CRP_RES_ERROR -1
#define CRP_RES_ERROR_RECV_TIMEOUT LINK_RESULT_ERROR_RECV_TIMEOUT
#define CRP_RES_ERROR_SEND_TIMEOUT LINK_RESULT_ERROR_SEND_TIMEOUT
#define CRP_RES_ERROR_CRC -2
#define CRP_RES_ERROR_PARSE -3
#define CRP_RES_ERROR_MAX_NAK -4
#define CRP_RES_ERROR_MEMORY -5
#define CRP_RES_ERROR_NOT_CONNECTED -6
#define CRP_MAX_NAK 3
#define CRP_RETRIES 3
#define CRP_HEADER_TIMEOUT 1000
#define CRP_DATA_TIMEOUT 500
#define CRP_IDLE_TIMEOUT 500
#define CRP_SEND_TIMEOUT 1000
#define CRP_MAX_ARGS 10
#define CRP_BUFSIZE 0x80
#define CRP_BUFPAD 8
#define CRP_PROCTABLE_LEN 0x40
#define CRP_START_CODE 0xaaaa5555
#define CRP_CALL 0x80
#define CRP_RESPONSE 0x40
#define CRP_INTRINSIC 0x20
#define CRP_DATA 0x10
#define CRP_XDATA 0x18 // data not associated with no associated procedure)
#define CRP_CALL_ENUMERATE (CRP_CALL | CRP_INTRINSIC | 0x00)
#define CRP_CALL_INIT (CRP_CALL | CRP_INTRINSIC | 0x01)
#define CRP_CALL_ENUMERATE_INFO (CRP_CALL | CRP_INTRINSIC | 0x02)
#define CRP_ACK 0x59
#define CRP_NACK 0x95
#define CRP_MAX_HEADER_LEN 64
#define CRP_ARRAY 0x80 // bit
#define CRP_FLT 0x10 // bit
#define CRP_NO_COPY (0x10 | 0x20)
#define CRP_HINT 0x40 // bit
#define CRP_NULLTERM_ARRAY (0x20 | CRP_ARRAY) // bits
#define CRP_INT8 0x01
#define CRP_UINT8 0x01
#define CRP_INT16 0x02
#define CRP_UINT16 0x02
#define CRP_INT32 0x04
#define CRP_UINT32 0x04
#define CRP_FLT32 (CRP_FLT | 0x04)
#define CRP_FLT64 (CRP_FLT | 0x08)
#define CRP_STRING (CRP_NULLTERM_ARRAY | CRP_INT8)
#define CRP_TYPE_HINT 0x64 // type hint identifier
#define CRP_INTS8 (CRP_INT8 | CRP_ARRAY)
#define CRP_INTS16 (CRP_INT16 | CRP_ARRAY)
#define CRP_INTS32 (CRP_INT32 | CRP_ARRAY)
#define CRP_UINTS8 CRP_INTS8
#define CRP_UINTS8_NO_COPY (CRP_INTS8 | CRP_NO_COPY)
#define CRP_UINTS16_NO_COPY (CRP_INTS16 | CRP_NO_COPY)
#define CRP_UINTS32_NO_COPY (CRP_INTS32 | CRP_NO_COPY)
#define CRP_UINTS16 CRP_INTS16
#define CRP_UINTS32 CRP_INTS32
#define CRP_FLTS32 (CRP_FLT32 | CRP_ARRAY)
#define CRP_FLTS64 (CRP_FLT64 | CRP_ARRAY)
#define CRP_HINT8 (CRP_INT8 | CRP_HINT)
#define CRP_HINT16 (CRP_INT16 | CRP_HINT)
#define CRP_HINT32 (CRP_INT32 | CRP_HINT)
#define CRP_HINTS8 (CRP_INT8 | CRP_ARRAY | CRP_HINT)
#define CRP_HINTS16 (CRP_INT16 | CRP_ARRAY | CRP_HINT)
#define CRP_HINTS32 (CRP_INT32 | CRP_ARRAY | CRP_HINT)
#define CRP_HFLTS32 (CRP_FLT32 | CRP_ARRAY | CRP_HINT)
#define CRP_HFLTS64 (CRP_FLT64 | CRP_ARRAY | CRP_HINT)
#define CRP_HSTRING (CRP_STRING | CRP_HINT)
// CRP_HTYPE is for arg lists which are uint8_t arrays
#define CRP_HTYPE(v) CRP_TYPE_HINT, (uint8_t)(v>>0&0xff), (uint8_t)(v>>8&0xff), (uint8_t)(v>>16&0xff), (uint8_t)(v>>24&0xff)
// regular call args
#define INT8(v) CRP_INT8, v
#define UINT8(v) CRP_INT8, v
#define INT16(v) CRP_INT16, v
#define UINT16(v) CRP_INT16, v
#define INT32(v) CRP_INT32, v
#define UINT32(v) CRP_INT32, v
#define FLT32(v) CRP_FLT32, v
#define FLT64(v) CRP_FLT64, v
#define STRING(s) CRP_STRING, s
#define INTS8(len, a) CRP_INTS8, len, a
#define UINTS8(len, a) CRP_INTS8, len, a
#define UINTS8_NO_COPY(len) CRP_UINTS8_NO_COPY, len
#define UINTS16_NO_COPY(len) CRP_UINTS16_NO_COPY, len
#define UINTS32_NO_COPY(len) CRP_UINTS32_NO_COPY, len
#define INTS16(len, a) CRP_INTS16, len, a
#define UINTS16(len, a) CRP_INTS16, len, a
#define INTS32(len, a) CRP_INTS32, len, a
#define UINTS32(len, a) CRP_INTS32, len, a
#define FLTS32(len, a) CRP_FLTS32, len, a
#define FLTS64(len, a) CRP_FLTS64, len, a
// hint call args
#define HINT8(v) CRP_HINT8, v
#define UHINT8(v) CRP_HINT8, v
#define HINT16(v) CRP_HINT16, v
#define UHINT16(v) CRP_HINT16, v
#define HINT32(v) CRP_HINT32, v
#define UHINT32(v) CRP_HINT32, v
#define HFLT32(v) CRP_HFLT32, v
#define HFLT64(v) CRP_HFLT64, v
#define HSTRING(s) CRP_HSTRING, s
#define HINTS8(len, a) CRP_HINTS8, len, a
#define UHINTS8(len, a) CRP_HINTS8, len, a
#define HINTS16(len, a) CRP_HINTS16, len, a
#define UHINTS16(len, a) CRP_HINTS16, len, a
#define HINTS32(len, a) CRP_HINTS32, len, a
#define UHINTS32(len, a) CRP_HINTS32, len, a
#define HFLTS32(len, a) CRP_HFLTS32, len, a
#define HFLTS64(len, a) CRP_HFLTS64, len, a
#define HTYPE(v) CRP_TYPE_HINT, v
#define INT8_IN(v) int8_t & v
#define UINT8_IN(v) uint8_t & v
#define INT16_IN(v) int16_t & v
#define UINT16_IN(v) uint16_t & v
#define INT32_IN(v) int32_t & v
#define UINT32_IN(v) uint32_t & v
#define FLT32_IN(v) float & v
#define FLT64_IN(v) double & v
#define STRING_IN(s) const char * s
#define INTS8_IN(len, a) uint32_t & len, int8_t * a
#define UINTS8_IN(len, a) uint32_t & len, uint8_t * a
#define INTS16_IN(len, a) uint32_t & len, int16_t * a
#define UINTS16_IN(len, a) uint32_t & len, uint16_t * a
#define INTS32_IN(len, a) uint32_t & len, int32_t * a
#define UINTS32_IN(len, a) uint32_t & len, uint32_t * a
#define FLTS32_IN(len, a) uint32_t & len, float * a
#define FLTS64_IN(len, a) uint32_t & len, double * a
#ifndef END
#ifdef __x86_64__
#define END (int64_t)0
#else
#define END 0
#endif
#endif
#define END_OUT_ARGS END
#define END_IN_ARGS END
// service types
#define SYNC 0
#define ASYNC 0x01 // bit
#define RETURN_ARRAY 0x02 // bit
#define SYNC_RETURN_ARRAY (SYNC | RETURN_ARRAY)
#define CRP_RETURN(chirp, ...) chirp->assemble(0, __VA_ARGS__, END)
#define CRP_SEND_XDATA(chirp, ...) chirp->assemble(CRP_XDATA, __VA_ARGS__, END)
#define callSync(...) call(SYNC, __VA_ARGS__, END)
#define callAsync(...) call(ASYNC, __VA_ARGS__, END)
#define callSyncArray(...) call(SYNC_RETURN_ARRAY, __VA_ARGS__, END)
class Chirp;
typedef int16_t ChirpProc; // negative values are invalid
typedef uint32_t (*ProcPtr)(Chirp *);
struct ProcModule
{
char *procName;
ProcPtr procPtr;
uint8_t argTypes[CRP_MAX_ARGS];
char *procInfo;
};
struct ProcTableExtension
{
uint8_t argTypes[CRP_MAX_ARGS];
char *procInfo;
};
struct ProcInfo
{
char *procName;
uint8_t *argTypes;
char *procInfo;
};
struct ProcTableEntry
{
const char *procName;
ProcPtr procPtr;
ChirpProc chirpProc;
const ProcTableExtension *extension;
};
class Chirp
{
public:
Chirp(bool hinterested=false, bool client=false, Link *link=NULL);
~Chirp();
virtual int init(bool connect);
int setLink(Link *link);
ChirpProc getProc(const char *procName, ProcPtr callback=0);
int setProc(const char *procName, ProcPtr proc, ProcTableExtension *extension=NULL);
int getProcInfo(ChirpProc proc, ProcInfo *info);
int registerModule(const ProcModule *module);
void setSendTimeout(uint32_t timeout);
void setRecvTimeout(uint32_t timeout);
int call(uint8_t service, ChirpProc proc, ...);
int call(uint8_t service, ChirpProc proc, va_list args);
static uint8_t getType(const void *arg);
int service(bool all=true);
int assemble(uint8_t type, ...);
bool connected();
// utility methods
static int serialize(Chirp *chirp, uint8_t *buf, uint32_t bufSize, ...);
static int deserialize(uint8_t *buf, uint32_t len, ...);
static int vserialize(Chirp *chirp, uint8_t *buf, uint32_t bufSize, va_list *args);
static int vdeserialize(uint8_t *buf, uint32_t len, va_list *args);
static int deserializeParse(uint8_t *buf, uint32_t len, void *args[]);
static int loadArgs(va_list *args, void *recvArgs[]);
static int getArgList(uint8_t *buf, uint32_t len, uint8_t *argList);
int useBuffer(uint8_t *buf, uint32_t len);
static uint16_t calcCrc(uint8_t *buf, uint32_t len);
protected:
int remoteInit(bool connect);
int recvChirp(uint8_t *type, ChirpProc *proc, void *args[], bool wait=false); // null pointer terminates
virtual int handleChirp(uint8_t type, ChirpProc proc, const void *args[]); // null pointer terminates
virtual void handleXdata(const void *data[]) {(void)data;}
virtual int sendChirp(uint8_t type, ChirpProc proc);
uint8_t *m_buf;
uint8_t *m_bufSave;
uint32_t m_len;
uint32_t m_offset;
uint32_t m_bufSize;
bool m_errorCorrected;
bool m_sharedMem;
bool m_hinformer;
bool m_hinterested;
bool m_client;
uint32_t m_headerLen;
uint16_t m_headerTimeout;
uint16_t m_dataTimeout;
uint16_t m_idleTimeout;
uint16_t m_sendTimeout;
private:
int sendHeader(uint8_t type, ChirpProc proc);
int sendFull(uint8_t type, ChirpProc proc);
int sendData();
int sendAck(bool ack); // false=nack
int sendChirpRetry(uint8_t type, ChirpProc proc);
int recvHeader(uint8_t *type, ChirpProc *proc, bool wait);
int recvFull(uint8_t *type, ChirpProc *proc, bool wait);
int recvData();
int recvAck(bool *ack, uint16_t timeout); // false=nack
int32_t handleEnumerate(char *procName, ChirpProc *callback);
int32_t handleInit(uint16_t *blkSize, uint8_t *hintSource);
int32_t handleEnumerateInfo(ChirpProc *proc);
int vassemble(va_list *args);
void restoreBuffer();
ChirpProc updateTable(const char *procName, ProcPtr procPtr);
ChirpProc lookupTable(const char *procName);
int realloc(uint32_t min=0);
int reallocTable();
Link *m_link;
ProcTableEntry *m_procTable;
uint16_t m_procTableSize;
uint16_t m_blkSize;
uint8_t m_maxNak;
uint8_t m_retries;
bool m_call;
bool m_connected;
};
#endif // CHIRP_H
-38
View File
@@ -1,38 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#include "chirpreceiver.hpp"
ChirpReceiver::ChirpReceiver(USBLink * link, Interpreter * interpreter)
{
m_hinterested = true;
m_client = true;
interpreter_ = interpreter;
setLink(link);
}
ChirpReceiver::~ChirpReceiver()
{
// This destructor does nothing but is necessary //
// for successful linkage on some combinations of //
// compilers and platforms. //
}
void ChirpReceiver::handleXdata(const void * data[])
{
// Interpret (Chirp) messages from Pixy //
interpreter_->interpret_data(data);
}
-43
View File
@@ -1,43 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#ifndef __CHIRPRECEIVER_HPP__
#define __CHIRPRECEIVER_HPP__
#include "chirp.hpp"
#include "usblink.h"
#include "interpreter.hpp"
class ChirpReceiver : public Chirp
{
public:
ChirpReceiver(USBLink * link, Interpreter * interpreter);
virtual ~ChirpReceiver();
private:
Interpreter * interpreter_;
/**
@brief Called by Chrip::service() when data
is received from Pixy.
@param[in] data Incoming Chirp protocol data from Pixy.
*/
void handleXdata(const void * data[]);
};
#endif
@@ -1,642 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#include <stdlib.h>
#include <math.h>
#include <string.h>
#ifndef PIXY
#include "debug.h"
#endif
#include "colorlut.h"
#include "calc.h"
IterPixel::IterPixel(const Frame8 &frame, const RectA &region)
{
m_frame = frame;
m_region = region;
m_points = NULL;
reset();
}
IterPixel::IterPixel(const Frame8 &frame, const Points *points)
{
m_frame = frame;
m_points = points;
reset();
}
bool IterPixel::reset(bool cleari)
{
if (cleari)
m_i = 0;
if (m_points)
{
if (m_points->size()>m_i)
{
m_region = RectA((*m_points)[m_i].m_x, (*m_points)[m_i].m_y, CL_GROW_INC, CL_GROW_INC);
m_i++;
}
else
return false; // empty!
}
m_x = m_y = 0;
m_pixels = m_frame.m_pixels + (m_region.m_yOffset | 1)*m_frame.m_width + (m_region.m_xOffset | 1);
return true;
}
bool IterPixel::next(UVPixel *uv, RGBPixel *rgb)
{
if (m_points)
{
if (nextHelper(uv, rgb))
return true; // working on the current block
else // get new block
{
if (reset(false)) // reset indexes, increment m_i, get new block
return nextHelper(uv, rgb); // we have another block!
else
return false; // blocks are empty
}
}
else
return nextHelper(uv, rgb);
}
bool IterPixel::nextHelper(UVPixel *uv, RGBPixel *rgb)
{
int32_t r, g1, g2, b, u, v, c, miny=CL_MIN_Y;
while(1)
{
if (m_x>=m_region.m_width)
{
m_x = 0;
m_y += 2;
m_pixels += m_frame.m_width*2;
}
if (m_y>=m_region.m_height)
return false;
r = m_pixels[m_x];
g1 = m_pixels[m_x - 1];
g2 = m_pixels[-m_frame.m_width + m_x];
b = m_pixels[-m_frame.m_width + m_x - 1];
if (rgb)
{
rgb->m_r = r;
rgb->m_g = (g1+g2)/2;
rgb->m_b = b;
}
if (uv)
{
c = r+g1+b;
if (c<miny)
{
m_x += 2;
continue;
}
u = ((r-g1)<<CL_LUT_ENTRY_SCALE)/c;
c = r+g2+b;
if (c<miny)
{
m_x += 2;
continue;
}
v = ((b-g2)<<CL_LUT_ENTRY_SCALE)/c;
uv->m_u = u;
uv->m_v = v;
}
m_x += 2;
return true;
}
}
uint32_t IterPixel::averageRgb(uint32_t *pixels)
{
RGBPixel rgb;
uint32_t r, g, b, n;
reset();
for (r=g=b=n=0; next(NULL, &rgb); n++)
{
r += rgb.m_r;
g += rgb.m_g;
b += rgb.m_b;
}
r /= n;
g /= n;
b /= n;
if (pixels)
*pixels = n;
return (r<<16) | (g<<8) | b;
}
ColorLUT::ColorLUT(uint8_t *lut)
{
int i;
m_lut = lut;
memset((void *)m_signatures, 0, sizeof(ColorSignature)*CL_NUM_SIGNATURES);
memset((void *)m_runtimeSigs, 0, sizeof(RuntimeSignature)*CL_NUM_SIGNATURES);
clearLUT();
setMinBrightness(CL_DEFAULT_MINY);
m_minRatio = CL_MIN_RATIO;
m_maxDist = CL_MAX_DIST;
m_ratio = CL_DEFAULT_TOL;
m_ccGain = CL_DEFAULT_CCGAIN;
for (i=0; i<CL_NUM_SIGNATURES; i++)
m_sigRanges[i] = CL_DEFAULT_SIG_RANGE;
}
ColorLUT::~ColorLUT()
{
}
void ColorLUT::calcRatios(IterPixel *ip, ColorSignature *sig, float ratios[])
{
UVPixel uv;
uint32_t n=0, counts[4];
longlong usum=0, vsum=0;
counts[0] = counts[1] = counts[2] = counts[3] = 0;
ip->reset();
while(ip->next(&uv))
{
if (uv.m_u>sig->m_uMin)
counts[0]++;
if (uv.m_u<sig->m_uMax)
counts[1]++;
if (uv.m_v>sig->m_vMin)
counts[2]++;
if (uv.m_v<sig->m_vMax)
counts[3]++;
usum += uv.m_u;
vsum += uv.m_v;
n++;
}
// calc ratios
ratios[0] = (float)counts[0]/n;
ratios[1] = (float)counts[1]/n;
ratios[2] = (float)counts[2]/n;
ratios[3] = (float)counts[3]/n;
// calc mean (because it's cheap to do it here)
sig->m_uMean = usum/n;
sig->m_vMean = vsum/n;
}
void ColorLUT::iterate(IterPixel *ip, ColorSignature *sig)
{
int32_t scale;
float ratios[4];
// binary search -- this rouine is guaranteed to find the right value +/- 1, which is good enough!
// find all four values, umin, umax, vmin, vmax simultaneously
for (scale=1<<30, sig->m_uMin=sig->m_uMax=sig->m_vMin=sig->m_vMax=0; scale!=0; scale>>=1)
{
calcRatios(ip, sig, ratios);
if (ratios[0]>m_ratio)
sig->m_uMin += scale;
else
sig->m_uMin -= scale;
if (ratios[1]>m_ratio)
sig->m_uMax -= scale;
else
sig->m_uMax += scale;
if (ratios[2]>m_ratio)
sig->m_vMin += scale;
else
sig->m_vMin -= scale;
if (ratios[3]>m_ratio)
sig->m_vMax -= scale;
else
sig->m_vMax += scale;
}
}
int ColorLUT::generateSignature(const Frame8 &frame, const RectA &region, uint8_t signum)
{
if (signum<1 || signum>CL_NUM_SIGNATURES)
return -1;
// this is cool-- this routine doesn't allocate any extra memory other than some stack variables
IterPixel ip(frame, region);
iterate(&ip, m_signatures+signum-1);
m_signatures[signum-1].m_type = 0;
updateSignature(signum);
return 0;
}
int ColorLUT::generateSignature(const Frame8 &frame, const Point16 &point, Points *points, uint8_t signum)
{
if (signum<1 || signum>CL_NUM_SIGNATURES)
return -1;
// this routine requires some memory to store the region which consists of some consistently-sized blocks
growRegion(frame, point, points);
IterPixel ip(frame, points);
iterate(&ip, m_signatures+signum-1);
m_signatures[signum-1].m_type = 0;
updateSignature(signum);
return 0;
}
void ColorLUT::updateSignature(uint8_t signum)
{
float range;
if (signum<1 || signum>CL_NUM_SIGNATURES)
return;
signum--;
if (m_signatures[signum].m_type==CL_MODEL_TYPE_COLORCODE)
range = m_sigRanges[signum]*m_ccGain;
else
range = m_sigRanges[signum];
m_runtimeSigs[signum].m_uMin = m_signatures[signum].m_uMean + (m_signatures[signum].m_uMin - m_signatures[signum].m_uMean)*range;
m_runtimeSigs[signum].m_uMax = m_signatures[signum].m_uMean + (m_signatures[signum].m_uMax - m_signatures[signum].m_uMean)*range;
m_runtimeSigs[signum].m_vMin = m_signatures[signum].m_vMean + (m_signatures[signum].m_vMin - m_signatures[signum].m_vMean)*range;
m_runtimeSigs[signum].m_vMax = m_signatures[signum].m_vMean + (m_signatures[signum].m_vMax - m_signatures[signum].m_vMean)*range;
m_runtimeSigs[signum].m_rgbSat = saturate(m_signatures[signum].m_rgb);
}
ColorSignature *ColorLUT::getSignature(uint8_t signum)
{
if (signum<1 || signum>CL_NUM_SIGNATURES)
return NULL;
return m_signatures+signum-1;
}
int ColorLUT::setSignature(uint8_t signum, const ColorSignature &sig)
{
if (signum<1 || signum>CL_NUM_SIGNATURES)
return -1;
m_signatures[signum-1] = sig;
updateSignature(signum);
return 0;
}
int ColorLUT::generateLUT()
{
int32_t r, g, b, u, v, y, bin, sig;
clearLUT();
// recalc bounds for each signature
for (r=0; r<CL_NUM_SIGNATURES; r++)
updateSignature(r+1);
for (r=0; r<1<<8; r+=1<<(8-CL_LUT_COMPONENT_SCALE))
{
for (g=0; g<1<<8; g+=1<<(8-CL_LUT_COMPONENT_SCALE))
{
for (b=0; b<1<<8; b+=1<<(8-CL_LUT_COMPONENT_SCALE))
{
y = r+g+b;
if (y<(int32_t)m_miny)
continue;
u = ((r-g)<<CL_LUT_ENTRY_SCALE)/y;
v = ((b-g)<<CL_LUT_ENTRY_SCALE)/y;
for (sig=0; sig<CL_NUM_SIGNATURES; sig++)
{
if (m_signatures[sig].m_uMin==0 && m_signatures[sig].m_uMax==0)
continue;
if ((m_runtimeSigs[sig].m_uMin<u) && (u<m_runtimeSigs[sig].m_uMax) &&
(m_runtimeSigs[sig].m_vMin<v) && (v<m_runtimeSigs[sig].m_vMax))
{
u = r-g;
u >>= 9-CL_LUT_COMPONENT_SCALE;
u &= (1<<CL_LUT_COMPONENT_SCALE)-1;
v = b-g;
v >>= 9-CL_LUT_COMPONENT_SCALE;
v &= (1<<CL_LUT_COMPONENT_SCALE)-1;
bin = (u<<CL_LUT_COMPONENT_SCALE)+ v;
if (m_lut[bin]==0 || m_lut[bin]>sig+1)
m_lut[bin] = sig+1;
}
}
}
}
}
return 0;
}
void ColorLUT::clearLUT(uint8_t signum)
{
int i;
for (i=0; i<CL_LUT_SIZE; i++)
{
if (signum==0)
m_lut[i] = 0;
else if (m_lut[i]==signum)
m_lut[i] = 0;
}
}
bool ColorLUT::growRegion(RectA *region, const Frame8 &frame, uint8_t dir)
{
if (dir==0) // grow left
{
if (region->m_xOffset>=CL_GROW_INC)
{
region->m_xOffset -= CL_GROW_INC;
region->m_width += CL_GROW_INC;
}
else
return true;
}
else if (dir==1) // grow top
{
if (region->m_yOffset>=CL_GROW_INC)
{
region->m_yOffset -= CL_GROW_INC;
region->m_height += CL_GROW_INC;
}
else
return true;
}
else if (dir==2) // grow right
{
if (region->m_xOffset+region->m_width+CL_GROW_INC>frame.m_width)
return true;
region->m_width += CL_GROW_INC;
}
else if (dir==3) // grow bottom
{
if (region->m_yOffset+region->m_height+CL_GROW_INC>frame.m_height)
return true;
region->m_height += CL_GROW_INC;
}
return false;
}
float ColorLUT::testRegion(const RectA &region, const Frame8 &frame, UVPixel *mean, Points *points)
{
UVPixel subMean;
float distance;
RectA subRegion(0, 0, CL_GROW_INC, CL_GROW_INC);
subRegion.m_xOffset = region.m_xOffset;
subRegion.m_yOffset = region.m_yOffset;
bool horiz = region.m_width>region.m_height;
uint32_t i, test, endpoint = horiz ? region.m_width : region.m_height;
for (i=0, test=0; i<endpoint; i+=CL_GROW_INC)
{
getMean(subRegion, frame, &subMean);
distance = sqrt((float)((mean->m_u-subMean.m_u)*(mean->m_u-subMean.m_u) + (mean->m_v-subMean.m_v)*(mean->m_v-subMean.m_v)));
if ((uint32_t)distance<m_maxDist)
{
int32_t n = points->size();
mean->m_u = ((longlong)mean->m_u*n + subMean.m_u)/(n+1);
mean->m_v = ((longlong)mean->m_v*n + subMean.m_v)/(n+1);
if (points->push_back(Point16(subRegion.m_xOffset, subRegion.m_yOffset))<0)
break;
//DBG("add %d %d %d", subRegion.m_xOffset, subRegion.m_yOffset, points->size());
test++;
}
if (horiz)
subRegion.m_xOffset += CL_GROW_INC;
else
subRegion.m_yOffset += CL_GROW_INC;
}
//DBG("return %f", (float)test*CL_GROW_INC/endpoint);
return (float)test*CL_GROW_INC/endpoint;
}
void ColorLUT::growRegion(const Frame8 &frame, const Point16 &seed, Points *points)
{
uint8_t dir, done;
RectA region, newRegion;
UVPixel mean;
float ratio;
done = 0;
// create seed 2*CL_GROW_INCx2*CL_GROW_INC region from seed position, make sure it's within the frame
region.m_xOffset = seed.m_x;
region.m_yOffset = seed.m_y;
if (growRegion(&region, frame, 0))
done |= 1<<0;
else
points->push_back(Point16(region.m_xOffset, region.m_yOffset));
if (growRegion(&region, frame, 1))
done |= 1<<1;
else
points->push_back(Point16(region.m_xOffset, region.m_yOffset));
if (growRegion(&region, frame, 2))
done |= 1<<2;
else
points->push_back(Point16(seed.m_x, region.m_yOffset));
if (growRegion(&region, frame, 3))
done |= 1<<3;
else
points->push_back(seed);
getMean(region, frame, &mean);
while(done!=0x0f)
{
for (dir=0; dir<4; dir++)
{
newRegion = region;
if (done&(1<<dir))
continue;
else if (dir==0) // left
newRegion.m_width = 0;
else if (dir==1) // top
newRegion.m_height = 0; // top and bottom
else if (dir==2) // right
{
newRegion.m_xOffset += newRegion.m_width;
newRegion.m_width = 0;
}
else if (dir==3) // bottom
{
newRegion.m_yOffset += newRegion.m_height;
newRegion.m_height = 0;
}
if (growRegion(&newRegion, frame, dir))
done |= 1<<dir;
else
{
ratio = testRegion(newRegion, frame, &mean, points);
if (ratio<m_minRatio)
done |= 1<<dir;
else
growRegion(&region, frame, dir);
}
}
}
}
void ColorLUT::getMean(const RectA &region ,const Frame8 &frame, UVPixel *mean)
{
UVPixel uv;
uint32_t n=0;
IterPixel ip(frame, region);
longlong usum=0, vsum=0;
while(ip.next(&uv))
{
usum += uv.m_u;
vsum += uv.m_v;
n++;
}
mean->m_u = usum/n;
mean->m_v = vsum/n;
}
void ColorLUT::setSigRange(uint8_t signum, float range)
{
if (signum<1 || signum>CL_NUM_SIGNATURES)
return;
m_sigRanges[signum-1] = range;
}
void ColorLUT::setGrowDist(uint32_t dist)
{
m_maxDist = dist;
}
void ColorLUT::setMinBrightness(float miny)
{
m_miny = 3*((1<<8)-1)*miny;
if (m_miny==0)
m_miny = 1;
}
void ColorLUT::setCCGain(float gain)
{
m_ccGain = gain;
}
uint32_t ColorLUT::getType(uint8_t signum)
{
if (signum<1 || signum>CL_NUM_SIGNATURES)
return 0;
return m_signatures[signum-1].m_type;
}
#if 0
uint32_t ColorLUT::getColor(uint8_t signum)
{
int32_t r, g, b, max, u, v;
if (signum<1 || signum>CL_NUM_SIGNATURES)
return 0;
u = m_signatures[signum-1].m_uMean;
v = m_signatures[signum-1].m_vMean;
// u = r-g
// v = b-g
if (abs(u)>abs(v))
{
if (u>0)
{
r = u;
if (v>0)
g = 0;
else
g = -v;
b = v+g;
}
else
{
g = -u;
r = 0;
b = v+g;
}
}
else
{
if (v>0)
{
b = v;
if (u>0)
g = 0;
else
g = -u;
r = u+g;
}
else
{
g = -v;
b = 0;
r = u+g;
}
}
if (r>g)
max = r;
else
max = g;
if (b>max)
max = b;
// normalize
if (max>0)
{
r = (float)r/max*255;
g = (float)g/max*255;
b = (float)b/max*255;
return (r<<16) | (g<<8) | b;
}
else
return 0;
}
#endif
-129
View File
@@ -1,129 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#ifndef COLORLUT_H
#define COLORLUT_H
#include <inttypes.h>
#include "simplevector.h"
#include "pixytypes.h"
#define CL_NUM_SIGNATURES 7
#define CL_LUT_COMPONENT_SCALE 6
#define CL_LUT_SIZE (1<<(CL_LUT_COMPONENT_SCALE*2))
#define CL_LUT_ENTRY_SCALE 15
#define CL_GROW_INC 4
#define CL_MIN_Y_F 0.05 // for when generating signatures, etc
#define CL_MIN_Y (int32_t)(3*((1<<8)-1)*CL_MIN_Y_F)
#define CL_MIN_RATIO 0.25f
#define CL_DEFAULT_MINY 0.1f
#define CL_DEFAULT_SIG_RANGE 2.5f
#define CL_MAX_DIST 2000
#define CL_DEFAULT_TOL 0.9f
#define CL_DEFAULT_CCGAIN 1.5f
#define CL_MODEL_TYPE_COLORCODE 1
struct ColorSignature
{
ColorSignature()
{
m_uMin = m_uMax = m_uMean = m_vMin = m_vMax = m_vMean = m_type = 0;
}
int32_t m_uMin;
int32_t m_uMax;
int32_t m_uMean;
int32_t m_vMin;
int32_t m_vMax;
int32_t m_vMean;
uint32_t m_rgb;
uint32_t m_type;
};
struct RuntimeSignature
{
int32_t m_uMin;
int32_t m_uMax;
int32_t m_vMin;
int32_t m_vMax;
uint32_t m_rgbSat;
};
typedef SimpleVector<Point16> Points;
class IterPixel
{
public:
IterPixel(const Frame8 &frame, const RectA &region);
IterPixel(const Frame8 &frame, const Points *points);
bool next(UVPixel *uv, RGBPixel *rgb=NULL);
bool reset(bool cleari=true);
uint32_t averageRgb(uint32_t *pixels=NULL);
private:
bool nextHelper(UVPixel *uv, RGBPixel *rgb);
Frame8 m_frame;
RectA m_region;
uint32_t m_x, m_y;
uint8_t *m_pixels;
const Points *m_points;
int m_i;
};
class ColorLUT
{
public:
ColorLUT(uint8_t *lut);
~ColorLUT();
int generateSignature(const Frame8 &frame, const RectA &region, uint8_t signum);
int generateSignature(const Frame8 &frame, const Point16 &point, Points *points, uint8_t signum);
ColorSignature *getSignature(uint8_t signum);
int setSignature(uint8_t signum, const ColorSignature &sig);
int generateLUT();
void clearLUT(uint8_t signum=0);
void updateSignature(uint8_t signum);
void growRegion(const Frame8 &frame, const Point16 &seed, Points *points);
void setSigRange(uint8_t signum, float range);
void setMinBrightness(float miny);
void setGrowDist(uint32_t dist);
void setCCGain(float gain);
uint32_t getType(uint8_t signum);
// these should be in little access methods, but they're here to speed things up a tad
ColorSignature m_signatures[CL_NUM_SIGNATURES];
RuntimeSignature m_runtimeSigs[CL_NUM_SIGNATURES];
uint32_t m_miny;
private:
bool growRegion(RectA *region, const Frame8 &frame, uint8_t dir);
float testRegion(const RectA &region, const Frame8 &frame, UVPixel *mean, Points *points);
void calcRatios(IterPixel *ip, ColorSignature *sig, float ratios[]);
void iterate(IterPixel *ip, ColorSignature *sig);
void getMean(const RectA &region ,const Frame8 &frame, UVPixel *mean);
uint8_t *m_lut;
uint32_t m_maxDist;
float m_ratio;
float m_minRatio;
float m_ccGain;
float m_sigRanges[CL_NUM_SIGNATURES];
};
#endif // COLORLUT_H
-7
View File
@@ -1,7 +0,0 @@
#ifndef DEBUG_H
#define DEBUG_H
#define DBG(...)
#endif // DEBUG_H
-36
View File
@@ -1,36 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#ifndef __DEBUG_H__
#define __DEBUG_H__
#include <stdarg.h>
#include <stdio.h>
static void log(const char *format, ...)
{
#ifdef DEBUG
va_list elements;
// Send debug message to stdout //
va_start(elements, format);
vfprintf(stderr,format, elements);
fflush(stderr);
va_end(elements);
#else
(void)format;
#endif
}
#endif
-26
View File
@@ -1,26 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#ifndef __INTERPRETER_HPP__
#define __INTERPRETER_HPP__
class Interpreter
{
public:
virtual void interpret_data(const void *data []) = 0;
};
#endif
-76
View File
@@ -1,76 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#ifndef LINK_H
#define LINK_H
#include <stdint.h>
// flags
#define LINK_FLAG_SHARED_MEM 0x01
#define LINK_FLAG_ERROR_CORRECTED 0x02
// result codes
#define LINK_RESULT_OK 0
#define LINK_RESULT_ERROR -100
#define LINK_RESULT_ERROR_RECV_TIMEOUT -101
#define LINK_RESULT_ERROR_SEND_TIMEOUT -102
// link flag index
#define LINK_FLAG_INDEX_FLAGS 0x00
#define LINK_FLAG_INDEX_SHARED_MEMORY_LOCATION 0x01
#define LINK_FLAG_INDEX_SHARED_MEMORY_SIZE 0x02
class Link
{
public:
Link()
{
m_flags = 0;
m_blockSize = 0;
}
~Link()
{
}
// the timeoutMs is a timeout value in milliseconds. The timeout timer should expire
// when the data channel has been continuously idle for the specified amount of time
// not the summation of the idle times.
virtual int send(const uint8_t *data, uint32_t len, uint16_t timeoutMs) = 0;
virtual int receive(uint8_t *data, uint32_t len, uint16_t timeoutMs) = 0;
virtual void setTimer() = 0;
virtual uint32_t getTimer() = 0; // returns elapsed time in milliseconds since setTimer() was called
virtual uint32_t getFlags(uint8_t index=LINK_FLAG_INDEX_FLAGS)
{
if (index==LINK_FLAG_INDEX_FLAGS)
return m_flags;
else
return 0;
}
virtual uint32_t blockSize()
{
return m_blockSize;
}
virtual int getBuffer(uint8_t **, uint32_t *)
{
return LINK_RESULT_ERROR;
}
protected:
uint32_t m_flags;
uint32_t m_blockSize;
};
#endif // LINK_H
-466
View File
@@ -1,466 +0,0 @@
#include <stdio.h>
#include <string.h>
#include "pixy.h"
#include "pixydefs.h"
#include "pixyinterpreter.hpp"
PixyInterpreter interpreter;
/**
\mainpage libpixyusb-0.4 API Reference
\section introduction Introduction
libpixyusb is an open source library that allows you to communicate with
Pixy over the USB protocol.
This documentation is aimed at application developers wishing to send
commands to Pixy or read sensor data from Pixy.
\section library_features Library features
- Read blocks with or without color codes
- RGB LED control (color/intensity)
- Auto white balance control
- Auto exposure compensation control
- Brightness control
- Servo position control/query
- Custom commands
\section dependencies Dependencies
Required to build:
- <a href=http://www.cmake.org>cmake</a>
Required for runtime:
- <a href=http://www.libusb.org>libusb</a>
- <a href=http://www.boost.org>libboost</a>
\section getting_started Getting Started
The libpixyusb API reference documentation can be found here:
libpixyusb API Reference
Some tutorials that use libpixyusb can be found here:
<a href=http://cmucam.org/projects/cmucam5/wiki/Hooking_up_Pixy_to_a_Raspberry_Pi>Hooking up Pixy to a Raspberry Pi</a>
<a href=http://cmucam.org/projects/cmucam5/wiki/Hooking_up_Pixy_to_a_Beaglebone_Black>Hooking up Pixy to a BeagleBone Black</a>
\section getting_help Getting Help
Tutorials, walkthroughs, and more are available on the Pixy wiki page:
<a href=http://www.cmucam.org/projects/cmucam5/wiki>Pixy Developer Wiki Page</a>
Our friendly developers and users might be able to answer your question on the forums:
<a href=http://www.cmucam.org/projects/cmucam5/boards/9>Pixy Software Discussion Forum</a>
<a href=http://www.cmucam.org/projects/cmucam5/boards/8>Pixy Hardware Discussion Forum</a>
*/
// Pixy C API //
extern "C"
{
static struct
{
int error;
const char * text;
} PIXY_ERROR_TABLE[] = {
{ 0, "Success" },
//{ PIXY_ERROR_USB_IO, "USB Error: I/O" },
//{ PIXY_ERROR_USB_BUSY, "USB Error: Busy" },
//{ PIXY_ERROR_USB_NO_DEVICE, "USB Error: No device" },
//{ PIXY_ERROR_USB_NOT_FOUND, "USB Error: Target not found" },
{ PIXY_ERROR_CHIRP, "Chirp Protocol Error" },
{ PIXY_ERROR_INVALID_COMMAND, "Pixy Error: Invalid command" },
{ 0, 0 }
};
static int pixy_initialized = false;
int pixy_init()
{
int return_value;
return_value = interpreter.init();
if(return_value == 0)
{
pixy_initialized = true;
}
return return_value;
}
int pixy_get_blocks(uint16_t max_blocks, struct Block * blocks)
{
return interpreter.get_blocks(max_blocks, blocks);
}
int pixy_blocks_are_new()
{
return interpreter.blocks_are_new();
}
int pixy_service()
{
//Service calls are commented at the moment because they cause problems with USB on the discovery.
//TODO: Fix problems.
return -1;
//return interpreter.service();
}
int pixy_command(const char *name, ...)
{
va_list arguments;
int return_value;
if(!pixy_initialized) return -1;
va_start(arguments, name);
return_value = interpreter.send_command(name, arguments);
va_end(arguments);
return return_value;
}
void pixy_close()
{
if(!pixy_initialized) return;
interpreter.close();
}
void pixy_error(int error_code)
{
int index;
// Convert pixy error code to string and display to stdout //
index = 0;
while(PIXY_ERROR_TABLE[index].text != 0) {
if(PIXY_ERROR_TABLE[index].error == error_code) {
fprintf(stderr,"%s\n", PIXY_ERROR_TABLE[index].text);
return;
}
index += 1;
}
fprintf(stderr,"Undefined error: [%d]\n", error_code);
}
int pixy_led_set_RGB(uint8_t red, uint8_t green, uint8_t blue)
{
int chirp_response;
int return_value;
uint32_t RGB;
// Pack the RGB value //
RGB = blue + (green << 8) + (red << 16);
return_value = pixy_command("led_set", INT32(RGB), END_OUT_ARGS, &chirp_response, END_IN_ARGS);
if (return_value < 0) {
// Error //
return return_value;
} else {
// Success //
return chirp_response;
}
}
int pixy_led_set_max_current(uint32_t current)
{
int chirp_response;
int return_value;
return_value = pixy_command("led_setMaxCurrent", INT32(current), END_OUT_ARGS, &chirp_response, END_IN_ARGS);
if (return_value < 0) {
// Error //
return return_value;
} else {
// Success //
return chirp_response;
}
}
int pixy_led_get_max_current()
{
int return_value;
uint32_t chirp_response;
return_value = pixy_command("led_getMaxCurrent", END_OUT_ARGS, &chirp_response, END_IN_ARGS);
if (return_value < 0) {
// Error //
return return_value;
} else {
// Success //
return chirp_response;
}
}
int pixy_cam_set_auto_white_balance(uint8_t enable)
{
int return_value;
uint32_t chirp_response;
return_value = pixy_command("cam_setAWB", UINT8(enable), END_OUT_ARGS, &chirp_response, END_IN_ARGS);
if (return_value < 0) {
// Error //
return return_value;
} else {
// Success //
return chirp_response;
}
}
int pixy_cam_get_auto_white_balance()
{
int return_value;
uint32_t chirp_response;
return_value = pixy_command("cam_getAWB", END_OUT_ARGS, &chirp_response, END_IN_ARGS);
if (return_value < 0) {
// Error //
return return_value;
} else {
// Success //
return chirp_response;
}
}
uint32_t pixy_cam_get_white_balance_value()
{
int return_value;
uint32_t chirp_response;
return_value = pixy_command("cam_getWBV", END_OUT_ARGS, &chirp_response, END_IN_ARGS);
if (return_value < 0) {
// Error //
return return_value;
} else {
// Success //
return chirp_response;
}
}
int pixy_cam_set_white_balance_value(uint8_t red, uint8_t green, uint8_t blue)
{
int return_value;
uint32_t chirp_response;
uint32_t white_balance;
white_balance = green + (red << 8) + (blue << 16);
return_value = pixy_command("cam_setAWB", UINT32(white_balance), END_OUT_ARGS, &chirp_response, END_IN_ARGS);
if (return_value < 0) {
// Error //
return return_value;
} else {
// Success //
return chirp_response;
}
}
int pixy_cam_set_auto_exposure_compensation(uint8_t enable)
{
int return_value;
uint32_t chirp_response;
return_value = pixy_command("cam_setAEC", UINT8(enable), END_OUT_ARGS, &chirp_response, END_IN_ARGS);
if (return_value < 0) {
// Error //
return return_value;
} else {
// Success //
return chirp_response;
}
}
int pixy_cam_get_auto_exposure_compensation()
{
int return_value;
uint32_t chirp_response;
return_value = pixy_command("cam_getAEC", END_OUT_ARGS, &chirp_response, END_IN_ARGS);
if (return_value < 0) {
// Error //
return return_value;
} else {
// Success //
return chirp_response;
}
}
int pixy_cam_set_exposure_compensation(uint8_t gain, uint16_t compensation)
{
int return_value;
uint32_t chirp_response;
uint32_t exposure;
exposure = gain + (compensation << 8);
return_value = pixy_command("cam_setECV", UINT32(exposure), END_OUT_ARGS, &chirp_response, END_IN_ARGS);
if (return_value < 0) {
// Error //
return return_value;
} else {
// Success //
return chirp_response;
}
}
int pixy_cam_get_exposure_compensation(uint8_t * gain, uint16_t * compensation)
{
uint32_t exposure;
int return_value;
return_value = pixy_command("cam_getECV", END_OUT_ARGS, &exposure, END_IN_ARGS);
if (return_value < 0) {
// Chirp error //
return return_value;
}
if(gain == 0 || compensation == 0) {
// Error: Null pointer //
return PIXY_ERROR_INVALID_PARAMETER;
}
fprintf(stderr,"exp:%08x\n", exposure);
*gain = exposure & 0xFF;
*compensation = 0xFFFF & (exposure >> 8);
return 0;
}
int pixy_cam_set_brightness(uint8_t brightness)
{
int chirp_response;
int return_value;
return_value = pixy_command("cam_setBrightness", UINT8(brightness), END_OUT_ARGS, &chirp_response, END_IN_ARGS);
if (return_value < 0) {
// Error //
return return_value;
} else {
// Success //
return chirp_response;
}
}
int pixy_cam_get_brightness()
{
int chirp_response;
int return_value;
return_value = pixy_command("cam_getBrightness", END_OUT_ARGS, &chirp_response, END_IN_ARGS);
if (return_value < 0) {
// Error //
return return_value;
} else {
// Success //
return chirp_response;
}
}
int pixy_rcs_get_position(uint8_t channel)
{
int chirp_response;
int return_value;
return_value = pixy_command("rcs_getPos", UINT8(channel), END_OUT_ARGS, &chirp_response, END_IN_ARGS);
if (return_value < 0) {
// Error //
return return_value;
} else {
// Success //
return chirp_response;
}
}
int pixy_rcs_set_position(uint8_t channel, uint16_t position)
{
int chirp_response;
int return_value;
return_value = pixy_command("rcs_setPos", UINT8(channel), INT16(position), END_OUT_ARGS, &chirp_response, END_IN_ARGS);
if (return_value < 0) {
// Error //
return return_value;
} else {
// Success //
return chirp_response;
}
}
int pixy_rcs_set_frequency(uint16_t frequency)
{
int chirp_response;
int return_value;
return_value = pixy_command("rcs_setFreq", UINT16(frequency), END_OUT_ARGS, &chirp_response, END_IN_ARGS);
if (return_value < 0) {
// Error //
return return_value;
} else {
// Success //
return chirp_response;
}
}
int pixy_get_firmware_version(uint16_t * major, uint16_t * minor, uint16_t * build)
{
uint16_t * pixy_version;
uint32_t version_length;
uint32_t response;
uint16_t version[3];
int return_value;
if(major == 0 || minor == 0 || build == 0) {
// Error: Null pointer //
return PIXY_ERROR_INVALID_PARAMETER;
}
return_value = pixy_command("version", END_OUT_ARGS, &response, &version_length, &pixy_version, END_IN_ARGS);
if (return_value < 0) {
// Error //
return return_value;
}
memcpy((void *) version, pixy_version, 3 * sizeof(uint16_t));
*major = version[0];
*minor = version[1];
*build = version[2];
return 0;
}
}
-298
View File
@@ -1,298 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#include <string.h>
#include <stdio.h>
#include "pixyinterpreter.hpp"
PixyInterpreter::PixyInterpreter()
{
init_ = false;
receiver_ = NULL;
}
PixyInterpreter::~PixyInterpreter()
{
close();
}
int PixyInterpreter::init()
{
int USB_return_value;
if(init_ == true)
{
fprintf(stderr, "libpixy: Already initialized.");
return 0;
}
USB_return_value = link_.open();
if(USB_return_value < 0) {
return USB_return_value;
}
receiver_ = new ChirpReceiver(&link_, this);
init_ = true;
return 0;
}
void PixyInterpreter::close()
{
if (receiver_)
{
delete receiver_;
receiver_ = NULL;
}
init_ = false;
}
int PixyInterpreter::get_blocks(int max_blocks, Block * blocks)
{
uint16_t number_of_blocks_to_copy;
uint16_t index;
// Check parameters //
if(max_blocks < 0 || blocks == 0) {
return PIXY_ERROR_INVALID_PARAMETER;
}
number_of_blocks_to_copy = (max_blocks >= blocks_.size() ? blocks_.size() : max_blocks);
// Copy blocks //
for (index = 0; index != number_of_blocks_to_copy; ++index) {
memcpy(&blocks[index], &blocks_[index], sizeof(Block));
}
blocks_are_new_ = false;
return number_of_blocks_to_copy;
}
int PixyInterpreter::send_command(const char * name, ...)
{
va_list arguments;
int return_value;
va_start(arguments, name);
return_value = send_command(name, arguments);
va_end(arguments);
return return_value;
}
int PixyInterpreter::send_command(const char * name, va_list args)
{
ChirpProc procedure_id;
int return_value;
va_list arguments;
va_copy(arguments, args);
// Request chirp procedure id for 'name'. //
procedure_id = receiver_->getProc(name);
// Was there an error requesting procedure id? //
if (procedure_id < 0) {
// Request error //
va_end(arguments);
return PIXY_ERROR_INVALID_COMMAND;
}
// Execute chirp synchronous remote procedure call //
return_value = receiver_->call(SYNC, procedure_id, arguments);
va_end(arguments);
return return_value;
}
int PixyInterpreter::service()
{
if(!init_) return -1;
receiver_->service(false);
return 0; //success
}
void PixyInterpreter::interpret_data(const void * chirp_data[])
{
uint8_t chirp_message;
uint32_t chirp_type;
if (chirp_data[0]) {
chirp_message = Chirp::getType(chirp_data[0]);
switch(chirp_message) {
case CRP_TYPE_HINT:
chirp_type = * static_cast<const uint32_t *>(chirp_data[0]);
switch(chirp_type) {
case FOURCC('B', 'A', '8', '1'):
break;
case FOURCC('C', 'C', 'Q', '1'):
break;
case FOURCC('C', 'C', 'B', '1'):
interpret_CCB1(chirp_data + 1);
break;
case FOURCC('C', 'C', 'B', '2'):
interpret_CCB2(chirp_data + 1);
break;
case FOURCC('C', 'M', 'V', '1'):
break;
default:
fprintf(stderr,"libpixy: Chirp hint [%u] not recognized.\n", chirp_type);
break;
}
break;
case CRP_HSTRING:
break;
default:
fprintf(stderr, "libpixy: Unknown message received from Pixy: [%u]\n", chirp_message);
break;
}
}
}
void PixyInterpreter::interpret_CCB1(const void * CCB1_data[])
{
uint32_t number_of_blobs;
const BlobA * blobs;
// Add blocks with normal signatures //
number_of_blobs = * static_cast<const uint32_t *>(CCB1_data[3]);
blobs = static_cast<const BlobA *>(CCB1_data[4]);
number_of_blobs /= sizeof(BlobA) / sizeof(uint16_t);
add_normal_blocks(blobs, number_of_blobs);
blocks_are_new_ = true;
}
void PixyInterpreter::interpret_CCB2(const void * CCB2_data[])
{
uint32_t number_of_blobs;
const BlobA * A_blobs;
const BlobB * B_blobs;
// The blocks container will only contain the newest //
// blocks //
blocks_.clear();
// Add blocks with color code signatures //
number_of_blobs = * static_cast<const uint32_t *>(CCB2_data[5]);
B_blobs = static_cast<const BlobB *>(CCB2_data[6]);
number_of_blobs /= sizeof(BlobB) / sizeof(uint16_t);
add_color_code_blocks(B_blobs, number_of_blobs);
// Add blocks with normal signatures //
number_of_blobs = * static_cast<const uint32_t *>(CCB2_data[3]);
A_blobs = static_cast<const BlobA *>(CCB2_data[4]);
number_of_blobs /= sizeof(BlobA) / sizeof(uint16_t);
add_normal_blocks(A_blobs, number_of_blobs);
blocks_are_new_ = true;
}
void PixyInterpreter::add_normal_blocks(const BlobA * blocks, uint32_t count)
{
uint32_t index;
Block block;
for (index = 0; index != count; ++index) {
// Decode CCB1 'Normal' Signature Type //
block.type = PIXY_BLOCKTYPE_NORMAL;
block.signature = blocks[index].m_model;
block.width = blocks[index].m_right - blocks[index].m_left;
block.height = blocks[index].m_bottom - blocks[index].m_top;
block.x = blocks[index].m_left + block.width / 2;
block.y = blocks[index].m_top + block.height / 2;
// Angle is not a valid parameter for 'Normal' //
// signature types. Setting to zero by default. //
block.angle = 0;
// Store new block in block buffer //
if (blocks_.size() == PIXY_BLOCK_CAPACITY) {
// Blocks buffer is full - replace oldest received block with newest block //
blocks_.erase(blocks_.begin());
blocks_.push_back(block);
} else {
// Add new block to blocks buffer //
blocks_.push_back(block);
}
}
}
void PixyInterpreter::add_color_code_blocks(const BlobB * blocks, uint32_t count)
{
uint32_t index;
Block block;
for (index = 0; index != count; ++index) {
// Decode 'Color Code' Signature Type //
block.type = PIXY_BLOCKTYPE_COLOR_CODE;
block.signature = blocks[index].m_model;
block.width = blocks[index].m_right - blocks[index].m_left;
block.height = blocks[index].m_bottom - blocks[index].m_top;
block.x = blocks[index].m_left + block.width / 2;
block.y = blocks[index].m_top + block.height / 2;
block.angle = blocks[index].m_angle;
// Store new block in block buffer //
if (blocks_.size() == PIXY_BLOCK_CAPACITY) {
// Blocks buffer is full - replace oldest received block with newest block //
blocks_.erase(blocks_.begin());
blocks_.push_back(block);
} else {
// Add new block to blocks buffer //
blocks_.push_back(block);
}
}
}
int PixyInterpreter::blocks_are_new()
{
if (blocks_are_new_) {
// Fresh blocks!! :D //
return 1;
} else {
// Stale blocks... :\ //
return 0;
}
}
-149
View File
@@ -1,149 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#ifndef __PIXYINTERPRETER_HPP__
#define __PIXYINTERPRETER_HPP__
#include <vector>
#include "pixytypes.h"
#include "pixy.h"
#include "pixydefs.h"
#include "usblink.h"
#include "interpreter.hpp"
#include "chirpreceiver.hpp"
#define PIXY_BLOCK_CAPACITY 250
class PixyInterpreter : public Interpreter
{
public:
PixyInterpreter();
~PixyInterpreter();
/**
@brief Spawns an 'interpreter' thread which attempts to
connect to Pixy using the USB interface.
On successful connection, this thread will
capture and store Pixy 'block' object data
which can be retreived using the getBlocks()
method.
@return 0 Success
@return -1 Error: Unable to open pixy USB device
*/
int init();
/**
@brief Terminates the USB connection to Pixy and
the 'iterpreter' thread.
*/
void close();
/**
@brief Get status of the block data received from Pixy.
@return 0 Stale Data: Block data has previously been retrieved using 'pixy_get_blocks()'.
@return 1 New Data: Pixy sent new data that has not been retrieve yet.
*/
int blocks_are_new();
/**
@brief Copies up to 'max_blocks' number of Blocks to the address pointed
to by 'blocks'.
@param[in] max_blocks Maximum number of Blocks to copy to the address pointed to
by 'blocks'.
@param[out] blocks Address of an array in which to copy the blocks to.
The array must be large enough to write 'max_blocks' number
of Blocks to.
@return Non-negative Success: Number of blocks copied
@return PIXY_ERROR_USB_IO USB Error: I/O
@return PIXY_ERROR_NOT_FOUND USB Error: Pixy not found
@return PIXY_ERROR_USB_BUSY USB Error: Busy
@return PIXY_ERROR_USB_NO_DEVICE USB Error: No device
@return PIXY_ERROR_INVALID_PARAMETER Invalid pararmeter specified
*/
int get_blocks(int max_blocks, Block * blocks);
/**
@brief Sends a command to Pixy.
@param[in] name Remote procedure call identifier string.
@param[in,out] arguments Argument list to function call.
@return -1 Error
*/
int send_command(const char * name, va_list arguments);
/**
@brief Sends a command to Pixy.
@param[in] name Remote procedure call identifier string.
@return -1 Error
*/
int send_command(const char * name, ...);
int service();
private:
ChirpReceiver * receiver_;
USBLink link_;
std::vector<Block> blocks_;
bool blocks_are_new_;
bool init_;
/**
@brief Interprets data sent from Pixy over the Chirp protocol.
@param[in] data Incoming Chirp protocol data from Pixy.
*/
void interpret_data(const void * chrip_data[]);
/**
@brief Interprets CCB1 messages sent from Pixy.
@param[in] data Incoming Chirp protocol data from Pixy.
*/
void interpret_CCB1(const void * data[]);
/**
@brief Interprets CCB2 messages sent from Pixy.
@param[in] data Incoming Chirp protocol data from Pixy.
*/
void interpret_CCB2(const void * data[]);
/**
@brief Adds blocks with normal signatures to the PixyInterpreter
'blocks_' buffer.
@param[in] blocks An array of normal signature blocks to add to buffer.
@param[in] count Size of the 'blocks' array.
*/
void add_normal_blocks(const BlobA * blocks, uint32_t count);
/**
@brief Adds blocks with color code signatures to the PixyInterpreter
'blocks_' buffer.
@param[in] blocks An array of color code signature blocks to add to buffer.
@param[in] count Size of the 'blocks' array.
*/
void add_color_code_blocks(const BlobB * blocks, uint32_t count);
};
#endif
-271
View File
@@ -1,271 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#ifndef PIXYTYPES_H
#define PIXYTYPES_H
#include <stdint.h>
#define RENDER_FLAG_FLUSH 0x01 // add to stack, render immediately
#define RENDER_FLAG_BLEND 0x02 // blend with a previous images in image stack
#define PRM_FLAG_INTERNAL 0x00000001
#define PRM_FLAG_ADVANCED 0x00000002
#define PRM_FLAG_HEX_FORMAT 0x00000010
#define PRM_FLAG_SIGNED 0x00000080
// render-specific flags
#define PRM_FLAG_SLIDER 0x00000100
#define PRM_FLAG_CHECKBOX 0x00000200
#define PRM_FLAG_PATH 0x00000400
// events
#define EVT_PARAM_CHANGE 1
struct Point16
{
Point16()
{
m_x = m_y = 0;
}
Point16(int16_t x, int16_t y)
{
m_x = x;
m_y = y;
}
int16_t m_x;
int16_t m_y;
};
struct Point32
{
Point32()
{
m_x = m_y = 0;
}
Point32(int32_t x, int32_t y)
{
m_x = x;
m_y = y;
}
int32_t m_x;
int32_t m_y;
};
struct Frame8
{
Frame8()
{
m_pixels = (uint8_t *)NULL;
m_width = m_height = 0;
}
Frame8(uint8_t *pixels, uint16_t width, uint16_t height)
{
m_pixels = pixels;
m_width = width;
m_height = height;
}
uint8_t *m_pixels;
int16_t m_width;
int16_t m_height;
};
struct RectA
{
RectA()
{
m_xOffset = m_yOffset = m_width = m_height = 0;
}
RectA(uint16_t xOffset, uint16_t yOffset, uint16_t width, uint16_t height)
{
m_xOffset = xOffset;
m_yOffset = yOffset;
m_width = width;
m_height = height;
}
uint16_t m_xOffset;
uint16_t m_yOffset;
uint16_t m_width;
uint16_t m_height;
};
struct RectB
{
RectB()
{
m_left = m_right = m_top = m_bottom = 0;
}
RectB(uint16_t left, uint16_t right, uint16_t top, uint16_t bottom)
{
m_left = left;
m_right = right;
m_top = top;
m_bottom = bottom;
}
uint16_t m_left;
uint16_t m_right;
uint16_t m_top;
uint16_t m_bottom;
};
struct BlobA
{
BlobA()
{
m_model = m_left = m_right = m_top = m_bottom = 0;
}
BlobA(uint16_t model, uint16_t left, uint16_t right, uint16_t top, uint16_t bottom)
{
m_model = model;
m_left = left;
m_right = right;
m_top = top;
m_bottom = bottom;
}
uint16_t m_model;
uint16_t m_left;
uint16_t m_right;
uint16_t m_top;
uint16_t m_bottom;
};
struct BlobB
{
BlobB()
{
m_model = m_left = m_right = m_top = m_bottom = m_angle = 0;
}
BlobB(uint16_t model, uint16_t left, uint16_t right, uint16_t top, uint16_t bottom, int16_t angle)
{
m_model = model;
m_left = left;
m_right = right;
m_top = top;
m_bottom = bottom;
m_angle = angle;
}
uint16_t m_model;
uint16_t m_left;
uint16_t m_right;
uint16_t m_top;
uint16_t m_bottom;
int16_t m_angle;
};
struct HuePixel
{
HuePixel()
{
m_u = m_v = 0;
}
HuePixel(int8_t u, int8_t v)
{
m_u = u;
m_v = v;
}
int8_t m_u;
int8_t m_v;
};
struct Fpoint
{
Fpoint()
{
m_x = m_y = 0.0;
}
Fpoint(float x, float y)
{
m_x = x;
m_y = y;
}
float m_x;
float m_y;
};
struct UVPixel
{
UVPixel()
{
m_u = m_v = 0;
}
UVPixel(int32_t u, int32_t v)
{
m_u = u;
m_v = v;
}
int32_t m_u;
int32_t m_v;
};
struct RGBPixel
{
RGBPixel()
{
m_r = m_g = m_b = 0;
}
RGBPixel(uint8_t r, uint8_t g, uint8_t b)
{
m_r = r;
m_g = g;
m_b = b;
}
uint8_t m_r;
uint8_t m_g;
uint8_t m_b;
};
struct Line
{
Line()
{
m_slope = m_yi = 0.0;
}
Line(float slope, float yi)
{
m_slope = slope;
m_yi = yi;
}
float m_slope;
float m_yi;
};
typedef long long longlong;
#endif // PIXYTYPES_H
@@ -1,103 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#include <string.h>
#include "qqueue.h"
#ifdef PIXY
#include <pixyvals.h>
#endif
Qqueue::Qqueue()
{
#ifdef PIXY
m_fields = (QqueueFields *)QQ_LOC;
#else
m_fields = (QqueueFields *)(new uint8_t[QQ_SIZE]);
#endif
memset((void *)m_fields, 0, sizeof(QqueueFields));
}
Qqueue::~Qqueue()
{
#ifdef PIXY
#else
delete [] m_fields;
#endif
}
uint32_t Qqueue::dequeue(Qval *val)
{
uint16_t len = m_fields->produced - m_fields->consumed;
if (len)
{
*val = m_fields->data[m_fields->readIndex++];
m_fields->consumed++;
if (m_fields->readIndex==QQ_MEM_SIZE)
m_fields->readIndex = 0;
return 1;
}
return 0;
}
#ifndef PIXY
int Qqueue::enqueue(Qval *val)
{
uint16_t len = m_fields->produced - m_fields->consumed;
uint16_t freeLen = QQ_MEM_SIZE-len;
if (freeLen>0)
{
m_fields->data[m_fields->writeIndex++] = *val;
m_fields->produced++;
if (m_fields->writeIndex==QQ_MEM_SIZE)
m_fields->writeIndex = 0;
return 1;
}
return 0;
}
#endif
uint32_t Qqueue::readAll(Qval *mem, uint32_t size)
{
uint16_t len = m_fields->produced - m_fields->consumed;
uint16_t i, j;
for (i=0, j=m_fields->readIndex; i<len && i<size; i++)
{
mem[i] = m_fields->data[j++];
if (j==QQ_MEM_SIZE)
j = 0;
}
// flush the rest
m_fields->consumed += len;
m_fields->readIndex += len;
if (m_fields->readIndex>=QQ_MEM_SIZE)
m_fields->readIndex -= QQ_MEM_SIZE;
return i;
}
void Qqueue::flush()
{
uint16_t len = m_fields->produced - m_fields->consumed;
m_fields->consumed += len;
m_fields->readIndex += len;
if (m_fields->readIndex>=QQ_MEM_SIZE)
m_fields->readIndex -= QQ_MEM_SIZE;
}
-105
View File
@@ -1,105 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#ifndef _QQUEUE_H
#define _QQUEUE_H
#include <inttypes.h>
#define QQ_LOC SRAM4_LOC
#ifdef PIXY
#define QQ_SIZE 0x3c00
#else
#define QQ_SIZE 0x30000
#endif
#define QQ_MEM_SIZE ((QQ_SIZE-sizeof(struct QqueueFields)+sizeof(Qval))/sizeof(Qval))
#ifdef __cplusplus
struct Qval
#else
typedef struct
#endif
{
#ifdef __cplusplus
Qval()
{
m_u = m_v = m_y = m_col = 0;
}
Qval(int16_t u, int16_t v, uint16_t y, uint16_t col)
{
m_u = u;
m_v = v;
m_y = y;
m_col = col;
}
#endif
uint16_t m_col;
int16_t m_v;
int16_t m_u;
uint16_t m_y;
#ifdef __cplusplus
};
#else
} Qval;
#endif
struct QqueueFields
{
uint16_t readIndex;
uint16_t writeIndex;
uint16_t produced;
uint16_t consumed;
// (array size below doesn't matter-- we're just going to cast a pointer to this struct)
Qval data[1]; // data
};
#ifdef __cplusplus // M4 is C++ and the "consumer" of data
class Qqueue
{
public:
Qqueue();
~Qqueue();
uint32_t dequeue(Qval *val);
uint32_t queued()
{
return m_fields->produced - m_fields->consumed;
}
#ifndef PIXY
int enqueue(Qval *val);
#endif
uint32_t readAll(Qval *mem, uint32_t size);
void flush();
private:
QqueueFields *m_fields;
};
#else // M0 is C and the "producer" of data (Qvals)
uint32_t qq_enqueue(const Qval *val);
uint16_t qq_free(void);
extern struct QqueueFields *g_qqueue;
#endif
#endif
-95
View File
@@ -1,95 +0,0 @@
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// cmucam@cs.cmu.edu. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
#ifndef SIMPLEVECTOR_H
#define SIMPLEVECTOR_H
#include <new>
#define SPARE_CAPACITY 16
template <typename Object> class SimpleVector
{
public:
SimpleVector(int initSize = 0)
: m_size(0), m_capacity(initSize + SPARE_CAPACITY)
{ m_objects = new Object[m_capacity]; }
~SimpleVector()
{ delete [] m_objects; }
int resize(int newCapacity)
{
if(newCapacity < m_size)
return 0;
Object *oldArray = m_objects;
m_objects = new (std::nothrow) Object[newCapacity];
if (m_objects==NULL)
{
m_objects = oldArray;
return -1;
}
for(int k = 0; k<m_size; k++)
m_objects[k] = oldArray[k];
m_capacity = newCapacity;
delete [] oldArray;
return 0;
}
Object & operator[](int index)
{ return m_objects[index]; }
const Object& operator[](int index) const
{ return m_objects[index]; }
bool empty() const
{ return size()==0; }
int size() const
{ return m_size; }
int capacity() const
{ return m_capacity; }
const Object *data()
{ return m_objects; }
int push_back(const Object& x)
{
if(m_size == m_capacity)
if (resize(m_capacity + SPARE_CAPACITY)<0)
return -1;
m_objects[m_size++] = x;
return 0;
}
void pop_back()
{ m_size--; }
void clear()
{ m_size = 0; }
private:
int m_size;
int m_capacity;
Object *m_objects;
};
#endif // SIMPLEVECTOR_H
-52
View File
@@ -1,52 +0,0 @@
#include <unistd.h>
#include <stdio.h>
#include "usblink.h"
#include "pixy.h"
#include "debuglog.h"
extern "C" {
extern int USBH_LL_open();
extern int USBH_LL_close();
extern int USBH_LL_send(const uint8_t *data, uint32_t len, uint16_t timeoutMs);
extern int USBH_LL_receive(uint8_t *data, uint32_t len, uint16_t timeoutMs);
extern void USBH_LL_setTimer();
extern uint32_t USBH_LL_getTimer();
}
USBLink::USBLink()
{
m_blockSize = 64;
m_flags = LINK_FLAG_ERROR_CORRECTED;
}
USBLink::~USBLink()
{
USBH_LL_close();
}
int USBLink::open()
{
return USBH_LL_open();
}
int USBLink::send(const uint8_t *data, uint32_t len, uint16_t timeoutMs)
{
return USBH_LL_send(data,len,timeoutMs);
}
int USBLink::receive(uint8_t *data, uint32_t len, uint16_t timeoutMs)
{
return USBH_LL_receive(data,len,timeoutMs);
}
void USBLink::setTimer()
{
USBH_LL_setTimer();
}
uint32_t USBLink::getTimer()
{
return USBH_LL_getTimer();
}
-20
View File
@@ -1,20 +0,0 @@
#ifndef __USBLINK_H__
#define __USBLINK_H__
#include "link.h"
class USBLink : public Link
{
public:
USBLink();
~USBLink();
int open();
virtual int send(const uint8_t *data, uint32_t len, uint16_t timeoutMs);
virtual int receive(uint8_t *data, uint32_t len, uint16_t timeoutMs);
virtual void setTimer();
virtual uint32_t getTimer();
};
#endif
-70
View File
@@ -1,70 +0,0 @@
#2015 by tmoe, id10101 (and the internet :) )
#TODO Fix hacky includes and sources directories and obj folder stuff
TARGET=libusbhost
#Tools
CROSS_COMPILE=arm-none-eabi-
CC=$(CROSS_COMPILE)gcc
AR=$(CROSS_COMPILE)ar
RMDIR = rm -rf
RM=rm -f
MKDIR=mkdir -p
#Directories
SRC_DIR=./STM32_USB_HOST_Library/Core/src
SRC_DIR2=./STM32_USB_OTG_Driver/src
INC_DIR=./STM32_USB_HOST_Library/Core/inc
INC_DIR2=./STM32_USB_OTG_Driver/inc
INC_DIR3=./STM32_USB_Device_Specific/
INC_CORE_DIR=../StmCoreNPheriph/inc
OBJ_DIR=./obj
#Architecture flags
FP_FLAGS?=-mfpu=fpv4-sp-d16 -mfloat-abi=softfp
ARCH_FLAGS=-mthumb -mcpu=cortex-m4 $(FP_FLAGS)
#Compiler, Linker Options
CPPFLAGS=-DUSE_USB_OTG_FS -DUSE_HOST_MODE -I$(INC_DIR) -I$(INC_DIR2) -I$(INC_DIR3) -I$(INC_CORE_DIR)
CFLAGS=$(ARCH_FLAGS) -O0 -g -ffunction-sections -fdata-sections
#CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork
#CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
#Finding Input files
CFILES=$(shell find $(SRC_DIR) $(SRC_DIR2) -name '*.c')
#Generate corresponding obj names
COBJS=$(CFILES:.c=.o)
OBJS=$(patsubst $(SRC_DIR)/%,$(OBJ_DIR)/%,$(patsubst $(SRC_DIR2)/%,$(OBJ_DIR)/%,$(COBJS)))
#Keep the objects files
.SECONDARY: $(OBJS)
#Mark targets which are not "file-targets"
.PHONY: all clean
# List of all binaries to build
all: $(TARGET).a
#objects to lib
%.a : $(OBJS)
@echo Linking...
$(AR) rcs $@ $^
#C files to objects
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
@echo Compiling $<...
$(MKDIR) $(OBJ_DIR)
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
$(OBJ_DIR)/%.o: $(SRC_DIR2)/%.c
@echo Compiling $<...
$(MKDIR) $(OBJ_DIR)
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
#Clean Obj files and builded stuff
clean:
$(RMDIR) $(OBJ_DIR)
$(RM) $(TARGET).a
@@ -1,242 +0,0 @@
/**
******************************************************************************
* @file Audio_playback_and_record/inc/usb_conf.h
* @author MCD Application Team
* @version V1.0.0
* @date 28-October-2011
* @brief General low level driver configuration
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_CONF__H__
#define __USB_CONF__H__
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
/** @addtogroup USB_OTG_DRIVER
* @{
*/
/** @defgroup USB_CONF
* @brief USB low level driver configuration file
* @{
*/
/** @defgroup USB_CONF_Exported_Defines
* @{
*/
/* USB Core and PHY interface configuration.
Tip: To avoid modifying these defines each time you need to change the USB
configuration, you can declare the needed define in your toolchain
compiler preprocessor.
*/
#ifndef USE_USB_OTG_FS
//#define USE_USB_OTG_FS
#endif /* USE_USB_OTG_FS */
#ifndef USE_USB_OTG_HS
//#define USE_USB_OTG_HS
#endif /* USE_USB_OTG_HS */
#ifndef USE_ULPI_PHY
//#define USE_ULPI_PHY
#endif /* USE_ULPI_PHY */
#ifndef USE_EMBEDDED_PHY
//#define USE_EMBEDDED_PHY
#endif /* USE_EMBEDDED_PHY */
#ifndef USE_I2C_PHY
//#define USE_I2C_PHY
#endif /* USE_I2C_PHY */
#ifdef USE_USB_OTG_FS
#define USB_OTG_FS_CORE
#endif
#ifdef USE_USB_OTG_HS
#define USB_OTG_HS_CORE
#endif
/*******************************************************************************
* FIFO Size Configuration in Host mode
*
* (i) Receive data FIFO size = (Largest Packet Size / 4) + 1 or
* 2x (Largest Packet Size / 4) + 1, If a
* high-bandwidth channel or multiple isochronous
* channels are enabled
*
* (ii) For the host nonperiodic Transmit FIFO is the largest maximum packet size
* for all supported nonperiodic OUT channels. Typically, a space
* corresponding to two Largest Packet Size is recommended.
*
* (iii) The minimum amount of RAM required for Host periodic Transmit FIFO is
* the largest maximum packet size for all supported periodic OUT channels.
* If there is at least one High Bandwidth Isochronous OUT endpoint,
* then the space must be at least two times the maximum packet size for
* that channel.
*******************************************************************************/
/****************** USB OTG HS CONFIGURATION **********************************/
#ifdef USB_OTG_HS_CORE
#define RX_FIFO_HS_SIZE 512
#define TXH_NP_HS_FIFOSIZ 256
#define TXH_P_HS_FIFOSIZ 256
//#define USB_OTG_HS_LOW_PWR_MGMT_SUPPORT
//#define USB_OTG_HS_SOF_OUTPUT_ENABLED
#ifdef USE_ULPI_PHY
#define USB_OTG_ULPI_PHY_ENABLED
#endif
#ifdef USE_EMBEDDED_PHY
#define USB_OTG_EMBEDDED_PHY_ENABLED
#endif
#ifdef USE_I2C_PHY
#define USB_OTG_I2C_PHY_ENABLED
#endif
#define USB_OTG_HS_INTERNAL_DMA_ENABLED
#define USB_OTG_EXTERNAL_VBUS_ENABLED
//#define USB_OTG_INTERNAL_VBUS_ENABLED
#endif
/****************** USB OTG FS CONFIGURATION **********************************/
#ifdef USB_OTG_FS_CORE
#define RX_FIFO_FS_SIZE 128
#define TXH_NP_FS_FIFOSIZ 96
#define TXH_P_FS_FIFOSIZ 96
//#define USB_OTG_FS_LOW_PWR_MGMT_SUPPORT
//#define USB_OTG_FS_SOF_OUTPUT_ENABLED
#endif
/****************** USB OTG MODE CONFIGURATION ********************************/
//#define USE_HOST_MODE
//#define USE_DEVICE_MODE
//#define USE_OTG_MODE
#ifndef USB_OTG_FS_CORE
#ifndef USB_OTG_HS_CORE
#error "USB_OTG_HS_CORE or USB_OTG_FS_CORE should be defined"
#endif
#endif
#ifndef USE_DEVICE_MODE
#ifndef USE_HOST_MODE
#error "USE_DEVICE_MODE or USE_HOST_MODE should be defined"
#endif
#endif
#ifndef USE_USB_OTG_HS
#ifndef USE_USB_OTG_FS
#error "USE_USB_OTG_HS or USE_USB_OTG_FS should be defined"
#endif
#else //USE_USB_OTG_HS
#ifndef USE_ULPI_PHY
#ifndef USE_EMBEDDED_PHY
#ifndef USE_I2C_PHY
#error "USE_ULPI_PHY or USE_EMBEDDED_PHY or USE_I2C_PHY should be defined"
#endif
#endif
#endif
#endif
/****************** C Compilers dependant keywords ****************************/
/* In HS mode and when the DMA is used, all variables and data structures dealing
with the DMA during the transaction process should be 4-bytes aligned */
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
#if defined (__GNUC__) /* GNU Compiler */
#define __ALIGN_END __attribute__ ((aligned (4)))
#define __ALIGN_BEGIN
#else
#define __ALIGN_END
#if defined (__CC_ARM) /* ARM Compiler */
#define __ALIGN_BEGIN __align(4)
#elif defined (__ICCARM__) /* IAR Compiler */
#define __ALIGN_BEGIN
#elif defined (__TASKING__) /* TASKING Compiler */
#define __ALIGN_BEGIN __align(4)
#endif /* __CC_ARM */
#endif /* __GNUC__ */
#else
#define __ALIGN_BEGIN
#define __ALIGN_END
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
/* __packed keyword used to decrease the data type alignment to 1-byte */
#if defined (__CC_ARM) /* ARM Compiler */
#define __packed __packed
#elif defined (__ICCARM__) /* IAR Compiler */
#define __packed __packed
#elif defined ( __GNUC__ ) /* GNU Compiler */
// #define __packed __attribute__ ((__packed__))
#elif defined (__TASKING__) /* TASKING Compiler */
#define __packed __unaligned
#endif /* __CC_ARM */
/**
* @}
*/
/** @defgroup USB_CONF_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup USB_CONF_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USB_CONF_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USB_CONF_Exported_FunctionsPrototype
* @{
*/
/**
* @}
*/
#endif //__USB_CONF__H__
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
@@ -1,94 +0,0 @@
/**
******************************************************************************
* @file Audio_playback_and_record/inc/USBH_conf.h
* @author MCD Application Team
* @version V1.0.0
* @date 28-October-2011
* @brief General low level driver configuration
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBH_CONF__H__
#define __USBH_CONF__H__
/* Includes ------------------------------------------------------------------*/
/** @addtogroup USBH_OTG_DRIVER
* @{
*/
/** @defgroup USBH_CONF
* @brief usb otg low level driver configuration file
* @{
*/
/** @defgroup USBH_CONF_Exported_Defines
* @{
*/
#define USBH_MAX_NUM_ENDPOINTS 2
#define USBH_MAX_NUM_INTERFACES 2
#ifdef USE_USB_OTG_FS
#define USBH_MSC_MPS_SIZE 0x40
#else
#define USBH_MSC_MPS_SIZE 0x200
#endif
/**
* @}
*/
/** @defgroup USBH_CONF_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CONF_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CONF_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CONF_Exported_FunctionsPrototype
* @{
*/
/**
* @}
*/
#endif //__USBH_CONF__H__
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
@@ -1,195 +0,0 @@
/**
******************************************************************************
* @file usbh_hid_core.h
* @author MCD Application Team
* @version V2.0.0
* @date 22-July-2011
* @brief This file contains all the prototypes for the usbh_hid_core.c
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_HID_CORE_H
#define __USBH_HID_CORE_H
/* Includes ------------------------------------------------------------------*/
#include "usbh_core.h"
#include "usbh_stdreq.h"
#include "usb_bsp.h"
#include "usbh_ioreq.h"
#include "usbh_hcs.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_HID_CLASS
* @{
*/
/** @defgroup USBH_HID_CORE
* @brief This file is the Header file for USBH_HID_CORE.c
* @{
*/
/** @defgroup USBH_HID_CORE_Exported_Types
* @{
*/
/* States for HID State Machine */
typedef enum
{
HID_IDLE= 0,
HID_SEND_DATA,
HID_BUSY,
HID_GET_DATA,
HID_POLL,
HID_ERROR,
}
HID_State;
typedef enum
{
HID_REQ_IDLE = 0,
HID_REQ_GET_REPORT_DESC,
HID_REQ_GET_HID_DESC,
HID_REQ_SET_IDLE,
HID_REQ_SET_PROTOCOL,
HID_REQ_SET_REPORT,
}
HID_CtlState;
typedef struct HID_cb
{
void (*Init) (void);
void (*Decode) (uint8_t *data);
} HID_cb_TypeDef;
typedef struct _HID_Report
{
uint8_t ReportID;
uint8_t ReportType;
uint16_t UsagePage;
uint32_t Usage[2];
uint32_t NbrUsage;
uint32_t UsageMin;
uint32_t UsageMax;
int32_t LogMin;
int32_t LogMax;
int32_t PhyMin;
int32_t PhyMax;
int32_t UnitExp;
uint32_t Unit;
uint32_t ReportSize;
uint32_t ReportCnt;
uint32_t Flag;
uint32_t PhyUsage;
uint32_t AppUsage;
uint32_t LogUsage;
}
HID_Report_TypeDef;
/* Structure for HID process */
typedef struct _HID_Process
{
uint8_t buff[64];
uint8_t hc_num_in;
uint8_t hc_num_out;
HID_State state;
uint8_t HIDIntOutEp;
uint8_t HIDIntInEp;
HID_CtlState ctl_state;
uint16_t length;
uint8_t ep_addr;
uint16_t poll;
__IO uint16_t timer;
HID_cb_TypeDef *cb;
}
HID_Machine_TypeDef;
/**
* @}
*/
/** @defgroup USBH_HID_CORE_Exported_Defines
* @{
*/
#define USB_HID_REQ_GET_REPORT 0x01
#define USB_HID_GET_IDLE 0x02
#define USB_HID_GET_PROTOCOL 0x03
#define USB_HID_SET_REPORT 0x09
#define USB_HID_SET_IDLE 0x0A
#define USB_HID_SET_PROTOCOL 0x0B
/**
* @}
*/
/** @defgroup USBH_HID_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_HID_CORE_Exported_Variables
* @{
*/
extern USBH_Class_cb_TypeDef HID_cb;
/**
* @}
*/
/** @defgroup USBH_HID_CORE_Exported_FunctionsPrototype
* @{
*/
USBH_Status USBH_Set_Report (USB_OTG_CORE_HANDLE *pdev,
USBH_HOST *phost,
uint8_t reportType,
uint8_t reportId,
uint8_t reportLen,
uint8_t* reportBuff);
/**
* @}
*/
#endif /* __USBH_HID_CORE_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
@@ -1,122 +0,0 @@
/**
******************************************************************************
* @file usbh_hid_keybd.h
* @author MCD Application Team
* @version V2.0.0
* @date 22-July-2011
* @brief This file contains all the prototypes for the usbh_hid_keybd.c
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive -----------------------------------------------*/
#ifndef __USBH_HID_KEYBD_H
#define __USBH_HID_KEYBD_H
/* Includes ------------------------------------------------------------------*/
#include "usb_conf.h"
#include "usbh_hid_core.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_HID_CLASS
* @{
*/
/** @defgroup USBH_HID_KEYBD
* @brief This file is the Header file for USBH_HID_KEYBD.c
* @{
*/
/** @defgroup USBH_HID_KEYBD_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup USBH_HID_KEYBD_Exported_Defines
* @{
*/
//#define QWERTY_KEYBOARD
#define AZERTY_KEYBOARD
#define KBD_LEFT_CTRL 0x01
#define KBD_LEFT_SHIFT 0x02
#define KBD_LEFT_ALT 0x04
#define KBD_LEFT_GUI 0x08
#define KBD_RIGHT_CTRL 0x10
#define KBD_RIGHT_SHIFT 0x20
#define KBD_RIGHT_ALT 0x40
#define KBD_RIGHT_GUI 0x80
#define KBR_MAX_NBR_PRESSED 6
/**
* @}
*/
/** @defgroup USBH_HID_KEYBD_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_HID_KEYBD_Exported_Variables
* @{
*/
extern HID_cb_TypeDef HID_KEYBRD_cb;
/**
* @}
*/
/** @defgroup USBH_HID_KEYBD_Exported_FunctionsPrototype
* @{
*/
void USR_KEYBRD_Init (void);
void USR_KEYBRD_ProcessData (uint8_t pbuf);
/**
* @}
*/
#endif /* __USBH_HID_KEYBD_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
@@ -1,114 +0,0 @@
/**
******************************************************************************
* @file usbh_hid_mouse.h
* @author MCD Application Team
* @version V2.0.0
* @date 22-July-2011
* @brief This file contains all the prototypes for the usbh_hid_mouse.c
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_HID_MOUSE_H
#define __USBH_HID_MOUSE_H
/* Includes ------------------------------------------------------------------*/
#include "usbh_hid_core.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_HID_CLASS
* @{
*/
/** @defgroup USBH_HID_MOUSE
* @brief This file is the Header file for USBH_HID_MOUSE.c
* @{
*/
/** @defgroup USBH_HID_MOUSE_Exported_Types
* @{
*/
typedef struct _HID_MOUSE_Data
{
uint8_t x;
uint8_t y;
uint8_t z; /* Not Supported */
uint8_t button;
}
HID_MOUSE_Data_TypeDef;
/**
* @}
*/
/** @defgroup USBH_HID_MOUSE_Exported_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_HID_MOUSE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_HID_MOUSE_Exported_Variables
* @{
*/
extern HID_cb_TypeDef HID_MOUSE_cb;
extern HID_MOUSE_Data_TypeDef HID_MOUSE_Data;
/**
* @}
*/
/** @defgroup USBH_HID_MOUSE_Exported_FunctionsPrototype
* @{
*/
void USR_MOUSE_Init (void);
void USR_MOUSE_ProcessData (HID_MOUSE_Data_TypeDef *data);
/**
* @}
*/
#endif /* __USBH_HID_MOUSE_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
@@ -1,640 +0,0 @@
/**
******************************************************************************
* @file usbh_hid_core.c
* @author MCD Application Team
* @version V2.0.0
* @date 22-July-2011
* @brief This file is the HID Layer Handlers for USB Host HID class.
*
* @verbatim
*
* ===================================================================
* HID Class Description
* ===================================================================
* This module manages the MSC class V1.11 following the "Device Class Definition
* for Human Interface Devices (HID) Version 1.11 Jun 27, 2001".
* This driver implements the following aspects of the specification:
* - The Boot Interface Subclass
* - The Mouse and Keyboard protocols
*
* @endverbatim
*
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbh_hid_core.h"
#include "usbh_hid_mouse.h"
#include "usbh_hid_keybd.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_HID_CLASS
* @{
*/
/** @defgroup USBH_HID_CORE
* @brief This file includes HID Layer Handlers for USB Host HID class.
* @{
*/
/** @defgroup USBH_HID_CORE_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBH_HID_CORE_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_HID_CORE_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_HID_CORE_Private_Variables
* @{
*/
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
__ALIGN_BEGIN HID_Machine_TypeDef HID_Machine __ALIGN_END ;
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
__ALIGN_BEGIN HID_Report_TypeDef HID_Report __ALIGN_END ;
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
__ALIGN_BEGIN USB_Setup_TypeDef HID_Setup __ALIGN_END ;
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
__ALIGN_BEGIN USBH_HIDDesc_TypeDef HID_Desc __ALIGN_END ;
__IO uint8_t flag = 0;
/**
* @}
*/
/** @defgroup USBH_HID_CORE_Private_FunctionPrototypes
* @{
*/
static USBH_Status USBH_HID_InterfaceInit (USB_OTG_CORE_HANDLE *pdev ,
void *phost);
static void USBH_ParseHIDDesc (USBH_HIDDesc_TypeDef *desc, uint8_t *buf);
static void USBH_HID_InterfaceDeInit (USB_OTG_CORE_HANDLE *pdev ,
void *phost);
static USBH_Status USBH_HID_Handle(USB_OTG_CORE_HANDLE *pdev ,
void *phost);
static USBH_Status USBH_HID_ClassRequest(USB_OTG_CORE_HANDLE *pdev ,
void *phost);
static USBH_Status USBH_Get_HID_ReportDescriptor (USB_OTG_CORE_HANDLE *pdev,
USBH_HOST *phost,
uint16_t length);
static USBH_Status USBH_Get_HID_Descriptor (USB_OTG_CORE_HANDLE *pdev,\
USBH_HOST *phost,
uint16_t length);
static USBH_Status USBH_Set_Idle (USB_OTG_CORE_HANDLE *pdev,
USBH_HOST *phost,
uint8_t duration,
uint8_t reportId);
static USBH_Status USBH_Set_Protocol (USB_OTG_CORE_HANDLE *pdev,
USBH_HOST *phost,
uint8_t protocol);
USBH_Class_cb_TypeDef HID_cb =
{
USBH_HID_InterfaceInit,
USBH_HID_InterfaceDeInit,
USBH_HID_ClassRequest,
USBH_HID_Handle
};
/**
* @}
*/
/** @defgroup USBH_HID_CORE_Private_Functions
* @{
*/
/**
* @brief USBH_HID_InterfaceInit
* The function init the HID class.
* @param pdev: Selected device
* @param hdev: Selected device property
* @retval USBH_Status :Response for USB HID driver intialization
*/
static USBH_Status USBH_HID_InterfaceInit ( USB_OTG_CORE_HANDLE *pdev,
void *phost)
{
uint8_t maxEP;
USBH_HOST *pphost = phost;
uint8_t num =0;
USBH_Status status = USBH_BUSY ;
HID_Machine.state = HID_ERROR;
if(pphost->device_prop.Itf_Desc[0].bInterfaceSubClass == HID_BOOT_CODE)
{
/*Decode Bootclass Protocl: Mouse or Keyboard*/
if(pphost->device_prop.Itf_Desc[0].bInterfaceProtocol == HID_KEYBRD_BOOT_CODE)
{
HID_Machine.cb = &HID_KEYBRD_cb;
}
else if(pphost->device_prop.Itf_Desc[0].bInterfaceProtocol == HID_MOUSE_BOOT_CODE)
{
HID_Machine.cb = &HID_MOUSE_cb;
}
HID_Machine.state = HID_IDLE;
HID_Machine.ctl_state = HID_REQ_IDLE;
HID_Machine.ep_addr = pphost->device_prop.Ep_Desc[0][0].bEndpointAddress;
HID_Machine.length = pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize;
HID_Machine.poll = pphost->device_prop.Ep_Desc[0][0].bInterval ;
/* Check fo available number of endpoints */
/* Find the number of EPs in the Interface Descriptor */
/* Choose the lower number in order not to overrun the buffer allocated */
maxEP = ( (pphost->device_prop.Itf_Desc[0].bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) ?
pphost->device_prop.Itf_Desc[0].bNumEndpoints :
USBH_MAX_NUM_ENDPOINTS);
/* Decode endpoint IN and OUT address from interface descriptor */
for (num=0; num < maxEP; num++)
{
if(pphost->device_prop.Ep_Desc[0][num].bEndpointAddress & 0x80)
{
HID_Machine.HIDIntInEp = (pphost->device_prop.Ep_Desc[0][num].bEndpointAddress);
HID_Machine.hc_num_in =\
USBH_Alloc_Channel(pdev,
pphost->device_prop.Ep_Desc[0][num].bEndpointAddress);
/* Open channel for IN endpoint */
USBH_Open_Channel (pdev,
HID_Machine.hc_num_in,
pphost->device_prop.address,
pphost->device_prop.speed,
EP_TYPE_INTR,
HID_Machine.length);
}
else
{
HID_Machine.HIDIntOutEp = (pphost->device_prop.Ep_Desc[0][num].bEndpointAddress);
HID_Machine.hc_num_out =\
USBH_Alloc_Channel(pdev,
pphost->device_prop.Ep_Desc[0][num].bEndpointAddress);
/* Open channel for OUT endpoint */
USBH_Open_Channel (pdev,
HID_Machine.hc_num_out,
pphost->device_prop.address,
pphost->device_prop.speed,
EP_TYPE_INTR,
HID_Machine.length);
}
}
flag =0;
status = USBH_OK;
}
else
{
pphost->usr_cb->USBH_USR_DeviceNotSupported();
}
return status;
}
/**
* @brief USBH_HID_InterfaceDeInit
* The function DeInit the Host Channels used for the HID class.
* @param pdev: Selected device
* @param hdev: Selected device property
* @retval None
*/
void USBH_HID_InterfaceDeInit ( USB_OTG_CORE_HANDLE *pdev,
void *phost)
{
//USBH_HOST *pphost = phost;
if(HID_Machine.hc_num_in != 0x00)
{
USB_OTG_HC_Halt(pdev, HID_Machine.hc_num_in);
USBH_Free_Channel (pdev, HID_Machine.hc_num_in);
HID_Machine.hc_num_in = 0; /* Reset the Channel as Free */
}
if(HID_Machine.hc_num_out != 0x00)
{
USB_OTG_HC_Halt(pdev, HID_Machine.hc_num_out);
USBH_Free_Channel (pdev, HID_Machine.hc_num_out);
HID_Machine.hc_num_out = 0; /* Reset the Channel as Free */
}
flag = 0;
}
/**
* @brief USBH_HID_ClassRequest
* The function is responsible for handling HID Class requests
* for HID class.
* @param pdev: Selected device
* @param hdev: Selected device property
* @retval USBH_Status :Response for USB Set Protocol request
*/
static USBH_Status USBH_HID_ClassRequest(USB_OTG_CORE_HANDLE *pdev ,
void *phost)
{
USBH_HOST *pphost = phost;
USBH_Status status = USBH_BUSY;
USBH_Status classReqStatus = USBH_BUSY;
/* Switch HID state machine */
switch (HID_Machine.ctl_state)
{
case HID_IDLE:
case HID_REQ_GET_HID_DESC:
/* Get HID Desc */
if (USBH_Get_HID_Descriptor (pdev, pphost, USB_HID_DESC_SIZE)== USBH_OK)
{
USBH_ParseHIDDesc(&HID_Desc, pdev->host.Rx_Buffer);
HID_Machine.ctl_state = HID_REQ_GET_REPORT_DESC;
}
break;
case HID_REQ_GET_REPORT_DESC:
/* Get Report Desc */
if (USBH_Get_HID_ReportDescriptor(pdev , pphost, HID_Desc.wItemLength) == USBH_OK)
{
HID_Machine.ctl_state = HID_REQ_SET_IDLE;
}
break;
case HID_REQ_SET_IDLE:
classReqStatus = USBH_Set_Idle (pdev, pphost, 0, 0);
/* set Idle */
if (classReqStatus == USBH_OK)
{
HID_Machine.ctl_state = HID_REQ_SET_PROTOCOL;
}
else if(classReqStatus == USBH_NOT_SUPPORTED)
{
HID_Machine.ctl_state = HID_REQ_SET_PROTOCOL;
}
break;
case HID_REQ_SET_PROTOCOL:
/* set protocol */
if (USBH_Set_Protocol (pdev ,pphost, 0) == USBH_OK)
{
HID_Machine.ctl_state = HID_REQ_IDLE;
/* all requests performed*/
status = USBH_OK;
}
break;
default:
break;
}
return status;
}
/**
* @brief USBH_HID_Handle
* The function is for managing state machine for HID data transfers
* @param pdev: Selected device
* @param hdev: Selected device property
* @retval USBH_Status
*/
static USBH_Status USBH_HID_Handle(USB_OTG_CORE_HANDLE *pdev ,
void *phost)
{
USBH_HOST *pphost = phost;
USBH_Status status = USBH_OK;
switch (HID_Machine.state)
{
case HID_IDLE:
HID_Machine.cb->Init();
HID_Machine.state = HID_GET_DATA;
break;
case HID_GET_DATA:
/* Sync with start of Even Frame */
while(USB_OTG_IsEvenFrame(pdev) == FALSE);
USBH_InterruptReceiveData(pdev,
HID_Machine.buff,
HID_Machine.length,
HID_Machine.hc_num_in);
flag = 1;
HID_Machine.state = HID_POLL;
HID_Machine.timer = HCD_GetCurrentFrame(pdev);
break;
case HID_POLL:
if(( HCD_GetCurrentFrame(pdev) - HID_Machine.timer) >= HID_Machine.poll)
{
HID_Machine.state = HID_GET_DATA;
}
else if(HCD_GetURB_State(pdev , HID_Machine.hc_num_in) == URB_DONE)
{
if(flag == 1) /* handle data once */
{
flag = 0;
HID_Machine.cb->Decode(HID_Machine.buff);
}
}
else if(HCD_GetURB_State(pdev, HID_Machine.hc_num_in) == URB_STALL) /* IN Endpoint Stalled */
{
/* Issue Clear Feature on interrupt IN endpoint */
if( (USBH_ClrFeature(pdev,
pphost,
HID_Machine.ep_addr,
HID_Machine.hc_num_in)) == USBH_OK)
{
/* Change state to issue next IN token */
HID_Machine.state = HID_GET_DATA;
}
}
break;
default:
break;
}
return status;
}
/**
* @brief USBH_Get_HID_ReportDescriptor
* Issue report Descriptor command to the device. Once the response
* received, parse the report descriptor and update the status.
* @param pdev : Selected device
* @param Length : HID Report Descriptor Length
* @retval USBH_Status : Response for USB HID Get Report Descriptor Request
*/
static USBH_Status USBH_Get_HID_ReportDescriptor (USB_OTG_CORE_HANDLE *pdev,
USBH_HOST *phost,
uint16_t length)
{
USBH_Status status;
status = USBH_GetDescriptor(pdev,
phost,
USB_REQ_RECIPIENT_INTERFACE
| USB_REQ_TYPE_STANDARD,
USB_DESC_HID_REPORT,
pdev->host.Rx_Buffer,
length);
/* HID report descriptor is available in pdev->host.Rx_Buffer.
In case of USB Boot Mode devices for In report handling ,
HID report descriptor parsing is not required.
In case, for supporting Non-Boot Protocol devices and output reports,
user may parse the report descriptor*/
return status;
}
/**
* @brief USBH_Get_HID_Descriptor
* Issue HID Descriptor command to the device. Once the response
* received, parse the report descriptor and update the status.
* @param pdev : Selected device
* @param Length : HID Descriptor Length
* @retval USBH_Status : Response for USB HID Get Report Descriptor Request
*/
static USBH_Status USBH_Get_HID_Descriptor (USB_OTG_CORE_HANDLE *pdev,
USBH_HOST *phost,
uint16_t length)
{
USBH_Status status;
status = USBH_GetDescriptor(pdev,
phost,
USB_REQ_RECIPIENT_INTERFACE
| USB_REQ_TYPE_STANDARD,
USB_DESC_HID,
pdev->host.Rx_Buffer,
length);
return status;
}
/**
* @brief USBH_Set_Idle
* Set Idle State.
* @param pdev: Selected device
* @param duration: Duration for HID Idle request
* @param reportID : Targetted report ID for Set Idle request
* @retval USBH_Status : Response for USB Set Idle request
*/
static USBH_Status USBH_Set_Idle (USB_OTG_CORE_HANDLE *pdev,
USBH_HOST *phost,
uint8_t duration,
uint8_t reportId)
{
phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\
USB_REQ_TYPE_CLASS;
phost->Control.setup.b.bRequest = USB_HID_SET_IDLE;
phost->Control.setup.b.wValue.w = (duration << 8 ) | reportId;
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = 0;
return USBH_CtlReq(pdev, phost, 0 , 0 );
}
/**
* @brief USBH_Set_Report
* Issues Set Report
* @param pdev: Selected device
* @param reportType : Report type to be sent
* @param reportID : Targetted report ID for Set Report request
* @param reportLen : Length of data report to be send
* @param reportBuff : Report Buffer
* @retval USBH_Status : Response for USB Set Idle request
*/
USBH_Status USBH_Set_Report (USB_OTG_CORE_HANDLE *pdev,
USBH_HOST *phost,
uint8_t reportType,
uint8_t reportId,
uint8_t reportLen,
uint8_t* reportBuff)
{
phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\
USB_REQ_TYPE_CLASS;
phost->Control.setup.b.bRequest = USB_HID_SET_REPORT;
phost->Control.setup.b.wValue.w = (reportType << 8 ) | reportId;
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = reportLen;
return USBH_CtlReq(pdev, phost, reportBuff , reportLen );
}
/**
* @brief USBH_Set_Protocol
* Set protocol State.
* @param pdev: Selected device
* @param protocol : Set Protocol for HID : boot/report protocol
* @retval USBH_Status : Response for USB Set Protocol request
*/
static USBH_Status USBH_Set_Protocol(USB_OTG_CORE_HANDLE *pdev,
USBH_HOST *phost,
uint8_t protocol)
{
phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE |\
USB_REQ_TYPE_CLASS;
phost->Control.setup.b.bRequest = USB_HID_SET_PROTOCOL;
if(protocol != 0)
{
/* Boot Protocol */
phost->Control.setup.b.wValue.w = 0;
}
else
{
/*Report Protocol*/
phost->Control.setup.b.wValue.w = 1;
}
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = 0;
return USBH_CtlReq(pdev, phost, 0 , 0 );
}
/**
* @brief USBH_ParseHIDDesc
* This function Parse the HID descriptor
* @param buf: Buffer where the source descriptor is available
* @retval None
*/
static void USBH_ParseHIDDesc (USBH_HIDDesc_TypeDef *desc, uint8_t *buf)
{
desc->bLength = *(uint8_t *) (buf + 0);
desc->bDescriptorType = *(uint8_t *) (buf + 1);
desc->bcdHID = LE16 (buf + 2);
desc->bCountryCode = *(uint8_t *) (buf + 4);
desc->bNumDescriptors = *(uint8_t *) (buf + 5);
desc->bReportDescriptorType = *(uint8_t *) (buf + 6);
desc->wItemLength = LE16 (buf + 7);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
@@ -1,338 +0,0 @@
/**
******************************************************************************
* @file usbh_hid_keybd.c
* @author MCD Application Team
* @version V2.0.0
* @date 22-July-2011
* @brief This file is the application layer for USB Host HID Keyboard handling
* QWERTY and AZERTY Keyboard are supported as per the selection in
* usbh_hid_keybd.h
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbh_hid_keybd.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_HID_CLASS
* @{
*/
/** @defgroup USBH_HID_KEYBD
* @brief This file includes HID Layer Handlers for USB Host HID class.
* @{
*/
/** @defgroup USBH_HID_KEYBD_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBH_HID_KEYBD_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_HID_KEYBD_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_HID_KEYBD_Private_FunctionPrototypes
* @{
*/
static void KEYBRD_Init (void);
static void KEYBRD_Decode(uint8_t *data);
/**
* @}
*/
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
#if defined (__CC_ARM) /*!< ARM Compiler */
__align(4)
#elif defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#elif defined (__GNUC__) /*!< GNU Compiler */
#pragma pack(4)
#elif defined (__TASKING__) /*!< TASKING Compiler */
__align(4)
#endif /* __CC_ARM */
#endif
/** @defgroup USBH_HID_KEYBD_Private_Variables
* @{
*/
HID_cb_TypeDef HID_KEYBRD_cb=
{
KEYBRD_Init,
KEYBRD_Decode
};
/*
*******************************************************************************
* LOCAL CONSTANTS
*******************************************************************************
*/
static const uint8_t HID_KEYBRD_Codes[] = {
0, 0, 0, 0, 31, 50, 48, 33,
19, 34, 35, 36, 24, 37, 38, 39, /* 0x00 - 0x0F */
52, 51, 25, 26, 17, 20, 32, 21,
23, 49, 18, 47, 22, 46, 2, 3, /* 0x10 - 0x1F */
4, 5, 6, 7, 8, 9, 10, 11,
43, 110, 15, 16, 61, 12, 13, 27, /* 0x20 - 0x2F */
28, 29, 42, 40, 41, 1, 53, 54,
55, 30, 112, 113, 114, 115, 116, 117, /* 0x30 - 0x3F */
118, 119, 120, 121, 122, 123, 124, 125,
126, 75, 80, 85, 76, 81, 86, 89, /* 0x40 - 0x4F */
79, 84, 83, 90, 95, 100, 105, 106,
108, 93, 98, 103, 92, 97, 102, 91, /* 0x50 - 0x5F */
96, 101, 99, 104, 45, 129, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6F */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7F */
0, 0, 0, 0, 0, 107, 0, 56,
0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8F */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9F */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xAF */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 - 0xBF */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xCF */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xDF */
58, 44, 60, 127, 64, 57, 62, 128 /* 0xE0 - 0xE7 */
};
#ifdef QWERTY_KEYBOARD
static const int8_t HID_KEYBRD_Key[] = {
'\0', '`', '1', '2', '3', '4', '5', '6',
'7', '8', '9', '0', '-', '=', '\0', '\r',
'\t', 'q', 'w', 'e', 'r', 't', 'y', 'u',
'i', 'o', 'p', '[', ']', '\\',
'\0', 'a', 's', 'd', 'f', 'g', 'h', 'j',
'k', 'l', ';', '\'', '\0', '\n',
'\0', '\0', 'z', 'x', 'c', 'v', 'b', 'n',
'm', ',', '.', '/', '\0', '\0',
'\0', '\0', '\0', ' ', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '7', '4', '1',
'\0', '/', '8', '5', '2',
'0', '*', '9', '6', '3',
'.', '-', '+', '\0', '\n', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0'
};
static const int8_t HID_KEYBRD_ShiftKey[] = {
'\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
'_', '+', '\0', '\0', '\0', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U',
'I', 'O', 'P', '{', '}', '|', '\0', 'A', 'S', 'D', 'F', 'G',
'H', 'J', 'K', 'L', ':', '"', '\0', '\n', '\0', '\0', 'Z', 'X',
'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
};
#else
static const int8_t HID_KEYBRD_Key[] = {
'\0', '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
'-', '=', '\0', '\r', '\t', 'a', 'z', 'e', 'r', 't', 'y', 'u',
'i', 'o', 'p', '[', ']', '\\', '\0', 'q', 's', 'd', 'f', 'g',
'h', 'j', 'k', 'l', 'm', '\0', '\0', '\n', '\0', '\0', 'w', 'x',
'c', 'v', 'b', 'n', ',', ';', ':', '!', '\0', '\0', '\0', '\0',
'\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '4', '1','\0', '/',
'8', '5', '2', '0', '*', '9', '6', '3', '.', '-', '+', '\0',
'\n', '\0', '\0', '\0', '\0', '\0', '\0','\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
};
static const int8_t HID_KEYBRD_ShiftKey[] = {
'\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_',
'+', '\0', '\0', '\0', 'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', 'O',
'P', '{', '}', '*', '\0', 'Q', 'S', 'D', 'F', 'G', 'H', 'J', 'K',
'L', 'M', '%', '\0', '\n', '\0', '\0', 'W', 'X', 'C', 'V', 'B', 'N',
'?', '.', '/', '\0', '\0', '\0','\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
};
#endif
/**
* @}
*/
/** @defgroup USBH_HID_KEYBD_Private_Functions
* @{
*/
/**
* @brief KEYBRD_Init.
* Initialize the keyboard function.
* @param None
* @retval None
*/
static void KEYBRD_Init (void)
{
/* Call User Init*/
USR_KEYBRD_Init();
}
/**
* @brief KEYBRD_ProcessData.
* The function is to decode the pressed keys.
* @param pbuf : Pointer to the HID IN report data buffer
* @retval None
*/
static void KEYBRD_Decode(uint8_t *pbuf)
{
static uint8_t shift;
static uint8_t keys[KBR_MAX_NBR_PRESSED];
static uint8_t keys_new[KBR_MAX_NBR_PRESSED];
static uint8_t keys_last[KBR_MAX_NBR_PRESSED];
static uint8_t key_newest;
static uint8_t nbr_keys;
static uint8_t nbr_keys_new;
static uint8_t nbr_keys_last;
uint8_t ix;
uint8_t jx;
uint8_t error;
uint8_t output;
nbr_keys = 0;
nbr_keys_new = 0;
nbr_keys_last = 0;
key_newest = 0x00;
/* Check if Shift key is pressed */
if ((pbuf[0] == KBD_LEFT_SHIFT) || (pbuf[0] == KBD_RIGHT_SHIFT)) {
shift = TRUE;
} else {
shift = FALSE;
}
error = FALSE;
/* Check for the value of pressed key */
for (ix = 2; ix < 2 + KBR_MAX_NBR_PRESSED; ix++) {
if ((pbuf[ix] == 0x01) ||
(pbuf[ix] == 0x02) ||
(pbuf[ix] == 0x03)) {
error = TRUE;
}
}
if (error == TRUE) {
return;
}
nbr_keys = 0;
nbr_keys_new = 0;
for (ix = 2; ix < 2 + KBR_MAX_NBR_PRESSED; ix++) {
if (pbuf[ix] != 0) {
keys[nbr_keys] = pbuf[ix];
nbr_keys++;
for (jx = 0; jx < nbr_keys_last; jx++) {
if (pbuf[ix] == keys_last[jx]) {
break;
}
}
if (jx == nbr_keys_last) {
keys_new[nbr_keys_new] = pbuf[ix];
nbr_keys_new++;
}
}
}
if (nbr_keys_new == 1) {
key_newest = keys_new[0];
if (shift == TRUE) {
output = HID_KEYBRD_ShiftKey[HID_KEYBRD_Codes[key_newest]];
} else {
output = HID_KEYBRD_Key[HID_KEYBRD_Codes[key_newest]];
}
/* call user process handle */
USR_KEYBRD_ProcessData(output);
} else {
key_newest = 0x00;
}
nbr_keys_last = nbr_keys;
for (ix = 0; ix < KBR_MAX_NBR_PRESSED; ix++) {
keys_last[ix] = keys[ix];
}
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
@@ -1,155 +0,0 @@
/**
******************************************************************************
* @file usbh_hid_mouse.c
* @author MCD Application Team
* @version V2.0.0
* @date 22-July-2011
* @brief This file is the application layer for USB Host HID Mouse Handling.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbh_hid_mouse.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_HID_CLASS
* @{
*/
/** @defgroup USBH_HID_MOUSE
* @brief This file includes HID Layer Handlers for USB Host HID class.
* @{
*/
/** @defgroup USBH_HID_MOUSE_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBH_HID_MOUSE_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_HID_MOUSE_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_HID_MOUSE_Private_FunctionPrototypes
* @{
*/
static void MOUSE_Init (void);
static void MOUSE_Decode(uint8_t *data);
/**
* @}
*/
/** @defgroup USBH_HID_MOUSE_Private_Variables
* @{
*/
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
#if defined (__CC_ARM) /*!< ARM Compiler */
__align(4)
#elif defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#elif defined (__GNUC__) /*!< GNU Compiler */
#pragma pack(4)
#elif defined (__TASKING__) /*!< TASKING Compiler */
__align(4)
#endif /* __CC_ARM */
#endif
HID_MOUSE_Data_TypeDef HID_MOUSE_Data;
HID_cb_TypeDef HID_MOUSE_cb =
{
MOUSE_Init,
MOUSE_Decode,
};
/**
* @}
*/
/** @defgroup USBH_HID_MOUSE_Private_Functions
* @{
*/
/**
* @brief MOUSE_Init
* Init Mouse State.
* @param None
* @retval None
*/
static void MOUSE_Init ( void)
{
/* Call User Init*/
USR_MOUSE_Init();
}
/**
* @brief MOUSE_Decode
* Decode Mouse data
* @param data : Pointer to Mouse HID data buffer
* @retval None
*/
static void MOUSE_Decode(uint8_t *data)
{
HID_MOUSE_Data.button = data[0];
HID_MOUSE_Data.x = data[1];
HID_MOUSE_Data.y = data[2];
USR_MOUSE_ProcessData(&HID_MOUSE_Data);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
@@ -1,221 +0,0 @@
/**
******************************************************************************
* @file usbh_msc_bot.h
* @author MCD Application Team
* @version V2.0.0
* @date 22-July-2011
* @brief Header file for usbh_msc_bot.c
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_MSC_BOT_H__
#define __USBH_MSC_BOT_H__
/* Includes ------------------------------------------------------------------*/
#include "usbh_stdreq.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_MSC_CLASS
* @{
*/
/** @defgroup USBH_MSC_BOT
* @brief This file is the Header file for usbh_msc_core.c
* @{
*/
/** @defgroup USBH_MSC_BOT_Exported_Types
* @{
*/
typedef union _USBH_CBW_Block
{
struct __CBW
{
uint32_t CBWSignature;
uint32_t CBWTag;
uint32_t CBWTransferLength;
uint8_t CBWFlags;
uint8_t CBWLUN;
uint8_t CBWLength;
uint8_t CBWCB[16];
}field;
uint8_t CBWArray[31];
}HostCBWPkt_TypeDef;
typedef enum
{
USBH_MSC_BOT_INIT_STATE = 0,
USBH_MSC_BOT_RESET,
USBH_MSC_GET_MAX_LUN,
USBH_MSC_TEST_UNIT_READY,
USBH_MSC_READ_CAPACITY10,
USBH_MSC_MODE_SENSE6,
USBH_MSC_REQUEST_SENSE,
USBH_MSC_BOT_USB_TRANSFERS,
USBH_MSC_DEFAULT_APPLI_STATE,
USBH_MSC_CTRL_ERROR_STATE,
USBH_MSC_UNRECOVERED_STATE
}
MSCState;
typedef struct _BOTXfer
{
uint8_t MSCState;
uint8_t MSCStateBkp;
uint8_t MSCStateCurrent;
uint8_t CmdStateMachine;
uint8_t BOTState;
uint8_t BOTStateBkp;
uint8_t* pRxTxBuff;
uint16_t DataLength;
uint8_t BOTXferErrorCount;
uint8_t BOTXferStatus;
} USBH_BOTXfer_TypeDef;
typedef union _USBH_CSW_Block
{
struct __CSW
{
uint32_t CSWSignature;
uint32_t CSWTag;
uint32_t CSWDataResidue;
uint8_t CSWStatus;
}field;
uint8_t CSWArray[13];
}HostCSWPkt_TypeDef;
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Exported_Defines
* @{
*/
#define USBH_MSC_SEND_CBW 1
#define USBH_MSC_SENT_CBW 2
#define USBH_MSC_BOT_DATAIN_STATE 3
#define USBH_MSC_BOT_DATAOUT_STATE 4
#define USBH_MSC_RECEIVE_CSW_STATE 5
#define USBH_MSC_DECODE_CSW 6
#define USBH_MSC_BOT_ERROR_IN 7
#define USBH_MSC_BOT_ERROR_OUT 8
#define USBH_MSC_BOT_CBW_SIGNATURE 0x43425355
#define USBH_MSC_BOT_CBW_TAG 0x20304050
#define USBH_MSC_BOT_CSW_SIGNATURE 0x53425355
#define USBH_MSC_CSW_DATA_LENGTH 0x000D
#define USBH_MSC_BOT_CBW_PACKET_LENGTH 31
#define USBH_MSC_CSW_LENGTH 13
#define USBH_MSC_CSW_MAX_LENGTH 63
/* CSW Status Definitions */
#define USBH_MSC_CSW_CMD_PASSED 0x00
#define USBH_MSC_CSW_CMD_FAILED 0x01
#define USBH_MSC_CSW_PHASE_ERROR 0x02
#define USBH_MSC_SEND_CSW_DISABLE 0
#define USBH_MSC_SEND_CSW_ENABLE 1
#define USBH_MSC_DIR_IN 0
#define USBH_MSC_DIR_OUT 1
#define USBH_MSC_BOTH_DIR 2
//#define USBH_MSC_PAGE_LENGTH 0x40
#define USBH_MSC_PAGE_LENGTH 512
#define CBW_CB_LENGTH 16
#define CBW_LENGTH 10
#define CBW_LENGTH_TEST_UNIT_READY 6
#define USB_REQ_BOT_RESET 0xFF
#define USB_REQ_GET_MAX_LUN 0xFE
#define MAX_BULK_STALL_COUNT_LIMIT 0x04 /* If STALL is seen on Bulk
Endpoint continously, this means
that device and Host has phase error
Hence a Reset is needed */
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Exported_Variables
* @{
*/
extern USBH_BOTXfer_TypeDef USBH_MSC_BOTXferParam;
extern HostCBWPkt_TypeDef USBH_MSC_CBWData;
extern HostCSWPkt_TypeDef USBH_MSC_CSWData;
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Exported_FunctionsPrototype
* @{
*/
void USBH_MSC_HandleBOTXfer(USB_OTG_CORE_HANDLE *pdev,
USBH_HOST *phost);
uint8_t USBH_MSC_DecodeCSW(USB_OTG_CORE_HANDLE *pdev,
USBH_HOST *phost);
void USBH_MSC_Init(USB_OTG_CORE_HANDLE *pdev);
USBH_Status USBH_MSC_BOT_Abort(USB_OTG_CORE_HANDLE *pdev,
USBH_HOST *phost,
uint8_t direction);
/**
* @}
*/
#endif //__USBH_MSC_BOT_H__
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
@@ -1,141 +0,0 @@
/**
******************************************************************************
* @file usbh_msc_core.h
* @author MCD Application Team
* @version V2.0.0
* @date 22-July-2011
* @brief This file contains all the prototypes for the usbh_msc_core.c
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_MSC_CORE_H
#define __USBH_MSC_CORE_H
/* Includes ------------------------------------------------------------------*/
#include "usbh_core.h"
#include "usbh_stdreq.h"
#include "usb_bsp.h"
#include "usbh_ioreq.h"
#include "usbh_hcs.h"
#include "usbh_msc_core.h"
#include "usbh_msc_scsi.h"
#include "usbh_msc_bot.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_MSC_CLASS
* @{
*/
/** @defgroup USBH_MSC_CORE
* @brief This file is the Header file for usbh_msc_core.c
* @{
*/
/** @defgroup USBH_MSC_CORE_Exported_Types
* @{
*/
/* Structure for MSC process */
typedef struct _MSC_Process
{
uint8_t hc_num_in;
uint8_t hc_num_out;
uint8_t MSBulkOutEp;
uint8_t MSBulkInEp;
uint16_t MSBulkInEpSize;
uint16_t MSBulkOutEpSize;
uint8_t buff[USBH_MSC_MPS_SIZE];
uint8_t maxLun;
}
MSC_Machine_TypeDef;
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Exported_Defines
* @{
*/
#define USB_REQ_BOT_RESET 0xFF
#define USB_REQ_GET_MAX_LUN 0xFE
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Exported_Variables
* @{
*/
extern USBH_Class_cb_TypeDef USBH_MSC_cb;
extern MSC_Machine_TypeDef MSC_Machine;
extern uint8_t MSCErrorCount;
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Exported_FunctionsPrototype
* @{
*/
/**
* @}
*/
#endif /* __USBH_MSC_CORE_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
@@ -1,163 +0,0 @@
/**
******************************************************************************
* @file usbh_msc_scsi.h
* @author MCD Application Team
* @version V2.0.0
* @date 22-July-2011
* @brief Header file for usbh_msc_scsi.c
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_MSC_SCSI_H__
#define __USBH_MSC_SCSI_H__
/* Includes ------------------------------------------------------------------*/
#include "usbh_stdreq.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_MSC_CLASS
* @{
*/
/** @defgroup USBH_MSC_SCSI
* @brief This file is the Header file for usbh_msc_scsi.c
* @{
*/
/** @defgroup USBH_MSC_SCSI_Exported_Types
* @{
*/
typedef enum {
USBH_MSC_OK = 0,
USBH_MSC_FAIL = 1,
USBH_MSC_PHASE_ERROR = 2,
USBH_MSC_BUSY = 3
}USBH_MSC_Status_TypeDef;
typedef enum {
CMD_UNINITIALIZED_STATE =0,
CMD_SEND_STATE,
CMD_WAIT_STATUS
} CMD_STATES_TypeDef;
typedef struct __MassStorageParameter
{
uint32_t MSCapacity;
uint32_t MSSenseKey;
uint16_t MSPageLength;
uint8_t MSBulkOutEp;
uint8_t MSBulkInEp;
uint8_t MSWriteProtect;
} MassStorageParameter_TypeDef;
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Exported_Defines
* @{
*/
#define OPCODE_TEST_UNIT_READY 0X00
#define OPCODE_READ_CAPACITY10 0x25
#define OPCODE_MODE_SENSE6 0x1A
#define OPCODE_READ10 0x28
#define OPCODE_WRITE10 0x2A
#define OPCODE_REQUEST_SENSE 0x03
#define DESC_REQUEST_SENSE 0X00
#define ALLOCATION_LENGTH_REQUEST_SENSE 63
#define XFER_LEN_READ_CAPACITY10 8
#define XFER_LEN_MODE_SENSE6 63
#define MASK_MODE_SENSE_WRITE_PROTECT 0x80
#define MODE_SENSE_PAGE_CONTROL_FIELD 0x00
#define MODE_SENSE_PAGE_CODE 0x3F
#define DISK_WRITE_PROTECTED 0x01
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup _Exported_Variables
* @{
*/
extern MassStorageParameter_TypeDef USBH_MSC_Param;
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Exported_FunctionsPrototype
* @{
*/
uint8_t USBH_MSC_TestUnitReady(USB_OTG_CORE_HANDLE *pdev);
uint8_t USBH_MSC_ReadCapacity10(USB_OTG_CORE_HANDLE *pdev);
uint8_t USBH_MSC_ModeSense6(USB_OTG_CORE_HANDLE *pdev);
uint8_t USBH_MSC_RequestSense(USB_OTG_CORE_HANDLE *pdev);
uint8_t USBH_MSC_Write10(USB_OTG_CORE_HANDLE *pdev,
uint8_t *,
uint32_t ,
uint32_t );
uint8_t USBH_MSC_Read10(USB_OTG_CORE_HANDLE *pdev,
uint8_t *,
uint32_t ,
uint32_t );
void USBH_MSC_StateMachine(USB_OTG_CORE_HANDLE *pdev);
/**
* @}
*/
#endif //__USBH_MSC_SCSI_H__
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
@@ -1,613 +0,0 @@
/**
******************************************************************************
* @file usbh_msc_bot.c
* @author MCD Application Team
* @version V2.0.0
* @date 22-July-2011
* @brief This file includes the mass storage related functions
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbh_msc_core.h"
#include "usbh_msc_scsi.h"
#include "usbh_msc_bot.h"
#include "usbh_ioreq.h"
#include "usbh_def.h"
#include "usb_hcd_int.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_MSC_CLASS
* @{
*/
/** @defgroup USBH_MSC_BOT
* @brief This file includes the mass storage related functions
* @{
*/
/** @defgroup USBH_MSC_BOT_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Private_Variables
* @{
*/
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
__ALIGN_BEGIN HostCBWPkt_TypeDef USBH_MSC_CBWData __ALIGN_END ;
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
__ALIGN_BEGIN HostCSWPkt_TypeDef USBH_MSC_CSWData __ALIGN_END ;
static uint32_t BOTStallErrorCount; /* Keeps count of STALL Error Cases*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Exported_Variables
* @{
*/
USBH_BOTXfer_TypeDef USBH_MSC_BOTXferParam;
/**
* @}
*/
/** @defgroup USBH_MSC_BOT_Private_Functions
* @{
*/
/**
* @brief USBH_MSC_Init
* Initializes the mass storage parameters
* @param None
* @retval None
*/
void USBH_MSC_Init(USB_OTG_CORE_HANDLE *pdev )
{
if(HCD_IsDeviceConnected(pdev))
{
USBH_MSC_CBWData.field.CBWSignature = USBH_MSC_BOT_CBW_SIGNATURE;
USBH_MSC_CBWData.field.CBWTag = USBH_MSC_BOT_CBW_TAG;
USBH_MSC_CBWData.field.CBWLUN = 0; /*Only one LUN is supported*/
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
}
BOTStallErrorCount = 0;
MSCErrorCount = 0;
}
/**
* @brief USBH_MSC_HandleBOTXfer
* This function manages the different states of BOT transfer and
* updates the status to upper layer.
* @param None
* @retval None
*
*/
void USBH_MSC_HandleBOTXfer (USB_OTG_CORE_HANDLE *pdev ,USBH_HOST *phost)
{
uint8_t xferDirection, index;
static uint32_t remainingDataLength;
static uint8_t *datapointer;
static uint8_t error_direction;
USBH_Status status;
URB_STATE URB_Status = URB_IDLE;
if(HCD_IsDeviceConnected(pdev))
{
switch (USBH_MSC_BOTXferParam.BOTState)
{
case USBH_MSC_SEND_CBW:
/* send CBW */
USBH_BulkSendData (pdev,
&USBH_MSC_CBWData.CBWArray[0],
USBH_MSC_BOT_CBW_PACKET_LENGTH ,
MSC_Machine.hc_num_out);
USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_SEND_CBW;
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SENT_CBW;
break;
case USBH_MSC_SENT_CBW:
URB_Status = HCD_GetURB_State(pdev , MSC_Machine.hc_num_out);
if(URB_Status == URB_DONE)
{
BOTStallErrorCount = 0;
USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_SENT_CBW;
/* If the CBW Pkt is sent successful, then change the state */
xferDirection = (USBH_MSC_CBWData.field.CBWFlags & USB_REQ_DIR_MASK);
if ( USBH_MSC_CBWData.field.CBWTransferLength != 0 )
{
remainingDataLength = USBH_MSC_CBWData.field.CBWTransferLength ;
datapointer = USBH_MSC_BOTXferParam.pRxTxBuff;
/* If there is Data Transfer Stage */
if (xferDirection == USB_D2H)
{
/* Data Direction is IN */
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_DATAIN_STATE;
}
else
{
/* Data Direction is OUT */
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_DATAOUT_STATE;
}
}
else
{/* If there is NO Data Transfer Stage */
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_RECEIVE_CSW_STATE;
}
}
else if(URB_Status == URB_NOTREADY)
{
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp;
}
else if(URB_Status == URB_STALL)
{
error_direction = USBH_MSC_DIR_OUT;
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_OUT;
}
break;
case USBH_MSC_BOT_DATAIN_STATE:
URB_Status = HCD_GetURB_State(pdev , MSC_Machine.hc_num_in);
/* BOT DATA IN stage */
if((URB_Status == URB_DONE) ||(USBH_MSC_BOTXferParam.BOTStateBkp != USBH_MSC_BOT_DATAIN_STATE))
{
BOTStallErrorCount = 0;
USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_BOT_DATAIN_STATE;
if(remainingDataLength > USBH_MSC_MPS_SIZE)
{
USBH_BulkReceiveData (pdev,
datapointer,
USBH_MSC_MPS_SIZE ,
MSC_Machine.hc_num_in);
remainingDataLength -= USBH_MSC_MPS_SIZE;
datapointer = datapointer + USBH_MSC_MPS_SIZE;
}
else if ( remainingDataLength == 0)
{
/* If value was 0, and successful transfer, then change the state */
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_RECEIVE_CSW_STATE;
}
else
{
USBH_BulkReceiveData (pdev,
datapointer,
remainingDataLength ,
MSC_Machine.hc_num_in);
remainingDataLength = 0; /* Reset this value and keep in same state */
}
}
else if(URB_Status == URB_STALL)
{
/* This is Data Stage STALL Condition */
error_direction = USBH_MSC_DIR_IN;
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_IN;
/* Refer to USB Mass-Storage Class : BOT (www.usb.org)
6.7.2 Host expects to receive data from the device
3. On a STALL condition receiving data, then:
The host shall accept the data received.
The host shall clear the Bulk-In pipe.
4. The host shall attempt to receive a CSW.
USBH_MSC_BOTXferParam.BOTStateBkp is used to switch to the Original
state after the ClearFeature Command is issued.
*/
USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE;
}
break;
case USBH_MSC_BOT_DATAOUT_STATE:
/* BOT DATA OUT stage */
URB_Status = HCD_GetURB_State(pdev , MSC_Machine.hc_num_out);
if(URB_Status == URB_DONE)
{
BOTStallErrorCount = 0;
USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_BOT_DATAOUT_STATE;
if(remainingDataLength > USBH_MSC_MPS_SIZE)
{
USBH_BulkSendData (pdev,
datapointer,
USBH_MSC_MPS_SIZE ,
MSC_Machine.hc_num_out);
datapointer = datapointer + USBH_MSC_MPS_SIZE;
remainingDataLength = remainingDataLength - USBH_MSC_MPS_SIZE;
}
else if ( remainingDataLength == 0)
{
/* If value was 0, and successful transfer, then change the state */
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_RECEIVE_CSW_STATE;
}
else
{
USBH_BulkSendData (pdev,
datapointer,
remainingDataLength ,
MSC_Machine.hc_num_out);
remainingDataLength = 0; /* Reset this value and keep in same state */
}
}
else if(URB_Status == URB_NOTREADY)
{
USBH_BulkSendData (pdev,
(datapointer - USBH_MSC_MPS_SIZE),
USBH_MSC_MPS_SIZE ,
MSC_Machine.hc_num_out);
}
else if(URB_Status == URB_STALL)
{
error_direction = USBH_MSC_DIR_OUT;
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_OUT;
/* Refer to USB Mass-Storage Class : BOT (www.usb.org)
6.7.3 Ho - Host expects to send data to the device
3. On a STALL condition sending data, then:
" The host shall clear the Bulk-Out pipe.
4. The host shall attempt to receive a CSW.
The Above statement will do the clear the Bulk-Out pipe.
The Below statement will help in Getting the CSW.
USBH_MSC_BOTXferParam.BOTStateBkp is used to switch to the Original
state after the ClearFeature Command is issued.
*/
USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE;
}
break;
case USBH_MSC_RECEIVE_CSW_STATE:
/* BOT CSW stage */
/* NOTE: We cannot reset the BOTStallErrorCount here as it may come from
the clearFeature from previous command */
USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE;
USBH_MSC_BOTXferParam.pRxTxBuff = USBH_MSC_CSWData.CSWArray;
USBH_MSC_BOTXferParam.DataLength = USBH_MSC_CSW_MAX_LENGTH;
for(index = USBH_MSC_CSW_LENGTH; index != 0; index--)
{
USBH_MSC_CSWData.CSWArray[index] = 0;
}
USBH_MSC_CSWData.CSWArray[0] = 0;
USBH_BulkReceiveData (pdev,
USBH_MSC_BOTXferParam.pRxTxBuff,
USBH_MSC_CSW_MAX_LENGTH ,
MSC_Machine.hc_num_in);
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_DECODE_CSW;
break;
case USBH_MSC_DECODE_CSW:
URB_Status = HCD_GetURB_State(pdev , MSC_Machine.hc_num_in);
/* Decode CSW */
if(URB_Status == URB_DONE)
{
BOTStallErrorCount = 0;
USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE;
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOTXferParam.MSCStateCurrent ;
USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_DecodeCSW(pdev , phost);
}
else if(URB_Status == URB_STALL)
{
error_direction = USBH_MSC_DIR_IN;
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_IN;
}
break;
case USBH_MSC_BOT_ERROR_IN:
status = USBH_MSC_BOT_Abort(pdev, phost, USBH_MSC_DIR_IN);
if (status == USBH_OK)
{
/* Check if the error was due in Both the directions */
if (error_direction == USBH_MSC_BOTH_DIR)
{/* If Both directions are Needed, Switch to OUT Direction */
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_OUT;
}
else
{
/* Switch Back to the Original State, In many cases this will be
USBH_MSC_RECEIVE_CSW_STATE state */
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp;
}
}
else if (status == USBH_UNRECOVERED_ERROR)
{
/* This means that there is a STALL Error limit, Do Reset Recovery */
USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_PHASE_ERROR;
}
break;
case USBH_MSC_BOT_ERROR_OUT:
status = USBH_MSC_BOT_Abort(pdev, phost, USBH_MSC_DIR_OUT);
if ( status == USBH_OK)
{ /* Switch Back to the Original State */
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp;
}
else if (status == USBH_UNRECOVERED_ERROR)
{
/* This means that there is a STALL Error limit, Do Reset Recovery */
USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_PHASE_ERROR;
}
break;
default:
break;
}
}
}
/**
* @brief USBH_MSC_BOT_Abort
* This function manages the different Error handling for STALL
* @param direction : IN / OUT
* @retval None
*/
USBH_Status USBH_MSC_BOT_Abort(USB_OTG_CORE_HANDLE *pdev,
USBH_HOST *phost,
uint8_t direction)
{
USBH_Status status;
status = USBH_BUSY;
switch (direction)
{
case USBH_MSC_DIR_IN :
/* send ClrFeture on Bulk IN endpoint */
status = USBH_ClrFeature(pdev,
phost,
MSC_Machine.MSBulkInEp,
MSC_Machine.hc_num_in);
break;
case USBH_MSC_DIR_OUT :
/*send ClrFeature on Bulk OUT endpoint */
status = USBH_ClrFeature(pdev,
phost,
MSC_Machine.MSBulkOutEp,
MSC_Machine.hc_num_out);
break;
default:
break;
}
BOTStallErrorCount++; /* Check Continous Number of times, STALL has Occured */
if (BOTStallErrorCount > MAX_BULK_STALL_COUNT_LIMIT )
{
status = USBH_UNRECOVERED_ERROR;
}
return status;
}
/**
* @brief USBH_MSC_DecodeCSW
* This function decodes the CSW received by the device and updates the
* same to upper layer.
* @param None
* @retval On success USBH_MSC_OK, on failure USBH_MSC_FAIL
* @notes
* Refer to USB Mass-Storage Class : BOT (www.usb.org)
* 6.3.1 Valid CSW Conditions :
* The host shall consider the CSW valid when:
* 1. dCSWSignature is equal to 53425355h
* 2. the CSW is 13 (Dh) bytes in length,
* 3. dCSWTag matches the dCBWTag from the corresponding CBW.
*/
uint8_t USBH_MSC_DecodeCSW(USB_OTG_CORE_HANDLE *pdev , USBH_HOST *phost)
{
uint8_t status;
uint32_t dataXferCount = 0;
status = USBH_MSC_FAIL;
if(HCD_IsDeviceConnected(pdev))
{
/*Checking if the transfer length is diffrent than 13*/
dataXferCount = HCD_GetXferCnt(pdev, MSC_Machine.hc_num_in);
if(dataXferCount != USBH_MSC_CSW_LENGTH)
{
/*(4) Hi > Dn (Host expects to receive data from the device,
Device intends to transfer no data)
(5) Hi > Di (Host expects to receive data from the device,
Device intends to send data to the host)
(9) Ho > Dn (Host expects to send data to the device,
Device intends to transfer no data)
(11) Ho > Do (Host expects to send data to the device,
Device intends to receive data from the host)*/
status = USBH_MSC_PHASE_ERROR;
}
else
{ /* CSW length is Correct */
/* Check validity of the CSW Signature and CSWStatus */
if(USBH_MSC_CSWData.field.CSWSignature == USBH_MSC_BOT_CSW_SIGNATURE)
{/* Check Condition 1. dCSWSignature is equal to 53425355h */
if(USBH_MSC_CSWData.field.CSWTag == USBH_MSC_CBWData.field.CBWTag)
{
/* Check Condition 3. dCSWTag matches the dCBWTag from the
corresponding CBW */
if(USBH_MSC_CSWData.field.CSWStatus == USBH_MSC_OK)
{
/* Refer to USB Mass-Storage Class : BOT (www.usb.org)
Hn Host expects no data transfers
Hi Host expects to receive data from the device
Ho Host expects to send data to the device
Dn Device intends to transfer no data
Di Device intends to send data to the host
Do Device intends to receive data from the host
Section 6.7
(1) Hn = Dn (Host expects no data transfers,
Device intends to transfer no data)
(6) Hi = Di (Host expects to receive data from the device,
Device intends to send data to the host)
(12) Ho = Do (Host expects to send data to the device,
Device intends to receive data from the host)
*/
status = USBH_MSC_OK;
}
else if(USBH_MSC_CSWData.field.CSWStatus == USBH_MSC_FAIL)
{
status = USBH_MSC_FAIL;
}
else if(USBH_MSC_CSWData.field.CSWStatus == USBH_MSC_PHASE_ERROR)
{
/* Refer to USB Mass-Storage Class : BOT (www.usb.org)
Section 6.7
(2) Hn < Di ( Host expects no data transfers,
Device intends to send data to the host)
(3) Hn < Do ( Host expects no data transfers,
Device intends to receive data from the host)
(7) Hi < Di ( Host expects to receive data from the device,
Device intends to send data to the host)
(8) Hi <> Do ( Host expects to receive data from the device,
Device intends to receive data from the host)
(10) Ho <> Di (Host expects to send data to the device,
Di Device intends to send data to the host)
(13) Ho < Do (Host expects to send data to the device,
Device intends to receive data from the host)
*/
status = USBH_MSC_PHASE_ERROR;
}
} /* CSW Tag Matching is Checked */
} /* CSW Signature Correct Checking */
else
{
/* If the CSW Signature is not valid, We sall return the Phase Error to
Upper Layers for Reset Recovery */
status = USBH_MSC_PHASE_ERROR;
}
} /* CSW Length Check*/
}
USBH_MSC_BOTXferParam.BOTXferStatus = status;
return status;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
@@ -1,559 +0,0 @@
/**
******************************************************************************
* @file usbh_msc_core.c
* @author MCD Application Team
* @version V2.0.0
* @date 22-July-2011
* @brief This file implements the MSC class driver functions
* ===================================================================
* MSC Class Description
* ===================================================================
* This module manages the MSC class V1.0 following the "Universal
* Serial Bus Mass Storage Class (MSC) Bulk-Only Transport (BOT) Version 1.0
* Sep. 31, 1999".
* This driver implements the following aspects of the specification:
* - Bulk-Only Transport protocol
* - Subclass : SCSI transparent command set (ref. SCSI Primary Commands - 3 (SPC-3))
*
* @endverbatim
*
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
*/
/* Includes ------------------------------------------------------------------*/
#include "usbh_msc_core.h"
#include "usbh_msc_scsi.h"
#include "usbh_msc_bot.h"
#include "usbh_core.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_MSC_CLASS
* @{
*/
/** @defgroup USBH_MSC_CORE
* @brief This file includes the mass storage related functions
* @{
*/
/** @defgroup USBH_MSC_CORE_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Private_Defines
* @{
*/
#define USBH_MSC_ERROR_RETRY_LIMIT 10
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Private_Variables
* @{
*/
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
__ALIGN_BEGIN MSC_Machine_TypeDef MSC_Machine __ALIGN_END ;
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
__ALIGN_BEGIN USB_Setup_TypeDef MSC_Setup __ALIGN_END ;
uint8_t MSCErrorCount = 0;
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Private_FunctionPrototypes
* @{
*/
static USBH_Status USBH_MSC_InterfaceInit (USB_OTG_CORE_HANDLE *pdev ,
void *phost);
static void USBH_MSC_InterfaceDeInit (USB_OTG_CORE_HANDLE *pdev ,
void *phost);
static USBH_Status USBH_MSC_Handle(USB_OTG_CORE_HANDLE *pdev ,
void *phost);
static USBH_Status USBH_MSC_ClassRequest(USB_OTG_CORE_HANDLE *pdev ,
void *phost);
static USBH_Status USBH_MSC_BOTReset(USB_OTG_CORE_HANDLE *pdev,
USBH_HOST *phost);
static USBH_Status USBH_MSC_GETMaxLUN(USB_OTG_CORE_HANDLE *pdev,
USBH_HOST *phost);
USBH_Class_cb_TypeDef USBH_MSC_cb =
{
USBH_MSC_InterfaceInit,
USBH_MSC_InterfaceDeInit,
USBH_MSC_ClassRequest,
USBH_MSC_Handle,
};
void USBH_MSC_ErrorHandle(uint8_t status);
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_CORE_Private_Functions
* @{
*/
/**
* @brief USBH_MSC_InterfaceInit
* Interface initialization for MSC class.
* @param pdev: Selected device
* @param hdev: Selected device property
* @retval USBH_Status : Status of class request handled.
*/
static USBH_Status USBH_MSC_InterfaceInit ( USB_OTG_CORE_HANDLE *pdev,
void *phost)
{
USBH_HOST *pphost = phost;
if((pphost->device_prop.Itf_Desc[0].bInterfaceClass == MSC_CLASS) && \
(pphost->device_prop.Itf_Desc[0].bInterfaceProtocol == MSC_PROTOCOL))
{
if(pphost->device_prop.Ep_Desc[0][0].bEndpointAddress & 0x80)
{
MSC_Machine.MSBulkInEp = (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress);
MSC_Machine.MSBulkInEpSize = pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize;
}
else
{
MSC_Machine.MSBulkOutEp = (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress);
MSC_Machine.MSBulkOutEpSize = pphost->device_prop.Ep_Desc[0] [0].wMaxPacketSize;
}
if(pphost->device_prop.Ep_Desc[0][1].bEndpointAddress & 0x80)
{
MSC_Machine.MSBulkInEp = (pphost->device_prop.Ep_Desc[0][1].bEndpointAddress);
MSC_Machine.MSBulkInEpSize = pphost->device_prop.Ep_Desc[0][1].wMaxPacketSize;
}
else
{
MSC_Machine.MSBulkOutEp = (pphost->device_prop.Ep_Desc[0][1].bEndpointAddress);
MSC_Machine.MSBulkOutEpSize = pphost->device_prop.Ep_Desc[0][1].wMaxPacketSize;
}
MSC_Machine.hc_num_out = USBH_Alloc_Channel(pdev,
MSC_Machine.MSBulkOutEp);
MSC_Machine.hc_num_in = USBH_Alloc_Channel(pdev,
MSC_Machine.MSBulkInEp);
/* Open the new channels */
USBH_Open_Channel (pdev,
MSC_Machine.hc_num_out,
pphost->device_prop.address,
pphost->device_prop.speed,
EP_TYPE_BULK,
MSC_Machine.MSBulkOutEpSize);
USBH_Open_Channel (pdev,
MSC_Machine.hc_num_in,
pphost->device_prop.address,
pphost->device_prop.speed,
EP_TYPE_BULK,
MSC_Machine.MSBulkInEpSize);
}
else
{
pphost->usr_cb->USBH_USR_DeviceNotSupported();
}
return USBH_OK ;
}
/**
* @brief USBH_MSC_InterfaceDeInit
* De-Initialize interface by freeing host channels allocated to interface
* @param pdev: Selected device
* @param hdev: Selected device property
* @retval None
*/
void USBH_MSC_InterfaceDeInit ( USB_OTG_CORE_HANDLE *pdev,
void *phost)
{
if ( MSC_Machine.hc_num_out)
{
USB_OTG_HC_Halt(pdev, MSC_Machine.hc_num_out);
USBH_Free_Channel (pdev, MSC_Machine.hc_num_out);
MSC_Machine.hc_num_out = 0; /* Reset the Channel as Free */
}
if ( MSC_Machine.hc_num_in)
{
USB_OTG_HC_Halt(pdev, MSC_Machine.hc_num_in);
USBH_Free_Channel (pdev, MSC_Machine.hc_num_in);
MSC_Machine.hc_num_in = 0; /* Reset the Channel as Free */
}
}
/**
* @brief USBH_MSC_ClassRequest
* This function will only initialize the MSC state machine
* @param pdev: Selected device
* @param hdev: Selected device property
* @retval USBH_Status : Status of class request handled.
*/
static USBH_Status USBH_MSC_ClassRequest(USB_OTG_CORE_HANDLE *pdev ,
void *phost)
{
USBH_Status status = USBH_OK ;
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_INIT_STATE;
return status;
}
/**
* @brief USBH_MSC_Handle
* MSC state machine handler
* @param pdev: Selected device
* @param hdev: Selected device property
* @retval USBH_Status
*/
static USBH_Status USBH_MSC_Handle(USB_OTG_CORE_HANDLE *pdev ,
void *phost)
{
USBH_HOST *pphost = phost;
USBH_Status status = USBH_BUSY;
uint8_t mscStatus = USBH_MSC_BUSY;
uint8_t appliStatus = 0;
static uint8_t maxLunExceed = FALSE;
if(HCD_IsDeviceConnected(pdev))
{
switch(USBH_MSC_BOTXferParam.MSCState)
{
case USBH_MSC_BOT_INIT_STATE:
USBH_MSC_Init(pdev);
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_RESET;
break;
case USBH_MSC_BOT_RESET:
/* Issue BOT RESET request */
status = USBH_MSC_BOTReset(pdev, phost);
if(status == USBH_OK )
{
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_GET_MAX_LUN;
}
if(status == USBH_NOT_SUPPORTED )
{
/* If the Command has failed, then we need to move to Next State, after
STALL condition is cleared by Control-Transfer */
USBH_MSC_BOTXferParam.MSCStateBkp = USBH_MSC_GET_MAX_LUN;
/* a Clear Feature should be issued here */
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_CTRL_ERROR_STATE;
}
break;
case USBH_MSC_GET_MAX_LUN:
/* Issue GetMaxLUN request */
status = USBH_MSC_GETMaxLUN(pdev, phost);
if(status == USBH_OK )
{
MSC_Machine.maxLun = *(MSC_Machine.buff) ;
/* If device has more that one logical unit then it is not supported */
if((MSC_Machine.maxLun > 0) && (maxLunExceed == FALSE))
{
maxLunExceed = TRUE;
pphost->usr_cb->USBH_USR_DeviceNotSupported();
break;
}
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_TEST_UNIT_READY;
}
if(status == USBH_NOT_SUPPORTED )
{
/* If the Command has failed, then we need to move to Next State, after
STALL condition is cleared by Control-Transfer */
USBH_MSC_BOTXferParam.MSCStateBkp = USBH_MSC_TEST_UNIT_READY;
/* a Clear Feature should be issued here */
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_CTRL_ERROR_STATE;
}
break;
case USBH_MSC_CTRL_ERROR_STATE:
/* Issue Clearfeature request */
status = USBH_ClrFeature(pdev,
phost,
0x00,
pphost->Control.hc_num_out);
if(status == USBH_OK )
{
/* If GetMaxLun Request not support, assume Single LUN configuration */
MSC_Machine.maxLun = 0;
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOTXferParam.MSCStateBkp;
}
break;
case USBH_MSC_TEST_UNIT_READY:
/* Issue SCSI command TestUnitReady */
mscStatus = USBH_MSC_TestUnitReady(pdev);
if(mscStatus == USBH_MSC_OK )
{
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_READ_CAPACITY10;
MSCErrorCount = 0;
status = USBH_OK;
}
else
{
USBH_MSC_ErrorHandle(mscStatus);
}
break;
case USBH_MSC_READ_CAPACITY10:
/* Issue READ_CAPACITY10 SCSI command */
mscStatus = USBH_MSC_ReadCapacity10(pdev);
if(mscStatus == USBH_MSC_OK )
{
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_MODE_SENSE6;
MSCErrorCount = 0;
status = USBH_OK;
}
else
{
USBH_MSC_ErrorHandle(mscStatus);
}
break;
case USBH_MSC_MODE_SENSE6:
/* Issue ModeSense6 SCSI command for detecting if device is write-protected */
mscStatus = USBH_MSC_ModeSense6(pdev);
if(mscStatus == USBH_MSC_OK )
{
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_DEFAULT_APPLI_STATE;
MSCErrorCount = 0;
status = USBH_OK;
}
else
{
USBH_MSC_ErrorHandle(mscStatus);
}
break;
case USBH_MSC_REQUEST_SENSE:
/* Issue RequestSense SCSI command for retreiving error code */
mscStatus = USBH_MSC_RequestSense(pdev);
if(mscStatus == USBH_MSC_OK )
{
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOTXferParam.MSCStateBkp;
status = USBH_OK;
}
else
{
USBH_MSC_ErrorHandle(mscStatus);
}
break;
case USBH_MSC_BOT_USB_TRANSFERS:
/* Process the BOT state machine */
USBH_MSC_HandleBOTXfer(pdev , phost);
break;
case USBH_MSC_DEFAULT_APPLI_STATE:
/* Process Application callback for MSC */
appliStatus = pphost->usr_cb->USBH_USR_MSC_Application();
if(appliStatus == 0)
{
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_DEFAULT_APPLI_STATE;
}
else if (appliStatus == 1)
{
/* De-init requested from application layer */
status = USBH_APPLY_DEINIT;
}
break;
case USBH_MSC_UNRECOVERED_STATE:
status = USBH_UNRECOVERED_ERROR;
break;
default:
break;
}
}
return status;
}
/**
* @brief USBH_MSC_BOTReset
* This request is used to reset the mass storage device and its
* associated interface. This class-specific request shall ready the
* device for the next CBW from the host.
* @param pdev: Selected device
* @retval USBH_Status : Status of class request handled.
*/
static USBH_Status USBH_MSC_BOTReset(USB_OTG_CORE_HANDLE *pdev,
USBH_HOST *phost)
{
phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_TYPE_CLASS | \
USB_REQ_RECIPIENT_INTERFACE;
phost->Control.setup.b.bRequest = USB_REQ_BOT_RESET;
phost->Control.setup.b.wValue.w = 0;
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = 0;
return USBH_CtlReq(pdev, phost, 0 , 0 );
}
/**
* @brief USBH_MSC_GETMaxLUN
* This request is used to reset the mass storage device and its
* associated interface. This class-specific request shall ready the
* device for the next CBW from the host.
* @param pdev: Selected device
* @retval USBH_Status : USB ctl xfer status
*/
static USBH_Status USBH_MSC_GETMaxLUN(USB_OTG_CORE_HANDLE *pdev , USBH_HOST *phost)
{
phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_TYPE_CLASS | \
USB_REQ_RECIPIENT_INTERFACE;
phost->Control.setup.b.bRequest = USB_REQ_GET_MAX_LUN;
phost->Control.setup.b.wValue.w = 0;
phost->Control.setup.b.wIndex.w = 0;
phost->Control.setup.b.wLength.w = 1;
return USBH_CtlReq(pdev, phost, MSC_Machine.buff , 1 );
}
/**
* @brief USBH_MSC_ErrorHandle
* The function is for handling errors occuring during the MSC
* state machine
* @param status
* @retval None
*/
void USBH_MSC_ErrorHandle(uint8_t status)
{
if(status == USBH_MSC_FAIL)
{
MSCErrorCount++;
if(MSCErrorCount < USBH_MSC_ERROR_RETRY_LIMIT)
{ /* Try MSC level error recovery, Issue the request Sense to get
Drive error reason */
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_REQUEST_SENSE;
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
}
else
{
/* Error trials exceeded the limit, go to unrecovered state */
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_UNRECOVERED_STATE;
}
}
else if(status == USBH_MSC_PHASE_ERROR)
{
/* Phase error, Go to Unrecoovered state */
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_UNRECOVERED_STATE;
}
else if(status == USBH_MSC_BUSY)
{
/*No change in state*/
}
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
@@ -1,186 +0,0 @@
#include "usb_conf.h"
#include "diskio.h"
#include "usbh_msc_core.h"
/*--------------------------------------------------------------------------
Module Private Functions and Variables
---------------------------------------------------------------------------*/
static volatile DSTATUS Stat = STA_NOINIT; /* Disk status */
extern USB_OTG_CORE_HANDLE USB_OTG_Core;
extern USBH_HOST USB_Host;
/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE drv /* Physical drive number (0) */
)
{
if(HCD_IsDeviceConnected(&USB_OTG_Core))
{
Stat &= ~STA_NOINIT;
}
return Stat;
}
/*-----------------------------------------------------------------------*/
/* Get Disk Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE drv /* Physical drive number (0) */
)
{
if (drv) return STA_NOINIT; /* Supports only single drive */
return Stat;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE drv, /* Physical drive number (0) */
BYTE *buff, /* Pointer to the data buffer to store read data */
DWORD sector, /* Start sector number (LBA) */
BYTE count /* Sector count (1..255) */
)
{
BYTE status = USBH_MSC_OK;
if (drv || !count) return RES_PARERR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
if(HCD_IsDeviceConnected(&USB_OTG_Core))
{
do
{
status = USBH_MSC_Read10(&USB_OTG_Core, buff, sector, 512*count);
USBH_MSC_HandleBOTXfer(&USB_OTG_Core ,&USB_Host);
if(!HCD_IsDeviceConnected(&USB_OTG_Core))
{
return RES_ERROR;
}
}
while(status == USBH_MSC_BUSY );
}
if(status == USBH_MSC_OK)
return RES_OK;
return RES_ERROR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
#if _READONLY == 0
DRESULT disk_write (
BYTE drv, /* Physical drive number (0) */
const BYTE *buff, /* Pointer to the data to be written */
DWORD sector, /* Start sector number (LBA) */
BYTE count /* Sector count (1..255) */
)
{
BYTE status = USBH_MSC_OK;
if (drv || !count) return RES_PARERR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
if (Stat & STA_PROTECT) return RES_WRPRT;
if(HCD_IsDeviceConnected(&USB_OTG_Core))
{
do
{
status = USBH_MSC_Write10(&USB_OTG_Core,(BYTE*)buff, sector, 512*count);
USBH_MSC_HandleBOTXfer(&USB_OTG_Core, &USB_Host);
if(!HCD_IsDeviceConnected(&USB_OTG_Core))
{
return RES_ERROR;
}
}
while(status == USBH_MSC_BUSY );
}
if(status == USBH_MSC_OK)
return RES_OK;
return RES_ERROR;
}
#endif /* _READONLY == 0 */
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
#if _USE_IOCTL != 0
DRESULT disk_ioctl (
BYTE drv, /* Physical drive number (0) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res = RES_OK;
if (drv) return RES_PARERR;
res = RES_ERROR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
switch (ctrl) {
case CTRL_SYNC : /* Make sure that no pending write process */
res = RES_OK;
break;
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
*(DWORD*)buff = (DWORD) USBH_MSC_Param.MSCapacity;
res = RES_OK;
break;
case GET_SECTOR_SIZE : /* Get R/W sector size (WORD) */
*(WORD*)buff = 512;
res = RES_OK;
break;
case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */
*(DWORD*)buff = 512;
break;
default:
res = RES_PARERR;
}
return res;
}
#endif /* _USE_IOCTL != 0 */
@@ -1,674 +0,0 @@
/**
******************************************************************************
* @file usbh_msc_scsi.c
* @author MCD Application Team
* @version V2.0.0
* @date 22-July-2011
* @brief This file implements the SCSI commands
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbh_msc_core.h"
#include "usbh_msc_scsi.h"
#include "usbh_msc_bot.h"
#include "usbh_ioreq.h"
#include "usbh_def.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_CLASS
* @{
*/
/** @addtogroup USBH_MSC_CLASS
* @{
*/
/** @defgroup USBH_MSC_SCSI
* @brief This file includes the mass storage related functions
* @{
*/
/** @defgroup USBH_MSC_SCSI_Private_TypesDefinitions
* @{
*/
MassStorageParameter_TypeDef USBH_MSC_Param;
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Private_Variables
* @{
*/
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
__ALIGN_BEGIN uint8_t USBH_DataInBuffer[512] __ALIGN_END ;
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
__ALIGN_BEGIN uint8_t USBH_DataOutBuffer[512] __ALIGN_END ;
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_MSC_SCSI_Private_Functions
* @{
*/
/**
* @brief USBH_MSC_TestUnitReady
* Issues 'Test unit ready' command to the device. Once the response
* received, it updates the status to upper layer.
* @param None
* @retval Status
*/
uint8_t USBH_MSC_TestUnitReady (USB_OTG_CORE_HANDLE *pdev)
{
uint8_t index;
USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;
if(HCD_IsDeviceConnected(pdev))
{
switch(USBH_MSC_BOTXferParam.CmdStateMachine)
{
case CMD_SEND_STATE:
/*Prepare the CBW and relevent field*/
USBH_MSC_CBWData.field.CBWTransferLength = 0; /* No Data Transfer */
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_OUT;
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH_TEST_UNIT_READY;
USBH_MSC_BOTXferParam.pRxTxBuff = USBH_MSC_CSWData.CSWArray;
USBH_MSC_BOTXferParam.DataLength = USBH_MSC_CSW_MAX_LENGTH;
USBH_MSC_BOTXferParam.MSCStateCurrent = USBH_MSC_TEST_UNIT_READY;
for(index = CBW_CB_LENGTH; index != 0; index--)
{
USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
}
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_TEST_UNIT_READY;
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
/* Start the transfer, then let the state
machine magage the other transactions */
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
status = USBH_MSC_BUSY;
break;
case CMD_WAIT_STATUS:
if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK)
{
/* Commands successfully sent and Response Received */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_OK;
}
else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL )
{
/* Failure Mode */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_FAIL;
}
else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR )
{
/* Failure Mode */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_PHASE_ERROR;
}
break;
default:
break;
}
}
return status;
}
/**
* @brief USBH_MSC_ReadCapacity10
* Issue the read capacity command to the device. Once the response
* received, it updates the status to upper layer
* @param None
* @retval Status
*/
uint8_t USBH_MSC_ReadCapacity10(USB_OTG_CORE_HANDLE *pdev)
{
uint8_t index;
USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;
if(HCD_IsDeviceConnected(pdev))
{
switch(USBH_MSC_BOTXferParam.CmdStateMachine)
{
case CMD_SEND_STATE:
/*Prepare the CBW and relevent field*/
USBH_MSC_CBWData.field.CBWTransferLength = XFER_LEN_READ_CAPACITY10;
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
USBH_MSC_BOTXferParam.pRxTxBuff = USBH_DataInBuffer;
USBH_MSC_BOTXferParam.MSCStateCurrent = USBH_MSC_READ_CAPACITY10;
for(index = CBW_CB_LENGTH; index != 0; index--)
{
USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
}
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_READ_CAPACITY10;
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
/* Start the transfer, then let the state machine manage the other
transactions */
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
status = USBH_MSC_BUSY;
break;
case CMD_WAIT_STATUS:
if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK)
{
/*assign the capacity*/
(((uint8_t*)&USBH_MSC_Param.MSCapacity )[3]) = USBH_DataInBuffer[0];
(((uint8_t*)&USBH_MSC_Param.MSCapacity )[2]) = USBH_DataInBuffer[1];
(((uint8_t*)&USBH_MSC_Param.MSCapacity )[1]) = USBH_DataInBuffer[2];
(((uint8_t*)&USBH_MSC_Param.MSCapacity )[0]) = USBH_DataInBuffer[3];
/*assign the page length*/
(((uint8_t*)&USBH_MSC_Param.MSPageLength )[1]) = USBH_DataInBuffer[6];
(((uint8_t*)&USBH_MSC_Param.MSPageLength )[0]) = USBH_DataInBuffer[7];
/* Commands successfully sent and Response Received */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_OK;
}
else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL )
{
/* Failure Mode */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_FAIL;
}
else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR )
{
/* Failure Mode */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_PHASE_ERROR;
}
else
{
/* Wait for the Commands to get Completed */
/* NO Change in state Machine */
}
break;
default:
break;
}
}
return status;
}
/**
* @brief USBH_MSC_ModeSense6
* Issue the Mode Sense6 Command to the device. This function is used
* for reading the WriteProtect Status of the Mass-Storage device.
* @param None
* @retval Status
*/
uint8_t USBH_MSC_ModeSense6(USB_OTG_CORE_HANDLE *pdev)
{
uint8_t index;
USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;
if(HCD_IsDeviceConnected(pdev))
{
switch(USBH_MSC_BOTXferParam.CmdStateMachine)
{
case CMD_SEND_STATE:
/*Prepare the CBW and relevent field*/
USBH_MSC_CBWData.field.CBWTransferLength = XFER_LEN_MODE_SENSE6;
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
USBH_MSC_BOTXferParam.pRxTxBuff = USBH_DataInBuffer;
USBH_MSC_BOTXferParam.MSCStateCurrent = USBH_MSC_MODE_SENSE6;
for(index = CBW_CB_LENGTH; index != 0; index--)
{
USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
}
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_MODE_SENSE6;
USBH_MSC_CBWData.field.CBWCB[2] = MODE_SENSE_PAGE_CONTROL_FIELD | \
MODE_SENSE_PAGE_CODE;
USBH_MSC_CBWData.field.CBWCB[4] = XFER_LEN_MODE_SENSE6;
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
/* Start the transfer, then let the state machine manage the other
transactions */
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
status = USBH_MSC_BUSY;
break;
case CMD_WAIT_STATUS:
if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK)
{
/* Assign the Write Protect status */
/* If WriteProtect = 0, Writing is allowed
If WriteProtect != 0, Disk is Write Protected */
if ( USBH_DataInBuffer[2] & MASK_MODE_SENSE_WRITE_PROTECT)
{
USBH_MSC_Param.MSWriteProtect = DISK_WRITE_PROTECTED;
}
else
{
USBH_MSC_Param.MSWriteProtect = 0;
}
/* Commands successfully sent and Response Received */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_OK;
}
else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL )
{
/* Failure Mode */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_FAIL;
}
else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR )
{
/* Failure Mode */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_PHASE_ERROR;
}
else
{
/* Wait for the Commands to get Completed */
/* NO Change in state Machine */
}
break;
default:
break;
}
}
return status;
}
/**
* @brief USBH_MSC_RequestSense
* Issues the Request Sense command to the device. Once the response
* received, it updates the status to upper layer
* @param None
* @retval Status
*/
uint8_t USBH_MSC_RequestSense(USB_OTG_CORE_HANDLE *pdev)
{
USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;
uint8_t index;
if(HCD_IsDeviceConnected(pdev))
{
switch(USBH_MSC_BOTXferParam.CmdStateMachine)
{
case CMD_SEND_STATE:
/*Prepare the CBW and relevent field*/
USBH_MSC_CBWData.field.CBWTransferLength = \
ALLOCATION_LENGTH_REQUEST_SENSE;
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
USBH_MSC_BOTXferParam.pRxTxBuff = USBH_DataInBuffer;
USBH_MSC_BOTXferParam.MSCStateBkp = USBH_MSC_BOTXferParam.MSCStateCurrent;
USBH_MSC_BOTXferParam.MSCStateCurrent = USBH_MSC_REQUEST_SENSE;
for(index = CBW_CB_LENGTH; index != 0; index--)
{
USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
}
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_REQUEST_SENSE;
USBH_MSC_CBWData.field.CBWCB[1] = DESC_REQUEST_SENSE;
USBH_MSC_CBWData.field.CBWCB[4] = ALLOCATION_LENGTH_REQUEST_SENSE;
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
/* Start the transfer, then let the state machine magage
the other transactions */
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
status = USBH_MSC_BUSY;
break;
case CMD_WAIT_STATUS:
if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK)
{
/* Get Sense data*/
(((uint8_t*)&USBH_MSC_Param.MSSenseKey )[3]) = USBH_DataInBuffer[0];
(((uint8_t*)&USBH_MSC_Param.MSSenseKey )[2]) = USBH_DataInBuffer[1];
(((uint8_t*)&USBH_MSC_Param.MSSenseKey )[1]) = USBH_DataInBuffer[2];
(((uint8_t*)&USBH_MSC_Param.MSSenseKey )[0]) = USBH_DataInBuffer[3];
/* Commands successfully sent and Response Received */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_OK;
}
else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL )
{
/* Failure Mode */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_FAIL;
}
else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR )
{
/* Failure Mode */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_PHASE_ERROR;
}
else
{
/* Wait for the Commands to get Completed */
/* NO Change in state Machine */
}
break;
default:
break;
}
}
return status;
}
/**
* @brief USBH_MSC_Write10
* Issue the write command to the device. Once the response received,
* it updates the status to upper layer
* @param dataBuffer : DataBuffer contains the data to write
* @param address : Address to which the data will be written
* @param nbOfbytes : NbOfbytes to be written
* @retval Status
*/
uint8_t USBH_MSC_Write10(USB_OTG_CORE_HANDLE *pdev,
uint8_t *dataBuffer,
uint32_t address,
uint32_t nbOfbytes)
{
uint8_t index;
USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;
uint16_t nbOfPages;
if(HCD_IsDeviceConnected(pdev))
{
switch(USBH_MSC_BOTXferParam.CmdStateMachine)
{
case CMD_SEND_STATE:
USBH_MSC_CBWData.field.CBWTransferLength = nbOfbytes;
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_OUT;
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
USBH_MSC_BOTXferParam.pRxTxBuff = dataBuffer;
for(index = CBW_CB_LENGTH; index != 0; index--)
{
USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
}
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_WRITE10;
/*logical block address*/
USBH_MSC_CBWData.field.CBWCB[2] = (((uint8_t*)&address)[3]) ;
USBH_MSC_CBWData.field.CBWCB[3] = (((uint8_t*)&address)[2]);
USBH_MSC_CBWData.field.CBWCB[4] = (((uint8_t*)&address)[1]);
USBH_MSC_CBWData.field.CBWCB[5] = (((uint8_t*)&address)[0]);
/*USBH_MSC_PAGE_LENGTH = 512*/
nbOfPages = nbOfbytes/ USBH_MSC_PAGE_LENGTH;
/*Tranfer length */
USBH_MSC_CBWData.field.CBWCB[7] = (((uint8_t *)&nbOfPages)[1]) ;
USBH_MSC_CBWData.field.CBWCB[8] = (((uint8_t *)&nbOfPages)[0]) ;
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
/* Start the transfer, then let the state machine
magage the other transactions */
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
status = USBH_MSC_BUSY;
break;
case CMD_WAIT_STATUS:
if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK)
{
/* Commands successfully sent and Response Received */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_OK;
}
else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL )
{
/* Failure Mode */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
}
else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR )
{
/* Failure Mode */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_PHASE_ERROR;
}
break;
default:
break;
}
}
return status;
}
/**
* @brief USBH_MSC_Read10
* Issue the read command to the device. Once the response received,
* it updates the status to upper layer
* @param dataBuffer : DataBuffer will contain the data to be read
* @param address : Address from which the data will be read
* @param nbOfbytes : NbOfbytes to be read
* @retval Status
*/
uint8_t USBH_MSC_Read10(USB_OTG_CORE_HANDLE *pdev,
uint8_t *dataBuffer,
uint32_t address,
uint32_t nbOfbytes)
{
uint8_t index;
static USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;
uint16_t nbOfPages;
status = USBH_MSC_BUSY;
if(HCD_IsDeviceConnected(pdev))
{
switch(USBH_MSC_BOTXferParam.CmdStateMachine)
{
case CMD_SEND_STATE:
/*Prepare the CBW and relevent field*/
USBH_MSC_CBWData.field.CBWTransferLength = nbOfbytes;
USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
USBH_MSC_BOTXferParam.pRxTxBuff = dataBuffer;
for(index = CBW_CB_LENGTH; index != 0; index--)
{
USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
}
USBH_MSC_CBWData.field.CBWCB[0] = OPCODE_READ10;
/*logical block address*/
USBH_MSC_CBWData.field.CBWCB[2] = (((uint8_t*)&address)[3]);
USBH_MSC_CBWData.field.CBWCB[3] = (((uint8_t*)&address)[2]);
USBH_MSC_CBWData.field.CBWCB[4] = (((uint8_t*)&address)[1]);
USBH_MSC_CBWData.field.CBWCB[5] = (((uint8_t*)&address)[0]);
/*USBH_MSC_PAGE_LENGTH = 512*/
nbOfPages = nbOfbytes/ USBH_MSC_PAGE_LENGTH;
/*Tranfer length */
USBH_MSC_CBWData.field.CBWCB[7] = (((uint8_t *)&nbOfPages)[1]) ;
USBH_MSC_CBWData.field.CBWCB[8] = (((uint8_t *)&nbOfPages)[0]) ;
USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
/* Start the transfer, then let the state machine
magage the other transactions */
USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
status = USBH_MSC_BUSY;
break;
case CMD_WAIT_STATUS:
if((USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK) && \
(HCD_IsDeviceConnected(pdev)))
{
/* Commands successfully sent and Response Received */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_OK;
}
else if (( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL ) && \
(HCD_IsDeviceConnected(pdev)))
{
/* Failure Mode */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
}
else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR )
{
/* Failure Mode */
USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
status = USBH_MSC_PHASE_ERROR;
}
else
{
/* Wait for the Commands to get Completed */
/* NO Change in state Machine */
}
break;
default:
break;
}
}
return status;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
@@ -1,94 +0,0 @@
/**
******************************************************************************
* @file usbh_conf_template
* @author MCD Application Team
* @version V2.0.0
* @date 22-July-2011
* @brief General USB Host library configuration
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBH_CONF__H__
#define __USBH_CONF__H__
/* Includes ------------------------------------------------------------------*/
/** @addtogroup USBH_OTG_DRIVER
* @{
*/
/** @defgroup USBH_CONF
* @brief usb otg low level driver configuration file
* @{
*/
/** @defgroup USBH_CONF_Exported_Defines
* @{
*/
#define USBH_MAX_NUM_ENDPOINTS 2
#define USBH_MAX_NUM_INTERFACES 2
#ifdef USE_USB_OTG_FS
#define USBH_MSC_MPS_SIZE 0x40
#else
#define USBH_MSC_MPS_SIZE 0x200
#endif
/**
* @}
*/
/** @defgroup USBH_CONF_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CONF_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CONF_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CONF_Exported_FunctionsPrototype
* @{
*/
/**
* @}
*/
#endif //__USBH_CONF__H__
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
@@ -1,289 +0,0 @@
/**
******************************************************************************
* @file usbh_core.h
* @author MCD Application Team
* @version V2.0.0
* @date 22-July-2011
* @brief Header file for usbh_core.c
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_CORE_H
#define __USBH_CORE_H
/* Includes ------------------------------------------------------------------*/
#include "usb_hcd.h"
#include "usbh_def.h"
#include "usbh_conf.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_LIB_CORE
* @{
*/
/** @defgroup USBH_CORE
* @brief This file is the Header file for usbh_core.c
* @{
*/
/** @defgroup USBH_CORE_Exported_Defines
* @{
*/
#define MSC_CLASS 0x08
#define HID_CLASS 0x03
#define MSC_PROTOCOL 0x50
#define CBI_PROTOCOL 0x01
#define USBH_MAX_ERROR_COUNT 2
#define USBH_DEVICE_ADDRESS_DEFAULT 0
#define USBH_DEVICE_ADDRESS 1
/**
* @}
*/
/** @defgroup USBH_CORE_Exported_Types
* @{
*/
typedef enum {
USBH_OK = 0,
USBH_BUSY,
USBH_FAIL,
USBH_NOT_SUPPORTED,
USBH_UNRECOVERED_ERROR,
USBH_ERROR_SPEED_UNKNOWN,
USBH_APPLY_DEINIT
}USBH_Status;
/* Following states are used for gState */
typedef enum {
HOST_IDLE =0,
HOST_ISSUE_CORE_RESET,
HOST_DEV_ATTACHED,
HOST_DEV_DISCONNECTED,
HOST_ISSUE_RESET,
HOST_DETECT_DEVICE_SPEED,
HOST_ENUMERATION,
HOST_CLASS_REQUEST,
HOST_CLASS,
HOST_CTRL_XFER,
HOST_USR_INPUT,
HOST_SUSPENDED,
HOST_ERROR_STATE
}HOST_State;
/* Following states are used for EnumerationState */
typedef enum {
ENUM_IDLE = 0,
ENUM_GET_FULL_DEV_DESC,
ENUM_SET_ADDR,
ENUM_GET_CFG_DESC,
ENUM_GET_FULL_CFG_DESC,
ENUM_GET_MFC_STRING_DESC,
ENUM_GET_PRODUCT_STRING_DESC,
ENUM_GET_SERIALNUM_STRING_DESC,
ENUM_SET_CONFIGURATION,
ENUM_DEV_CONFIGURED
} ENUM_State;
/* Following states are used for CtrlXferStateMachine */
typedef enum {
CTRL_IDLE =0,
CTRL_SETUP,
CTRL_SETUP_WAIT,
CTRL_DATA_IN,
CTRL_DATA_IN_WAIT,
CTRL_DATA_OUT,
CTRL_DATA_OUT_WAIT,
CTRL_STATUS_IN,
CTRL_STATUS_IN_WAIT,
CTRL_STATUS_OUT,
CTRL_STATUS_OUT_WAIT,
CTRL_ERROR
}
CTRL_State;
typedef enum {
USBH_USR_NO_RESP = 0,
USBH_USR_RESP_OK = 1,
}
USBH_USR_Status;
/* Following states are used for RequestState */
typedef enum {
CMD_IDLE =0,
CMD_SEND,
CMD_WAIT
} CMD_State;
typedef struct _Ctrl
{
uint8_t hc_num_in;
uint8_t hc_num_out;
uint8_t ep0size;
uint8_t *buff;
uint16_t length;
uint8_t errorcount;
uint16_t timer;
CTRL_STATUS status;
USB_Setup_TypeDef setup;
CTRL_State state;
} USBH_Ctrl_TypeDef;
typedef struct _DeviceProp
{
uint8_t address;
uint8_t speed;
USBH_DevDesc_TypeDef Dev_Desc;
USBH_CfgDesc_TypeDef Cfg_Desc;
USBH_InterfaceDesc_TypeDef Itf_Desc[USBH_MAX_NUM_INTERFACES];
USBH_EpDesc_TypeDef Ep_Desc[USBH_MAX_NUM_INTERFACES][USBH_MAX_NUM_ENDPOINTS];
USBH_HIDDesc_TypeDef HID_Desc;
}USBH_Device_TypeDef;
typedef struct _USBH_Class_cb
{
USBH_Status (*Init)\
(USB_OTG_CORE_HANDLE *pdev , void *phost);
void (*DeInit)\
(USB_OTG_CORE_HANDLE *pdev , void *phost);
USBH_Status (*Requests)\
(USB_OTG_CORE_HANDLE *pdev , void *phost);
USBH_Status (*Machine)\
(USB_OTG_CORE_HANDLE *pdev , void *phost);
} USBH_Class_cb_TypeDef;
typedef struct _USBH_USR_PROP
{
void (*Init)(void); /* HostLibInitialized */
void (*DeInit)(void); /* HostLibInitialized */
void (*DeviceAttached)(void); /* DeviceAttached */
void (*ResetDevice)(void);
void (*DeviceDisconnected)(void);
void (*OverCurrentDetected)(void);
void (*DeviceSpeedDetected)(uint8_t DeviceSpeed); /* DeviceSpeed */
void (*DeviceDescAvailable)(void *); /* DeviceDescriptor is available */
void (*DeviceAddressAssigned)(void); /* Address is assigned to USB Device */
void (*ConfigurationDescAvailable)(USBH_CfgDesc_TypeDef *,
USBH_InterfaceDesc_TypeDef *,
USBH_EpDesc_TypeDef *);
/* Configuration Descriptor available */
void (*ManufacturerString)(void *); /* ManufacturerString*/
void (*ProductString)(void *); /* ProductString*/
void (*SerialNumString)(void *); /* SerialNubString*/
void (*EnumerationDone)(void); /* Enumeration finished */
USBH_USR_Status (*UserInput)(void);
int (*USBH_USR_MSC_Application) (void);
void (*USBH_USR_DeviceNotSupported)(void); /* Device is not supported*/
void (*UnrecoveredError)(void);
}
USBH_Usr_cb_TypeDef;
typedef struct _Host_TypeDef
{
HOST_State gState; /* Host State Machine Value */
HOST_State gStateBkp; /* backup of previous State machine value */
ENUM_State EnumState; /* Enumeration state Machine */
CMD_State RequestState;
USBH_Ctrl_TypeDef Control;
USBH_Device_TypeDef device_prop;
USBH_Class_cb_TypeDef *class_cb;
USBH_Usr_cb_TypeDef *usr_cb;
} USBH_HOST, *pUSBH_HOST;
/**
* @}
*/
/** @defgroup USBH_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CORE_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_CORE_Exported_FunctionsPrototype
* @{
*/
void USBH_Init(USB_OTG_CORE_HANDLE *pdev,
USB_OTG_CORE_ID_TypeDef coreID,
USBH_HOST *phost,
USBH_Class_cb_TypeDef *class_cb,
USBH_Usr_cb_TypeDef *usr_cb);
USBH_Status USBH_DeInit(USB_OTG_CORE_HANDLE *pdev,
USBH_HOST *phost);
void USBH_Process(USB_OTG_CORE_HANDLE *pdev ,
USBH_HOST *phost);
void USBH_ErrorHandle(USBH_HOST *phost,
USBH_Status errType);
/**
* @}
*/
#endif /* __USBH_CORE_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
@@ -1,280 +0,0 @@
/**
******************************************************************************
* @file usbh_def.h
* @author MCD Application Team
* @version V2.0.0
* @date 22-July-2011
* @brief Definitions used in the USB host library
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_LIB_CORE
* @{
*/
/** @defgroup USBH_DEF
* @brief This file is includes USB descriptors
* @{
*/
#ifndef USBH_DEF_H
#define USBH_DEF_H
#ifndef USBH_NULL
#define USBH_NULL ((void *)0)
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#define ValBit(VAR,POS) (VAR & (1 << POS))
#define SetBit(VAR,POS) (VAR |= (1 << POS))
#define ClrBit(VAR,POS) (VAR &= ((1 << POS)^255))
#define LE16(addr) (((u16)(*((u8 *)(addr))))\
+ (((u16)(*(((u8 *)(addr)) + 1))) << 8))
#define USB_LEN_DESC_HDR 0x02
#define USB_LEN_DEV_DESC 0x12
#define USB_LEN_CFG_DESC 0x09
#define USB_LEN_IF_DESC 0x09
#define USB_LEN_EP_DESC 0x07
#define USB_LEN_OTG_DESC 0x03
#define USB_LEN_SETUP_PKT 0x08
/* bmRequestType :D7 Data Phase Transfer Direction */
#define USB_REQ_DIR_MASK 0x80
#define USB_H2D 0x00
#define USB_D2H 0x80
/* bmRequestType D6..5 Type */
#define USB_REQ_TYPE_STANDARD 0x00
#define USB_REQ_TYPE_CLASS 0x20
#define USB_REQ_TYPE_VENDOR 0x40
#define USB_REQ_TYPE_RESERVED 0x60
/* bmRequestType D4..0 Recipient */
#define USB_REQ_RECIPIENT_DEVICE 0x00
#define USB_REQ_RECIPIENT_INTERFACE 0x01
#define USB_REQ_RECIPIENT_ENDPOINT 0x02
#define USB_REQ_RECIPIENT_OTHER 0x03
/* Table 9-4. Standard Request Codes */
/* bRequest , Value */
#define USB_REQ_GET_STATUS 0x00
#define USB_REQ_CLEAR_FEATURE 0x01
#define USB_REQ_SET_FEATURE 0x03
#define USB_REQ_SET_ADDRESS 0x05
#define USB_REQ_GET_DESCRIPTOR 0x06
#define USB_REQ_SET_DESCRIPTOR 0x07
#define USB_REQ_GET_CONFIGURATION 0x08
#define USB_REQ_SET_CONFIGURATION 0x09
#define USB_REQ_GET_INTERFACE 0x0A
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C
/* Table 9-5. Descriptor Types of USB Specifications */
#define USB_DESC_TYPE_DEVICE 1
#define USB_DESC_TYPE_CONFIGURATION 2
#define USB_DESC_TYPE_STRING 3
#define USB_DESC_TYPE_INTERFACE 4
#define USB_DESC_TYPE_ENDPOINT 5
#define USB_DESC_TYPE_DEVICE_QUALIFIER 6
#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 7
#define USB_DESC_TYPE_INTERFACE_POWER 8
#define USB_DESC_TYPE_HID 0x21
#define USB_DESC_TYPE_HID_REPORT 0x22
#define USB_DEVICE_DESC_SIZE 18
#define USB_CONFIGURATION_DESC_SIZE 9
#define USB_HID_DESC_SIZE 9
#define USB_INTERFACE_DESC_SIZE 9
#define USB_ENDPOINT_DESC_SIZE 7
/* Descriptor Type and Descriptor Index */
/* Use the following values when calling the function USBH_GetDescriptor */
#define USB_DESC_DEVICE ((USB_DESC_TYPE_DEVICE << 8) & 0xFF00)
#define USB_DESC_CONFIGURATION ((USB_DESC_TYPE_CONFIGURATION << 8) & 0xFF00)
#define USB_DESC_STRING ((USB_DESC_TYPE_STRING << 8) & 0xFF00)
#define USB_DESC_INTERFACE ((USB_DESC_TYPE_INTERFACE << 8) & 0xFF00)
#define USB_DESC_ENDPOINT ((USB_DESC_TYPE_INTERFACE << 8) & 0xFF00)
#define USB_DESC_DEVICE_QUALIFIER ((USB_DESC_TYPE_DEVICE_QUALIFIER << 8) & 0xFF00)
#define USB_DESC_OTHER_SPEED_CONFIGURATION ((USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION << 8) & 0xFF00)
#define USB_DESC_INTERFACE_POWER ((USB_DESC_TYPE_INTERFACE_POWER << 8) & 0xFF00)
#define USB_DESC_HID_REPORT ((USB_DESC_TYPE_HID_REPORT << 8) & 0xFF00)
#define USB_DESC_HID ((USB_DESC_TYPE_HID << 8) & 0xFF00)
#define USB_EP_TYPE_CTRL 0x00
#define USB_EP_TYPE_ISOC 0x01
#define USB_EP_TYPE_BULK 0x02
#define USB_EP_TYPE_INTR 0x03
#define USB_EP_DIR_OUT 0x00
#define USB_EP_DIR_IN 0x80
#define USB_EP_DIR_MSK 0x80
/* supported classes */
#define USB_MSC_CLASS 0x08
#define USB_HID_CLASS 0x03
/* Interface Descriptor field values for HID Boot Protocol */
#define HID_BOOT_CODE 0x01
#define HID_KEYBRD_BOOT_CODE 0x01
#define HID_MOUSE_BOOT_CODE 0x02
/* As per USB specs 9.2.6.4 :Standard request with data request timeout: 5sec
Standard request with no data stage timeout : 50ms */
#define DATA_STAGE_TIMEOUT 5000
#define NODATA_STAGE_TIMEOUT 50
/**
* @}
*/
#define USBH_CONFIGURATION_DESCRIPTOR_SIZE (USB_CONFIGURATION_DESC_SIZE \
+ USB_INTERFACE_DESC_SIZE\
+ (USBH_MAX_NUM_ENDPOINTS * USB_ENDPOINT_DESC_SIZE))
#define CONFIG_DESC_wTOTAL_LENGTH (ConfigurationDescriptorData.ConfigDescfield.\
ConfigurationDescriptor.wTotalLength)
/* This Union is copied from usb_core.h */
typedef union
{
uint16_t w;
struct BW
{
uint8_t msb;
uint8_t lsb;
}
bw;
}
uint16_t_uint8_t;
typedef union _USB_Setup
{
uint8_t d8[8];
struct _SetupPkt_Struc
{
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t_uint8_t wValue;
uint16_t_uint8_t wIndex;
uint16_t_uint8_t wLength;
} b;
}
USB_Setup_TypeDef;
typedef struct _DescHeader
{
uint8_t bLength;
uint8_t bDescriptorType;
}
USBH_DescHeader_t;
typedef struct _DeviceDescriptor
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdUSB; /* USB Specification Number which device complies too */
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
/* If equal to Zero, each interface specifies its own class
code if equal to 0xFF, the class code is vendor specified.
Otherwise field is valid Class Code.*/
uint8_t bMaxPacketSize;
uint16_t idVendor; /* Vendor ID (Assigned by USB Org) */
uint16_t idProduct; /* Product ID (Assigned by Manufacturer) */
uint16_t bcdDevice; /* Device Release Number */
uint8_t iManufacturer; /* Index of Manufacturer String Descriptor */
uint8_t iProduct; /* Index of Product String Descriptor */
uint8_t iSerialNumber; /* Index of Serial Number String Descriptor */
uint8_t bNumConfigurations; /* Number of Possible Configurations */
}
USBH_DevDesc_TypeDef;
typedef struct _ConfigurationDescriptor
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength; /* Total Length of Data Returned */
uint8_t bNumInterfaces; /* Number of Interfaces */
uint8_t bConfigurationValue; /* Value to use as an argument to select this configuration*/
uint8_t iConfiguration; /*Index of String Descriptor Describing this configuration */
uint8_t bmAttributes; /* D7 Bus Powered , D6 Self Powered, D5 Remote Wakeup , D4..0 Reserved (0)*/
uint8_t bMaxPower; /*Maximum Power Consumption */
}
USBH_CfgDesc_TypeDef;
typedef struct _HIDDescriptor
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID; /* indicates what endpoint this descriptor is describing */
uint8_t bCountryCode; /* specifies the transfer type. */
uint8_t bNumDescriptors; /* specifies the transfer type. */
uint8_t bReportDescriptorType; /* Maximum Packet Size this endpoint is capable of sending or receiving */
uint16_t wItemLength; /* is used to specify the polling interval of certain transfers. */
}
USBH_HIDDesc_TypeDef;
typedef struct _InterfaceDescriptor
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting; /* Value used to select alternative setting */
uint8_t bNumEndpoints; /* Number of Endpoints used for this interface */
uint8_t bInterfaceClass; /* Class Code (Assigned by USB Org) */
uint8_t bInterfaceSubClass; /* Subclass Code (Assigned by USB Org) */
uint8_t bInterfaceProtocol; /* Protocol Code */
uint8_t iInterface; /* Index of String Descriptor Describing this interface */
}
USBH_InterfaceDesc_TypeDef;
typedef struct _EndpointDescriptor
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress; /* indicates what endpoint this descriptor is describing */
uint8_t bmAttributes; /* specifies the transfer type. */
uint16_t wMaxPacketSize; /* Maximum Packet Size this endpoint is capable of sending or receiving */
uint8_t bInterval; /* is used to specify the polling interval of certain transfers. */
}
USBH_EpDesc_TypeDef;
#endif
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
@@ -1,125 +0,0 @@
/**
******************************************************************************
* @file usbh_hcs.h
* @author MCD Application Team
* @version V2.0.0
* @date 22-July-2011
* @brief Header file for usbh_hcs.c
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_HCS_H
#define __USBH_HCS_H
/* Includes ------------------------------------------------------------------*/
#include "usbh_core.h"
/** @addtogroup USBH_LIB
* @{
*/
/** @addtogroup USBH_LIB_CORE
* @{
*/
/** @defgroup USBH_HCS
* @brief This file is the header file for usbh_hcs.c
* @{
*/
/** @defgroup USBH_HCS_Exported_Defines
* @{
*/
#define HC_MAX 8
#define HC_OK 0x0000
#define HC_USED 0x8000
#define HC_ERROR 0xFFFF
#define HC_USED_MASK 0x7FFF
/**
* @}
*/
/** @defgroup USBH_HCS_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup USBH_HCS_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBH_HCS_Exported_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USBH_HCS_Exported_FunctionsPrototype
* @{
*/
uint8_t USBH_Alloc_Channel(USB_OTG_CORE_HANDLE *pdev, uint8_t ep_addr);
uint8_t USBH_Free_Channel (USB_OTG_CORE_HANDLE *pdev, uint8_t idx);
uint8_t USBH_DeAllocate_AllChannel (USB_OTG_CORE_HANDLE *pdev);
uint8_t USBH_Open_Channel (USB_OTG_CORE_HANDLE *pdev,
uint8_t ch_num,
uint8_t dev_address,
uint8_t speed,
uint8_t ep_type,
uint16_t mps);
uint8_t USBH_Modify_Channel (USB_OTG_CORE_HANDLE *pdev,
uint8_t hc_num,
uint8_t dev_address,
uint8_t speed,
uint8_t ep_type,
uint16_t mps);
/**
* @}
*/
#endif /* __USBH_HCS_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

Some files were not shown because too many files have changed in this diff Show More