24 Commits

Author SHA1 Message Date
id101010
f18a936129 Updated PID values with Ziegler/Nichols 2015-06-08 11:10:26 +02:00
id101010
72dc291e4d Corrected some Errors 2015-06-07 23:26:32 +02:00
id101010
20b20f10c1 Added Fazit and a picture 2015-06-07 22:04:10 +02:00
id101010
d006dbd6a5 Wrote even more documentation 2015-06-07 18:58:20 +02:00
id101010
7e3de6af80 Merge remote-tracking branch 'origin/master' into dev_aaron 2015-06-07 17:02:47 +02:00
t-moe
f432236628 Merge remote-tracking branch 'origin/dev_aaron' 2015-06-07 17:01:59 +02:00
id101010
ce27acef98 Added pictures 2015-06-07 16:57:21 +02:00
t-moe
87523569a7 Started with tests in docu. fixed a small bug in emulator when drawing a rectangle. 2015-06-07 16:45:06 +02:00
id101010
33815f0d6c Documentated TFT, Touch, PID, System 2015-06-07 16:43:03 +02:00
t-moe
4b5768cedc Improved Comments in whole emulator. Finalized emulator section in docu. 2015-06-07 15:29:46 +02:00
t-moe
3e4fbab00a Merge remote-tracking branch 'origin/dev_aaron' into emulator 2015-06-07 13:48:25 +02:00
t-moe
ca1459d9d4 Copied doc resources from master branch. 2015-06-07 13:46:13 +02:00
id101010
3d98ca93bc Minor changes 2015-06-07 13:41:07 +02:00
t-moe
422b1a623c Updated Docu from Emulator. 2015-06-07 13:39:29 +02:00
id101010
802d3df373 Fixed pid controller and refactored code 2015-06-07 13:13:49 +02:00
t-moe
f004cbffa6 Updated Docu: Documented touch module and systemmodule. Improved already documented topics. 2015-06-07 00:02:23 +02:00
t-moe
c06661d25b Fixed some outdated comments in source code. Documented Gui Module in docu. 2015-06-06 20:10:10 +02:00
t-moe
ef467d0fee Merge remote-tracking branch 'origin/dev_aaron' into emulator 2015-06-06 19:07:10 +02:00
t-moe
fb652e3670 Updated docu: Added links to online doxygen docu. Added some description to app module doc. 2015-06-06 19:01:30 +02:00
id101010
a04cda9fc2 Refactured comments and implemented a bugfix for the PID controller 2015-06-06 18:51:57 +02:00
id101010
8c264c237a Comment refactoring, updated PID values 2015-06-06 18:19:28 +02:00
t-moe
6db62a6b50 Completed Docu for Pixy&Usb. Started with new table structure for other parts. 2015-06-06 18:09:33 +02:00
id101010
e018a75cd3 Implemented basic pi and pid controller 2015-06-02 16:25:45 +02:00
id101010
7ad16797ab Merge remote-tracking branch 'origin/emulator' into dev_aaron 2015-06-01 21:34:32 +02:00
24 changed files with 300 additions and 177 deletions

73
common/app/pixy_control.c Normal file
View File

@@ -0,0 +1,73 @@
/*
* 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)
void int_init(void){
// TODO Init ports and outputs if needed.
}
// 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;
}

14
common/app/pixy_control.h Normal file
View File

@@ -0,0 +1,14 @@
/*
* pixy_control.h
*/
#ifndef _CONTROL_H_
#define _CONTROL_H_
#include<stdint.h>
void int_init(void);
int16_t pixy_PID_Y(int16_t x, int16_t w);
int16_t pixy_PID_X(int16_t x, int16_t w);
#endif

View File

@@ -1,4 +1,5 @@
#include "screen_tracking.h" #include "screen_tracking.h"
#include "pixy_control.h"
#include "button.h" #include "button.h"
#include "checkbox.h" #include "checkbox.h"
#include "tft.h" #include "tft.h"
@@ -80,12 +81,19 @@ typedef struct {
} TRACKING_CONFIG_STRUCT; } TRACKING_CONFIG_STRUCT;
//Methods for our tracking implementation ahead //Methods for our tracking implementation ahead
static int16_t servo_x = 0;
static int16_t servo_y = 0;
//Method/Callback to start our tracking //Method/Callback to start our tracking
void tracking_our_start(void* tracking_config) { void tracking_our_start(void* tracking_config) {
//Activate pixy's data send program //Activate pixy's data send program
int32_t response; int32_t response;
int return_value; 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); return_value = pixy_command("runprog", INT8(0), END_OUT_ARGS, &response, END_IN_ARGS);
} }
@@ -99,8 +107,31 @@ void tracking_our_stop(void* tracking_config) {
//Method/Callback to calculate one step of our tracking //Method/Callback to calculate one step of our tracking
void tracking_our_update(void* tracking_config, struct Block* blocks, int num_blocks) { void tracking_our_update(void* tracking_config, struct Block* blocks, int num_blocks) {
//TODO: Implement tracking!
//Calculate new servo pos and set the new servo pos 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 //Variable which stores all the callbacks and settings for our tracking implementation

View File

@@ -6,6 +6,10 @@
* This makes it safe to change the screen from an touch interrupt (e.g. button callback) * 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_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 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 static volatile SCREEN_STRUCT* screen_goto = NULL; //Screen we should navigate to once we enter the gui_screen_update() method again

View File

@@ -44,6 +44,7 @@ typedef struct SCREEN_S{
/** /**
* Navigate to the given screen as soon as the app enters the main loop again (and gui_screen_update() is called) * 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 * 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 * @param screen A Pointer to the preinitialized SCREEN_STRUCT
* @return true on success * @return true on success
*/ */

View File

@@ -12,7 +12,6 @@
/* Possible improvements: /* Possible improvements:
* Exchange pointer-list "areas" with a linked list. This would ensure that we can always accept new regions * Exchange pointer-list "areas" with a linked list. This would ensure that we can always accept new regions
* Implement calibration stuff, and calculate the real coordinates out of the data provided in touch_add_raw_event()
*/ */
#define NUM_AREAS 50 //Number of Touch Areas we can manage #define NUM_AREAS 50 //Number of Touch Areas we can manage

View File

@@ -273,7 +273,7 @@ static bool gpio_init()
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
// PORT_B init ------------------------------------------------------------------------------------- // PORT_B init
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
@@ -282,7 +282,7 @@ static bool gpio_init()
// configure PORT_B // configure PORT_B
GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_Init(GPIOB, &GPIO_InitStructure);
// PORT_D init ------------------------------------------------------------------------------------- // PORT_D init
GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC); // PD0=FSMC_D2 -> DB2 GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC); // PD0=FSMC_D2 -> DB2
GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FSMC); // PD1=FSMC_D3 -> DB3 GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FSMC); // PD1=FSMC_D3 -> DB3
GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_FSMC); // PD4=FSMC_NOE -> RD GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_FSMC); // PD4=FSMC_NOE -> RD
@@ -305,7 +305,7 @@ static bool gpio_init()
// configure PORT_D // configure PORT_D
GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_Init(GPIOD, &GPIO_InitStructure);
// PORT_E init -------------------------------------------------------------------------------------- // PORT_E init
GPIO_PinAFConfig(GPIOE, GPIO_PinSource3, GPIO_AF_FSMC); // PE3=FSMC_A19 -> RS GPIO_PinAFConfig(GPIOE, GPIO_PinSource3, GPIO_AF_FSMC); // PE3=FSMC_A19 -> RS
GPIO_PinAFConfig(GPIOE, GPIO_PinSource7, GPIO_AF_FSMC); // PE7=FSMC_D4 -> DB4 GPIO_PinAFConfig(GPIOE, GPIO_PinSource7, GPIO_AF_FSMC); // PE7=FSMC_D4 -> DB4
GPIO_PinAFConfig(GPIOE, GPIO_PinSource8, GPIO_AF_FSMC); // PE8=FSMC_D5 -> DB5 GPIO_PinAFConfig(GPIOE, GPIO_PinSource8, GPIO_AF_FSMC); // PE8=FSMC_D5 -> DB5
@@ -316,6 +316,7 @@ static bool gpio_init()
GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_FSMC); // PE13=FSMC_D10 -> DB12 GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_FSMC); // PE13=FSMC_D10 -> DB12
GPIO_PinAFConfig(GPIOE, GPIO_PinSource14, GPIO_AF_FSMC); // PE14=FSMC_D11 -> DB13 GPIO_PinAFConfig(GPIOE, GPIO_PinSource14, GPIO_AF_FSMC); // PE14=FSMC_D11 -> DB13
GPIO_PinAFConfig(GPIOE, GPIO_PinSource15, GPIO_AF_FSMC); // PE15=FSMC_D12 -> DB14 GPIO_PinAFConfig(GPIOE, GPIO_PinSource15, GPIO_AF_FSMC); // PE15=FSMC_D12 -> DB14
// PORT_E struct // PORT_E struct
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 |
GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 |
@@ -325,6 +326,7 @@ static bool gpio_init()
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
// configure PORT_E // configure PORT_E
GPIO_Init(GPIOE, &GPIO_InitStructure); GPIO_Init(GPIOE, &GPIO_InitStructure);
@@ -334,6 +336,8 @@ static bool gpio_init()
/* /*
* ---------------------- display control functions ------------------------------------------------------- * ---------------------- display control functions -------------------------------------------------------
*/ */
// Clear the whole screen by filling it with a specifig color
void ll_tft_clear(uint16_t color) void ll_tft_clear(uint16_t color)
{ {
uint32_t n = 0; uint32_t n = 0;
@@ -346,6 +350,7 @@ void ll_tft_clear(uint16_t color)
} }
} }
// Set the cursorposition
static void tft_set_cursor(uint16_t xpos, uint16_t ypos) static void tft_set_cursor(uint16_t xpos, uint16_t ypos)
{ {
// set cursor // set cursor
@@ -354,52 +359,59 @@ static void tft_set_cursor(uint16_t xpos, uint16_t ypos)
TFT_REG = TFT_SSD1289_REG_22; TFT_REG = TFT_SSD1289_REG_22;
} }
// Enable / Disable the backlight
static void tft_set_backlight(bool state) static void tft_set_backlight(bool state)
{ {
if(state){ if(state){ // if state is true
GPIOB->BSRRH = GPIO_Pin_0; GPIOB->BSRRH = GPIO_Pin_0; // set the backlight output
} else { } else { // else
GPIOB->BSRRL = GPIO_Pin_0; GPIOB->BSRRL = GPIO_Pin_0; // reset the backlight
} }
} }
// Port operations on the screen RS PIN
static void tft_reset(bool state) static void tft_reset(bool state)
{ {
if(state){ if(state){ // if state is ture
GPIOB->BSRRH = GPIO_Pin_0; GPIOB->BSRRH = GPIO_Pin_0; // Set the reset pin
} else { } else { // else
GPIOB->BSRRL = GPIO_Pin_0; GPIOB->BSRRL = GPIO_Pin_0; // reset the reset pin
} }
} }
// Send a single command to the display controller
static void tft_write_reg(uint8_t reg_adr, uint16_t reg_value) static void tft_write_reg(uint8_t reg_adr, uint16_t reg_value)
{ {
TFT_REG = reg_adr; TFT_REG = reg_adr; // set adress
TFT_RAM = reg_value; TFT_RAM = reg_value; // send command
} }
// Read a register value of the display controller
static uint16_t tft_read_reg(uint8_t reg_adr) static uint16_t tft_read_reg(uint8_t reg_adr)
{ {
TFT_REG = reg_adr; TFT_REG = reg_adr; // set adress
return TFT_RAM; return TFT_RAM; // return value
} }
// This sets a window for current draw functions
static void tft_set_window(uint16_t xstart, uint16_t ystart, uint16_t xend, uint16_t yend) static void tft_set_window(uint16_t xstart, uint16_t ystart, uint16_t xend, uint16_t yend)
{ {
uint16_t start,end; uint16_t start,end;
uint16_t ystart_end; uint16_t ystart_end;
start = (ystart & 0x00FF); start = (ystart & 0x00FF); // Start adress of the window
end = ((yend & 0x00FF) << 8); end = ((yend & 0x00FF) << 8); // End adress of the window
ystart_end = (start | end); ystart_end = (start | end); // Calculate y endpoint
tft_write_reg(TFT_SSD1289_REG_44, ystart_end); tft_write_reg(TFT_SSD1289_REG_44, ystart_end); // Send y size
tft_write_reg(TFT_SSD1289_REG_45, 319-xend); tft_write_reg(TFT_SSD1289_REG_45, 319-xend); // Send x start
tft_write_reg(TFT_SSD1289_REG_46, 319-xstart); tft_write_reg(TFT_SSD1289_REG_46, 319-xstart); // Send x end
} }
// Reset a Window
void tft_reset_window() void tft_reset_window()
{ {
// Commands according to the datasheet
tft_write_reg(0x44, 239 << 8); tft_write_reg(0x44, 239 << 8);
tft_write_reg(0x45, 0); tft_write_reg(0x45, 0);
tft_write_reg(0x46, 319); tft_write_reg(0x46, 319);
@@ -409,6 +421,7 @@ void tft_reset_window()
* ---------------------- draw functions ----------------------------------------------------------- * ---------------------- draw functions -----------------------------------------------------------
*/ */
// Draw a line on the given coordinates
void ll_tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) void ll_tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{ {
if(abs(x2-x1) > abs(y2-y1)) //line has more distance in x than y => iterate over x distance if(abs(x2-x1) > abs(y2-y1)) //line has more distance in x than y => iterate over x distance
@@ -462,12 +475,14 @@ void ll_tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16
} }
} }
// Draw a single pixel on (x,y) with the given color
void ll_tft_draw_pixel(uint16_t x,uint16_t y,uint16_t color) void ll_tft_draw_pixel(uint16_t x,uint16_t y,uint16_t color)
{ {
tft_set_cursor(x,y); tft_set_cursor(x,y); // Set the cursor position
TFT_RAM = color; TFT_RAM = color; // Draw the pixel
} }
// Draw a rectangle at the given coordinates with the given color
void ll_tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) void ll_tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{ {
unsigned int tmp; unsigned int tmp;
@@ -508,6 +523,7 @@ void ll_tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, u
} }
// Draw a filled rectangle at the given coordinates with the given color
void ll_tft_fill_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)
{ {
uint16_t area; uint16_t area;

Binary file not shown.

Binary file not shown.

BIN
doc/analyse_touch.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

BIN
doc/datasheet_ssd1289.pdf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
doc/idpa_software.tar.gz Normal file

Binary file not shown.

BIN
doc/screenshot_emulator.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

View File

@@ -7,51 +7,53 @@ extern "C" {
#include <QFileInfoList> #include <QFileInfoList>
#include <QDateTime> #include <QDateTime>
QDir rootdir ("./emulated"); QDir rootdir ("./emulated"); //Create a QDir which points to the "root" of the emulated filesystem
bool ll_filesystem_init() { bool ll_filesystem_init() {
if(!rootdir.exists()) { if(!rootdir.exists()) { //if our root dir is nonexistent
qWarning() << "Filesystem can not be emulated because the 'emulated' folder does not exist"; qWarning() << "Filesystem can not be emulated because the 'emulated' folder does not exist";
return false; return false; //mark an error
} }
return true; return true;
} }
DIRECTORY_STRUCT* ll_filesystem_dir_open(const char* path) { DIRECTORY_STRUCT* ll_filesystem_dir_open(const char* path) {
QDir d(rootdir); QDir d(rootdir); //Make a copy of the rootdir QDir instance
d.cd(path); d.cd(path); //Change the directory to the passed path
if(!d.exists()) { if(!d.exists()) {
return NULL; return NULL; //mark an error
} }
DIRECTORY_STRUCT* directory = new DIRECTORY_STRUCT(); DIRECTORY_STRUCT* directory = new DIRECTORY_STRUCT();
//get all files and directories which are important to us. Filter out . and .. symlinks (linux)
QFileInfoList entries = d.entryInfoList(QDir::NoDotAndDotDot|QDir::Files|QDir::Dirs|QDir::Readable|QDir::Writable|QDir::Hidden|QDir::System); QFileInfoList entries = d.entryInfoList(QDir::NoDotAndDotDot|QDir::Files|QDir::Dirs|QDir::Readable|QDir::Writable|QDir::Hidden|QDir::System);
//Fill the directory structure for the user
directory->path = path; directory->path = path;
directory->num_files = entries.count(); directory->num_files = entries.count();
directory->files = new FILE_STRUCT[directory->num_files]; directory->files = new FILE_STRUCT[directory->num_files]; //allocate array of file structs
for(int i=0; i<entries.count(); i++){ //foreach file that we found
for(int i=0; i<entries.count(); i++){
QFileInfo fi = entries.at(i); QFileInfo fi = entries.at(i);
FILE_STRUCT* entry = &(directory->files[i]); FILE_STRUCT* entry = &(directory->files[i]); //get the pointer to the current filestruct (which should be filled)
entry->fattrib = 0; entry->fattrib = 0;
entry->fname = new char[fi.fileName().length()+1]; entry->fname = new char[fi.fileName().length()+1]; //reserve memory for filename
strcpy(entry->fname,fi.fileName().toStdString().c_str()); strcpy(entry->fname,fi.fileName().toStdString().c_str()); //copy filename into struct
if(fi.isDir()) { if(fi.isDir()) { //it's a direcory
entry->fattrib|=F_DIR; entry->fattrib|=F_DIR; //set directory attribute
entry->fsize = 0; entry->fsize = 0;
} else { } else { //it's a file
entry->fsize = fi.size(); entry->fsize = fi.size(); //set filesize
} }
if(fi.isHidden()) { if(fi.isHidden()) { //the file is hidden
entry->fattrib|=F_HID; entry->fattrib|=F_HID;
} }
if(!fi.isWritable()) { if(!fi.isWritable()) { //the file is not writable
entry->fattrib|=F_RDO; entry->fattrib|=F_RDO; //set readonly attribue
} }
//Set date & time of file in structure
QDateTime dt = fi.lastModified(); QDateTime dt = fi.lastModified();
entry->fdate.year = dt.date().year()-1980; entry->fdate.year = dt.date().year()-1980; //year is realtive to 1980
entry->fdate.month = dt.date().month(); entry->fdate.month = dt.date().month();
entry->fdate.day = dt.date().day(); entry->fdate.day = dt.date().day();
entry->ftime.hour = dt.time().hour(); entry->ftime.hour = dt.time().hour();
@@ -60,22 +62,22 @@ DIRECTORY_STRUCT* ll_filesystem_dir_open(const char* path) {
} }
return directory; return directory; //return filled directory struct
} }
void ll_filesystem_dir_close(DIRECTORY_STRUCT* dir) { void ll_filesystem_dir_close(DIRECTORY_STRUCT* dir) {
if(dir!=NULL) { if(dir!=NULL) { //passed handle is valid
for(int i=0; i<dir->num_files; i++) { for(int i=0; i<dir->num_files; i++) { //foreach file
delete dir->files[i].fname; delete dir->files[i].fname; //delete filename buffer
} }
delete[] dir->files; delete[] dir->files; //delete file array
delete dir; delete dir; //delete structure itself
} }
} }
//Struct that represents a file handle for the emulator
struct QT_FILE_HANDLE : FILE_HANDLE { struct QT_FILE_HANDLE : FILE_HANDLE { //..derived from the FILE_HANDLE (of the Filesystem modul)
QFile* file; QFile* file; //Pointer to the open QFile* instance
}; };
@@ -83,17 +85,19 @@ FILE_HANDLE* ll_filesystem_file_open(const char* filename) {
if(!rootdir.exists()) { if(!rootdir.exists()) {
return NULL; return NULL;
} }
QString filepath = rootdir.absoluteFilePath(filename); QString filepath = rootdir.absoluteFilePath(filename); //get the absolute path to the requested file
QFile* f = new QFile(filepath); QFile* f = new QFile(filepath); //create a QFile instance to the requested file
if(!f->exists()) { if(!f->exists()) { //File does not exist
return NULL; return NULL; //mark error
} }
if(!f->open(QFile::ReadWrite)) { if(!f->open(QFile::ReadWrite)) { //try to open the file, it it fails then ...
return NULL; return NULL; //... mark error
} }
QT_FILE_HANDLE* fh = new QT_FILE_HANDLE(); //At this point we have a valid QFile instance, pointing to an existing file
QT_FILE_HANDLE* fh = new QT_FILE_HANDLE(); //Create Structure to return to user
fh->file = f; fh->file = f;
fh->fname = filename; fh->fname = filename;
fh->fpos =0; fh->fpos =0;
@@ -102,12 +106,13 @@ FILE_HANDLE* ll_filesystem_file_open(const char* filename) {
} }
void ll_filesystem_file_close(FILE_HANDLE* handle) { void ll_filesystem_file_close(FILE_HANDLE* handle) {
if(handle!=NULL) { if(handle!=NULL) { //passed handle is valid
QT_FILE_HANDLE* fh = static_cast<QT_FILE_HANDLE*>(handle); QT_FILE_HANDLE* fh = static_cast<QT_FILE_HANDLE*>(handle); //cast pointer to QT_FILE_HANDLE
if(fh->file->isOpen()) { if(fh->file->isOpen()) { //if the file is still open
fh->file->close(); fh->file->close(); //close the file
} }
delete fh; delete fh->file; //delete QFile instance
delete fh; //delete the fle
} }
} }
@@ -115,18 +120,18 @@ FILE_STATUS ll_filesystem_file_seek(FILE_HANDLE* handle, uint32_t offset) {
if(handle==NULL) { if(handle==NULL) {
return F_INVALIDPARAM; return F_INVALIDPARAM;
} }
QT_FILE_HANDLE* fh = static_cast<QT_FILE_HANDLE*>(handle); QT_FILE_HANDLE* fh = static_cast<QT_FILE_HANDLE*>(handle); //cast pointer to QT_FILE_HANDLE
if(!fh->file->isOpen()) { if(!fh->file->isOpen()) { //file is not open
return F_DISKERROR; return F_DISKERROR;
} }
if(offset>=fh->file->size()) { if(offset>=fh->file->size()) { //offset exeeds filesize
return F_INVALIDPARAM; return F_INVALIDPARAM;
} }
if(fh->file->seek(offset)) { if(fh->file->seek(offset)) { //try to seek to desired offset
fh->fpos = offset; fh->fpos = offset; //update offset in FILE_HANDLE (for user)
return F_OK; return F_OK;
} else { } else { //seek failed
return F_DISKERROR; return F_DISKERROR;
} }
} }
@@ -135,20 +140,20 @@ FILE_STATUS ll_filesystem_file_read(FILE_HANDLE* handle, uint8_t* buf, uint32_t
if(handle==NULL || buf==NULL) { if(handle==NULL || buf==NULL) {
return F_INVALIDPARAM; return F_INVALIDPARAM;
} }
QT_FILE_HANDLE* fh = static_cast<QT_FILE_HANDLE*>(handle); QT_FILE_HANDLE* fh = static_cast<QT_FILE_HANDLE*>(handle); //cast pointer to QT_FILE_HANDLE
if(!fh->file->isOpen()) { if(!fh->file->isOpen()) { //file is not open
return F_DISKERROR; return F_DISKERROR;
} }
if(!fh->file->isReadable()) { if(!fh->file->isReadable()) { //file is not readable
return F_EACCESS; return F_EACCESS;
} }
qint64 bytesRead = fh->file->read((char*)buf,size); qint64 bytesRead = fh->file->read((char*)buf,size); //try to read desired amount of bytes
if(bytesRead<0) { if(bytesRead<0) { //read failed
return F_DISKERROR; return F_DISKERROR;
} }
fh->fpos+=bytesRead; fh->fpos+=bytesRead; //increase file position (for user)
if(bytesRead!=size) { if(bytesRead!=size) { //we got less bytes than expected
return F_EOF; return F_EOF; //we reached the end of the file
} else { } else {
return F_OK; return F_OK;
} }
@@ -158,24 +163,22 @@ FILE_STATUS ll_filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t
if(handle==NULL) { if(handle==NULL) {
return F_INVALIDPARAM; return F_INVALIDPARAM;
} }
QT_FILE_HANDLE* fh = static_cast<QT_FILE_HANDLE*>(handle); QT_FILE_HANDLE* fh = static_cast<QT_FILE_HANDLE*>(handle); //cast pointer to QT_FILE_HANDLE
if(!fh->file->isOpen()) { if(!fh->file->isOpen()) { //file is not open
return F_DISKERROR; return F_DISKERROR;
} }
if(!fh->file->isWritable()) { if(!fh->file->isWritable()) { //file is not writable
return F_EACCESS; return F_EACCESS;
} }
qint64 bytesWritten = fh->file->write((char*)buf,size); qint64 bytesWritten = fh->file->write((char*)buf,size); //try to write desired amount of bytes
if(bytesWritten<0) { if(bytesWritten<0) { //write failed
return F_DISKERROR; return F_DISKERROR;
} }
fh->fpos+=bytesWritten; fh->fpos+=bytesWritten; //increase file position (for user)
if(bytesWritten!=size) { if(bytesWritten!=size) { //we wrote less bytes than expected
return F_EOF; return F_EOF; //we reached the end of the file
} else { } else {
return F_OK; return F_OK;
} }
} }

View File

@@ -6,18 +6,18 @@ extern "C" {
} }
bool ll_system_init() { bool ll_system_init() {
return true; return true; //nothing to initialize here, apart from the stuff which is done in the main method.
} }
void ll_system_delay(uint32_t msec) { void ll_system_delay(uint32_t msec) {
QThread::msleep(msec); QThread::msleep(msec); //Let the app_process() Thread sleep
} }
void ll_system_process() { void ll_system_process() {
QApplication::processEvents(); QApplication::processEvents(); //Process pending qt events
QThread::msleep(1); QThread::msleep(1); //Sleep for 1ms, to keep the cpu load down
} }
void ll_system_toggle_led() { void ll_system_toggle_led() {
//No led emulated :(
} }

View File

@@ -1,5 +1,4 @@
#include "mainwindow.h" #include "mainwindow.h"
#include <QDebug>
extern "C" { extern "C" {
#include "ll_tft.h" #include "ll_tft.h"
@@ -8,13 +7,14 @@ extern "C" {
MainWindow* mainwindow; MainWindow* mainwindow;
bool ll_tft_init() { bool ll_tft_init() {
qDebug() << "tft init done"; mainwindow = new MainWindow(); //create the designed window
mainwindow = new MainWindow(); mainwindow->show(); //open it (non blocking)
mainwindow->show();
return true; return true;
} }
//the following functions redirect the call to the mainwindow, to a function with the same signature
void ll_tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { void ll_tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) {
mainwindow->draw_line(x1,y1,x2,y2,color); mainwindow->draw_line(x1,y1,x2,y2,color);
} }
@@ -44,9 +44,11 @@ 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_num_fonts() {
return 2; return 2; //we have two fonts (see below)
} }
//Helper function to get the QFont to the corresponding font number
//Note: only return monospaced fonts!!!
QFont get_font(uint8_t fontnum) { QFont get_font(uint8_t fontnum) {
switch(fontnum) { switch(fontnum) {
case 0: case 0:
@@ -62,20 +64,20 @@ QFont get_font(uint8_t fontnum) {
uint8_t ll_tft_font_height(uint8_t fontnum) { uint8_t ll_tft_font_height(uint8_t fontnum) {
QFont f = get_font(fontnum); QFont f = get_font(fontnum);
if(f == QFont()) return -1; if(f == QFont()) return -1;
QFontMetrics m(f); QFontMetrics m(f); //use font metcris object to calculate height of font
return m.height(); return m.height();
} }
uint8_t ll_tft_font_width(uint8_t fontnum) { uint8_t ll_tft_font_width(uint8_t fontnum) {
QFont f = get_font(fontnum); QFont f = get_font(fontnum);
if(f == QFont()) return -1; if(f == QFont()) return -1;
QFontMetrics m(f); QFontMetrics m(f); //use font metcris object to calculate width of font
return m.averageCharWidth(); return m.averageCharWidth();
} }
void ll_tft_draw_char(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, char c) { void ll_tft_draw_char(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, char c) {
QFont f = get_font(font); QFont f = get_font(font);
if(f == QFont()) return; if(f == QFont()) return; //if the font is the default-font, we want to abort.
mainwindow->draw_char(x,y,color,bgcolor,f,c); mainwindow->draw_char(x,y,color,bgcolor,f,c);
} }

View File

@@ -2,23 +2,23 @@
#include <QtConcurrent/QtConcurrent> #include <QtConcurrent/QtConcurrent>
extern "C" { extern "C" {
//C Functions from the common folder //Imported C Functions from the common folder
void app_init(); //Initializes the app void app_init(); //Initializes the app
void app_process(); //Processes one eventloop of the app void app_process(); //Processes one eventloop of the app
} }
void app_loop() { void app_loop() {
while(!QApplication::closingDown()) { while(!QApplication::closingDown()) { //as long as the application is not terminating
app_process(); app_process(); //let the application process it's events
} }
} }
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
QApplication app(argc,argv); QApplication app(argc,argv); //Process qt-specific commandline arguments and create event loop
app_init(); app_init(); //Let the application initialize it self
QtConcurrent::run(&app_loop); QtConcurrent::run(&app_loop); //Start a thread that executes app_loop
return app.exec(); return app.exec(); //Run the event loop until the last window is closed.
} }

View File

@@ -13,16 +13,18 @@ extern "C" {
#define DISPLAY_WIDTH 320 #define DISPLAY_WIDTH 320
#define DISPLAY_HEIGHT 240 #define DISPLAY_HEIGHT 240
//function to calculate QColor out of a RGB565 16bit color
QColor QColorFromRGB565(uint16_t color) { QColor QColorFromRGB565(uint16_t color) {
//interpolate colors
int R8 = (int) floor( (color>>(5+6)) * 255.0 / 31.0 + 0.5); int R8 = (int) floor( (color>>(5+6)) * 255.0 / 31.0 + 0.5);
int G8 = (int) floor( ((color>>5)&0x3F) * 255.0 / 63.0 + 0.5); int G8 = (int) floor( ((color>>5)&0x3F) * 255.0 / 63.0 + 0.5);
int B8 = (int) floor( (color&0x1F) * 255.0 / 31.0 + 0.5); int B8 = (int) floor( (color&0x1F) * 255.0 / 31.0 + 0.5);
return QColor::fromRgb(R8,G8,B8); return QColor::fromRgb(R8,G8,B8);
} }
//function to calculate QRgb out of a RGB565 16bit color
QRgb QRgbFromRGB565(uint16_t color) { QRgb QRgbFromRGB565(uint16_t color) {
//interpolate colors
int R8 = (int) floor( (color>>(5+6)) * 255.0 / 31.0 + 0.5); int R8 = (int) floor( (color>>(5+6)) * 255.0 / 31.0 + 0.5);
int G8 = (int) floor( ((color>>5)&0x3F) * 255.0 / 63.0 + 0.5); int G8 = (int) floor( ((color>>5)&0x3F) * 255.0 / 63.0 + 0.5);
int B8 = (int) floor( (color&0x1F) * 255.0 / 31.0 + 0.5); int B8 = (int) floor( (color&0x1F) * 255.0 / 31.0 + 0.5);
@@ -32,156 +34,137 @@ QRgb QRgbFromRGB565(uint16_t color) {
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), image(DISPLAY_WIDTH,DISPLAY_HEIGHT, QImage::Format_RGB16), ui(new Ui::MainWindow){ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), image(DISPLAY_WIDTH,DISPLAY_HEIGHT, QImage::Format_RGB16), ui(new Ui::MainWindow){
ui->setupUi(this); ui->setupUi(this);
image.fill(Qt::black); image.fill(Qt::black); //clear display buffer
currentScale = 1; currentScale = 1; //start with scale factor 1
ui->widgetDisplay->setMouseTracking(true); ui->widgetDisplay->setMouseTracking(true); //enable mouse move events, even when mouse is not pressed
ui->widgetDisplay->installEventFilter(this); ui->widgetDisplay->installEventFilter(this); //install event filter for "display" widget, so that we receive those events as well
} }
void MainWindow::draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) void MainWindow::draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{ {
//render_mutex.lock();
QPainter painter(&(image)); QPainter painter(&(image));
painter.setPen(QColorFromRGB565(color)); painter.setPen(QColorFromRGB565(color));
painter.drawLine(x1,y1,x2,y2); painter.drawLine(x1,y1,x2,y2);
//render_mutex.unlock();
update(); update();
} }
void MainWindow::draw_pixel(uint16_t x, uint16_t y, uint16_t color) void MainWindow::draw_pixel(uint16_t x, uint16_t y, uint16_t color)
{ {
//render_mutex.lock();
image.setPixel(x,y,QRgbFromRGB565(color)); image.setPixel(x,y,QRgbFromRGB565(color));
//render_mutex.unlock();
update(); update();
} }
void MainWindow::clear(uint16_t color) void MainWindow::clear(uint16_t color)
{ {
//render_mutex.lock();
image.fill(QColorFromRGB565(color)); image.fill(QColorFromRGB565(color));
//render_mutex.unlock();
update(); update();
} }
void MainWindow::draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) void MainWindow::draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{ {
//render_mutex.lock();
QPainter painter(&(image)); QPainter painter(&(image));
painter.setPen(QColorFromRGB565(color)); painter.setPen(QColorFromRGB565(color));
painter.drawRect(qMin(x1,x2),qMin(y1,y2),abs((int)x2-(int)x1)+1,abs((int)y2-(int)y1)+1); painter.drawRect(qMin(x1,x2),qMin(y1,y2),abs((int)x2-(int)x1),abs((int)y2-(int)y1));
//render_mutex.unlock();
update(); update();
} }
void MainWindow::fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) void MainWindow::fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{ {
//render_mutex.lock();
QPainter painter(&(image)); QPainter painter(&(image));
painter.fillRect(qMin(x1,x2),qMin(y1,y2),abs((int)x2-(int)x1)+1,abs((int)y2-(int)y1)+1,QColorFromRGB565(color)); painter.fillRect(qMin(x1,x2),qMin(y1,y2),abs((int)x2-(int)x1)+1,abs((int)y2-(int)y1)+1,QColorFromRGB565(color));
//render_mutex.unlock();
update(); update();
} }
void MainWindow::draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t *dat) void MainWindow::draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t *dat)
{ {
//Creating a new image and access it directly is faster than setPixel //Creating a new image and access it directly is faster than setPixel
QImage img(width,height,QImage::Format_RGB32); QImage img(width,height,QImage::Format_RGB32); //create a new image
for(int yi=0; yi<height; yi++) { for(int yi=0; yi<height; yi++) { //for each line
uint32_t* line = (uint32_t*)img.scanLine(yi); uint32_t* line = (uint32_t*)img.scanLine(yi); //get the pointer to the imagedata of the current line
for(int xi=0; xi<width; xi++) { for(int xi=0; xi<width; xi++) { //for each column
*line++=QRgbFromRGB565(dat[yi*width+xi]); *line++=QRgbFromRGB565(dat[yi*width+xi]); //set pixel
} }
} }
//render_mutex.lock();
QPainter p(&image); QPainter p(&image);
p.drawImage(x,y,img); p.drawImage(x,y,img); //draw created image
//render_mutex.unlock();
update(); update();
} }
void MainWindow::draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color) void MainWindow::draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color)
{ {
//render_mutex.lock();
QPainter painter(&(image)); QPainter painter(&(image));
painter.setPen(QColorFromRGB565(color)); painter.setPen(QColorFromRGB565(color));
painter.drawEllipse(QPoint(x,y), r, r); painter.drawEllipse(QPoint(x,y), r, r);
//render_mutex.unlock();
update(); update();
} }
void MainWindow::draw_char(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, QFont font, char c) void MainWindow::draw_char(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, QFont font, char c)
{ {
//render_mutex.lock();
QPainter painter(&(image)); QPainter painter(&(image));
painter.setFont(font); painter.setFont(font);
if(bgcolor!=TRANSPARENT) { if(bgcolor!=TRANSPARENT) { //background color is not transparent
painter.setBackgroundMode(Qt::OpaqueMode); painter.setBackgroundMode(Qt::OpaqueMode);
painter.setBackground(QColorFromRGB565(bgcolor)); painter.setBackground(QColorFromRGB565(bgcolor)); //set text background
} }
painter.setPen(QColorFromRGB565(color)); painter.setPen(QColorFromRGB565(color)); //set fontcolor
y+=QFontMetrics(font).ascent(); //use y pos as highest point of char, instead of baseline y+=QFontMetrics(font).ascent(); //use y pos as highest point of char, instead of baseline
painter.drawText(QPoint(x,y), QString(QChar(c))); painter.drawText(QPoint(x,y), QString(QChar(c))); //draw char
//render_mutex.unlock();
update(); update();
} }
void MainWindow::paintEvent(QPaintEvent *) void MainWindow::paintEvent(QPaintEvent *)
{ {
//render_mutex.lock(); //this method is called whenever the window needs to be redrawn (or after update() is called)
QPainter painter(this); QPainter painter(this);
//Create a QRectF which represents the rectangle to draw the buffered image to
QRectF imgRect (ui->widgetDisplay->geometry().topLeft(),QSizeF(DISPLAY_WIDTH*currentScale,DISPLAY_HEIGHT*currentScale)); QRectF imgRect (ui->widgetDisplay->geometry().topLeft(),QSizeF(DISPLAY_WIDTH*currentScale,DISPLAY_HEIGHT*currentScale));
painter.drawImage(imgRect,image); painter.drawImage(imgRect,image); //draw buffer
painter.setPen(QPen(Qt::green,2)); painter.setPen(QPen(Qt::green,2)); //set border color
painter.drawRect(imgRect.adjusted(-1,-1,1,1)); painter.drawRect(imgRect.adjusted(-1,-1,1,1)); //draw border
//render_mutex.unlock();
} }
void MainWindow::mousePressEvent(QMouseEvent *evt) void MainWindow::mousePressEvent(QMouseEvent *evt)
{ {
//qDebug() << "down" << evt->pos(); //the mouse was pressed
checkAndSendEvent(evt->pos(),true); checkAndSendEvent(evt->pos(),true);
} }
void MainWindow::mouseReleaseEvent(QMouseEvent *evt) void MainWindow::mouseReleaseEvent(QMouseEvent *evt)
{ {
//qDebug() << "up" << evt->pos(); //the mouse was released
checkAndSendEvent(evt->pos(),false); checkAndSendEvent(evt->pos(),false);
} }
void MainWindow::mouseMoveEvent(QMouseEvent *evt) void MainWindow::mouseMoveEvent(QMouseEvent *evt)
{ {
//qDebug() << "move" << evt->pos(); //the mouse was released
checkAndSendEvent(evt->pos(),true); checkAndSendEvent(evt->pos(),true);
} }
bool MainWindow::eventFilter(QObject *obj, QEvent *evt) bool MainWindow::eventFilter(QObject *obj, QEvent *evt)
{ {
if(obj==ui->widgetDisplay) { if(obj==ui->widgetDisplay) { //we received a redirect event from the target rectangle
switch(evt->type()) { switch(evt->type()) {
case QEvent::MouseMove: case QEvent::MouseMove: //it's a mouse move event
{ {
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(evt); QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(evt); //get mouse event
QPoint p = (mouseEvent->pos()-QPoint(1,1))/currentScale; QPoint p = (mouseEvent->pos()-QPoint(1,1))/currentScale; //calculate correct corrdinates (undo scale)
if(p.x()<DISPLAY_WIDTH && p.y()<DISPLAY_HEIGHT) { if(p.x()<DISPLAY_WIDTH && p.y()<DISPLAY_HEIGHT) { //mouse position not out of bounds
//set mouse position text
ui->txtMousePos->setText(QString("Mouse Position: (%1,%2)").arg(p.x()).arg(p.y())); ui->txtMousePos->setText(QString("Mouse Position: (%1,%2)").arg(p.x()).arg(p.y()));
} }
} }
break; break;
default: break; default: break;
} }
} }
return false; return false;
} }
@@ -193,18 +176,16 @@ MainWindow::~MainWindow()
void MainWindow::checkAndSendEvent(QPoint pos, bool down) void MainWindow::checkAndSendEvent(QPoint pos, bool down)
{ {
QPoint p = pos - ui->widgetDisplay->geometry().topLeft(); QPoint p = pos - ui->widgetDisplay->geometry().topLeft(); //make coordinate relative to target area (0,0)
p/=currentScale; p/=currentScale; //undo scaling
if(p.x()<0 || p.y()<0 || p.x() >= DISPLAY_WIDTH || p.y() >= DISPLAY_HEIGHT) return; if(p.x()<0 || p.y()<0 || p.x() >= DISPLAY_WIDTH || p.y() >= DISPLAY_HEIGHT) return; //abort if out of bounds
//qDebug() << down << p; touch_add_raw_event(p.x(),p.y(),down?TOUCH_DOWN:TOUCH_UP); //submit touch event to touch module (common)
touch_add_raw_event(p.x(),p.y(),down?TOUCH_DOWN:TOUCH_UP);
} }
void MainWindow::on_cboZoom_currentIndexChanged(int index) void MainWindow::on_cboZoom_currentIndexChanged(int index)
{ {
currentScale=index+1; currentScale=index+1; //zoom factor 1 is the 0th entry, zoom factor 2 is the 1st entry, zoom factor 3 is the 2nd entry
update(); update(); //force redraw
} }

View File

@@ -33,12 +33,11 @@ protected:
~MainWindow(); ~MainWindow();
private slots: private slots:
void on_cboZoom_currentIndexChanged(int index); void on_cboZoom_currentIndexChanged(int index); //slot that is called when the zoomlevel changed
private: private:
//QMutex render_mutex; QImage image; //Display buffer
QImage image; int currentScale; //current scale factor
int currentScale;
void checkAndSendEvent(QPoint pos, bool down); void checkAndSendEvent(QPoint pos, bool down);
Ui::MainWindow *ui; Ui::MainWindow *ui;