====== 12. Cvičení: Práce na projektu ======
Obsahem cvičení je samostatná práce na projektu a konzultace (projektu, témat z přednášek...).
Studenti z probíhajícího cvičení mají přednostní přístup k deskám.
===== Ukázková kód použití otočných voličů =====
Výhoda následujícího použití informace změně polohy otočných voličů:
* polohu objektu si nastavíte v nezávislé proměnné např. xx, yy
* při načtení informace si vypočtete změnu otočných voličů (absolutní hodnota změny bude menší než 127)
* můžete udělat pohyb citlivější, než je změna hodnoty voliče (zde xx+=diff_red/2;)
* můžete jednoduše kontrolovat správnost polohy objektu korekcí proměnných xx a yy
#include
#include
#include
#include
#include
#include //termios, TCSANOW, ECHO, ICANON
#include "mzapo_parlcd.h"
#include "mzapo_phys.h"
#include "mzapo_regs.h"
#include "kote.c"
unsigned short *fb;
void draw_pixel(int x, int y, unsigned short int color) {
if (color!=65535) {
fb[(x%480)+480*(y%320)] = color;
}
}
int main(int argc, char *argv[]) {
unsigned char *parlcd_mem_base, *mem_base;
int i,j, ptr;
fb = (unsigned short *)malloc(320*480*2);
printf("Hello world\n");
parlcd_mem_base = map_phys_address(PARLCD_REG_BASE_PHYS, PARLCD_REG_SIZE, 0);
if (parlcd_mem_base == NULL)
exit(1);
mem_base = map_phys_address(SPILED_REG_BASE_PHYS, SPILED_REG_SIZE, 0);
if (mem_base == NULL)
exit(1);
parlcd_hx8357_init(parlcd_mem_base);
struct timespec loop_delay;
loop_delay.tv_sec = 0;
loop_delay.tv_nsec = 150 * 1000 * 1000;
int xx=240, yy=160;
uint32_t r = *(volatile uint32_t*)(mem_base + SPILED_REG_KNOBS_8BIT_o);
int last_red = ((r>>16)&0xff);
int last_blue = (r&0xff);
while (1) {
r = *(volatile uint32_t*)(mem_base + SPILED_REG_KNOBS_8BIT_o);
if ((r&0x7000000)!=0) {
break;
}
int red = ((r>>16)&0xff);
int blue = (r&0xff);
int diff_red = red - last_red;
last_red = red;
if (diff_red<-128) {
diff_red+=256;
}
if (diff_red>128) {
diff_red-=256;
}
xx+=diff_red/2;
if (xx<0) {
xx=0;
}
if (xx>350) {
xx=350;
}
int diff_blue = blue - last_blue;
last_blue = blue;
if (diff_blue<-128) {
diff_blue+=256;
}
if (diff_blue>128) {
diff_blue-=256;
}
yy+=diff_blue/2;
if (yy<0) {
yy=0;
}
if (yy>240) {
yy=240;
}
printf("xx %i Diff red %i (%i) yy %i diff blue %i (%i)\n", xx, diff_red, red, yy, diff_blue, blue);
for (ptr = 0; ptr < 320*480 ; ptr++) {
fb[ptr]=0u;
}
for (j=0; j
===== Ukázková kód použití vláken =====
* Ukázkový kód využívající posix threads pro vícevláknovou aplikaci. Ukazuje možné rozdělení projektu do vláken
* ''main'' - hlavní vlákno
* ''input_thread'' - vstupní vlákno
* ''output_thread'' - výstupní vlákno
* V tomto případě je vykreslování na LCD realizováno kontinuelně a ne on-demand. Variant řešení je samozřejmě více. Template si klade za cíl hlavně ukázat práci s posixovými vlákny.
*
#define _POSIX_C_SOURCE 200112L
#include
#include
#include
#include
#include
#include
#include
#include "mzapo_parlcd.h"
#include "mzapo_phys.h"
#include "mzapo_regs.h"
#include "serialize_lock.h"
#define IMG_SIZE 320*480
//type definition of struct for shared data between threads
typedef struct {
bool quit;
unsigned char *parlcd_mem_base;
uint16_t * fb_read;
uint16_t * fb_write;
} data_t;
void * input_thread(void * data);
void * output_thread(void * data);
//mutexes for double buffering of frames
pthread_mutex_t mtx_fb;
int main(int argc, char *argv[])
{
// Serialize execution of applications
// Try to acquire lock the first
if (serialize_lock(1) <= 0) {
printf("System is occupied\n");
if (1) {
printf("Waiting\n");
// Wait till application holding lock releases it or exits
serialize_lock(0);
}
}
printf("Hello world\n");
//initialize the two frame buffers
uint16_t fb0[IMG_SIZE];
uint16_t fb1[IMG_SIZE];
//initialize the shared data
data_t shared_data;
shared_data.quit = false;
shared_data.fb_read = &fb0;
shared_data.fb_write = &fb1;
//map the memory
shared_data.parlcd_mem_base = map_phys_address(PARLCD_REG_BASE_PHYS, PARLCD_REG_SIZE, 0);
if (shared_data.parlcd_mem_base == NULL){
exit(1);
}
//prepare the threads
enum {INPUT, OUTPUT, NUM_THREADS};
const char *thread_names[] = {"input", "output"};
void* (*thread_functions[])(void *) = {input_thread, output_thread};
//initialize the threads and mutex
pthread_t threads[NUM_THREADS];
pthread_mutex_init(&mtx_fb, NULL);
//spawn the threads
for (int i = 0; i < NUM_THREADS; ++i){
int res = pthread_create(&threads[i], NULL, thread_functions[i], &shared_data);
fprintf(stdout, "INFO: Create thread '%s' %s\n", thread_names[i], (res == 0 ? "OK" : "FAIL") );
//TODO:correctly exit if some thread does not initialize
}
//main loop
uint16_t color = 0x0000;
while(!shared_data.quit){
//simulate some long calculations
usleep(10000);
//write the frame buffer
for (int i = 0; i < IMG_SIZE; i++) {
//write to the write buffer
shared_data.fb_write[i] = color;
}
color+=1;
//swap the buffers - first need to acquire the mutex for write read buffer
pthread_mutex_lock(&mtx_fb);
//..now swap them
uint16_t * tmp = shared_data.fb_read;
shared_data.fb_read = shared_data.fb_write;
shared_data.fb_write = tmp;
//..and unlock the read buffer for display
pthread_mutex_unlock(&mtx_fb);
}
shared_data.quit = true;
//joining the threads
for (int i = 0; i < NUM_THREADS; ++i) {
fprintf(stdout, "INFO: Call join to the thread %s\n", thread_names[i]);
int r = pthread_join(threads[i], NULL);
fprintf(stdout, "INFO: Joining the thread %s has been %s\n", thread_names[i], (r == 0 ? "OK" : "FAIL"));
}
printf("Goodbye world\n");
// Release the lock
serialize_unlock();
return 0;
}
//------------------------------------------------------------
void * input_thread(void * data){
data_t * shared_data = (data_t *) data;
while(!shared_data->quit){
//TODO: sample the input once in a while
char c = getchar();
if (c == 'q'){
shared_data->quit = true;
}
//sleep for some time
usleep(10000);
}
}
//------------------------------------------------------------
void * output_thread(void * data){
data_t * shared_data = (data_t *) data;
//initialize the display
parlcd_hx8357_init(shared_data->parlcd_mem_base);
uint16_t fb_p = NULL;
//draw in infinite loop
while(!shared_data->quit){
//lock the output frame buffer so no one can write into it
pthread_mutex_lock(&mtx_fb);
//reset the cursor
parlcd_write_cmd(shared_data->parlcd_mem_base, 0x2c);
//write the buffer
for (int i = 0; i < IMG_SIZE; ++i) {
parlcd_write_data(
shared_data->parlcd_mem_base, shared_data->fb_read[i]);
}
//unlock the buffer
pthread_mutex_unlock(&mtx_fb);
//sleep for some time
usleep(10000);
}
}