eac1ca22bd
NOTE: this commit does not introduce any change, ideally even the binary should be almost the same. I checked the disassembly by hand and there are only a few differences here and there, mostly the compiler decides to compile very close expressions slightly differently. I tried to run the new code on several targets to make sure and saw no difference. The major syntax changes of the new headers are as follows: - BF_{WR,SET,CLR} are now superpowerful and allows to set several fileds at once: BF_WR(reg, field1(value1), field2(value2), ...) - BF_CS (use like BF_WR) does a write to reg_CLR and then reg_SET instead of RMW - there is no more need for macros like BF_{WR_,SET,CLR}_V, since one can simply BF_WR with field_V(name) - the old BF_SETV macro has no trivial equivalent and is replaced with its its equivalent for BF_WR(reg_SET, ...) I also rename the register headers: "regs/regs-x.h" -> "regs/x.h" to avoid the redundant "regs". Final note: the registers were generated using the following command: ./headergen_v2 -g imx -o ../../firmware/target/arm/imx233/regs/ desc/regs-stmp3{600,700,780}.xml Change-Id: I7485e8b4315a0929a8edb63e7fa1edcaa54b1edc
274 lines
8.6 KiB
C
274 lines
8.6 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
*
|
|
* Copyright (C) 2013 by Lorenzo Miori
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "system.h"
|
|
#include "lcd.h"
|
|
#include "string.h"
|
|
#include "kernel.h"
|
|
#include "pinctrl-imx233.h"
|
|
#include "power-imx233.h"
|
|
#include "button-lradc-imx233.h"
|
|
#include "button-target.h"
|
|
|
|
#ifndef BOOTLOADER
|
|
#include "touchscreen.h"
|
|
#include "touchscreen-imx233.h"
|
|
#include "button.h"
|
|
#include "font.h"
|
|
#include "action.h"
|
|
#endif
|
|
|
|
struct imx233_button_lradc_mapping_t imx233_button_lradc_mapping[] =
|
|
{
|
|
{455, BUTTON_VOL_UP},
|
|
{900, BUTTON_VOL_DOWN},
|
|
{1410, BUTTON_BACK},
|
|
{1868, BUTTON_FF},
|
|
{2311, BUTTON_REW},
|
|
{2700, 0},
|
|
{3300, IMX233_BUTTON_LRADC_END},
|
|
};
|
|
|
|
#ifndef BOOTLOADER
|
|
static int last_x = 0;
|
|
static int last_y = 0;
|
|
static bool touching = false;
|
|
#endif /* BOOTLOADER */
|
|
|
|
#ifndef BOOTLOADER
|
|
|
|
/* Touchpad extra pin initialization
|
|
* Strange facts:
|
|
* 1. In the fully working sample I have, it seems that pins
|
|
* must be all set to low
|
|
* 2. In the other sample without LCD, it seems (by measurement) that
|
|
* not all the pins are set to low! Actually, I still need to see if
|
|
* touchpad works in this other sample.
|
|
*/
|
|
void touchpad_pin_setup(void)
|
|
{
|
|
/* TX+ */
|
|
imx233_pinctrl_acquire(0, 25, "touchpad X+ power low");
|
|
imx233_pinctrl_set_function(0, 25, PINCTRL_FUNCTION_GPIO);
|
|
imx233_pinctrl_set_drive(0, 25, PINCTRL_DRIVE_4mA);
|
|
imx233_pinctrl_enable_gpio(0, 25, true);
|
|
|
|
/* TY+ */
|
|
imx233_pinctrl_acquire(0, 26, "touchpad Y+ power high");
|
|
imx233_pinctrl_set_function(0, 26, PINCTRL_FUNCTION_GPIO);
|
|
imx233_pinctrl_set_drive(0, 26, PINCTRL_DRIVE_4mA);
|
|
imx233_pinctrl_enable_gpio(0, 26, true);
|
|
|
|
/* TY- */
|
|
imx233_pinctrl_acquire(1, 21, "touchpad Y- power low");
|
|
imx233_pinctrl_set_function(1, 21, PINCTRL_FUNCTION_GPIO);
|
|
imx233_pinctrl_set_drive(1, 21, PINCTRL_DRIVE_4mA);
|
|
imx233_pinctrl_enable_gpio(1, 21, true);
|
|
|
|
/* TX- */
|
|
imx233_pinctrl_acquire(3, 15, "touchpad X- power high");
|
|
imx233_pinctrl_set_function(3, 15, PINCTRL_FUNCTION_GPIO);
|
|
imx233_pinctrl_set_drive(3, 15, PINCTRL_DRIVE_4mA);
|
|
imx233_pinctrl_enable_gpio(3, 15, true);
|
|
|
|
}
|
|
#endif /* BOOTLOADER */
|
|
|
|
void button_init_device(void)
|
|
{
|
|
imx233_button_lradc_init();
|
|
#ifndef BOOTLOADER
|
|
touchpad_pin_setup();
|
|
/* Now that is powered up, proceed with touchpad initialization */
|
|
imx233_touchscreen_init();
|
|
imx233_touchscreen_enable(true);
|
|
#endif /* BOOTLOADER */
|
|
}
|
|
|
|
bool button_hold(void)
|
|
{
|
|
return imx233_button_lradc_hold();
|
|
}
|
|
|
|
/* X, Y, RadiusX, RadiusY */
|
|
#define TOUCH_UP 2400, 1050, 650, 250
|
|
#define TOUCH_DOWN 2057, 3320, 500, 350
|
|
#define TOUCH_LEFT 3581, 2297, 300, 350
|
|
#define TOUCH_RIGHT 1000, 2100, 400, 700
|
|
#define TOUCH_CENTER 2682, 2167, 335, 276
|
|
|
|
bool coord_in_radius(int x, int y, int cx, int cy, int rx, int ry)
|
|
{
|
|
return ((x >= cx - rx && x <= cx + rx) && (y >= cy - ry && y <= cy + ry));
|
|
}
|
|
|
|
int button_read_device(void)
|
|
{
|
|
int res = 0;
|
|
|
|
switch(imx233_power_read_pswitch())
|
|
{
|
|
case 1: res |= BUTTON_POWER; break;
|
|
case 3: res |= BUTTON_SELECT; break;
|
|
}
|
|
|
|
#ifndef BOOTLOADER
|
|
touching = imx233_touchscreen_get_touch(&last_x, &last_y);
|
|
if(touching)
|
|
{
|
|
if (coord_in_radius(last_x, last_y, TOUCH_LEFT))
|
|
{
|
|
res |= BUTTON_LEFT;
|
|
}
|
|
else if (coord_in_radius(last_x, last_y, TOUCH_RIGHT))
|
|
{
|
|
res |= BUTTON_RIGHT;
|
|
}
|
|
else if (coord_in_radius(last_x, last_y, TOUCH_DOWN))
|
|
{
|
|
res |= BUTTON_DOWN;
|
|
}
|
|
else if (coord_in_radius(last_x, last_y, TOUCH_UP))
|
|
{
|
|
res |= BUTTON_UP;
|
|
}
|
|
}
|
|
#endif /* BOOTLOADER */
|
|
return imx233_button_lradc_read(res);
|
|
}
|
|
|
|
#ifndef BOOTLOADER
|
|
|
|
#define MAX_ENTRIES 100
|
|
#define VIEWPORT_HEIGHT 100
|
|
#define VIEWPORT_WIDTH 100
|
|
#define MAX_X 3700
|
|
#define MAX_Y 3700
|
|
#define ADAPT_TO_VIEWPORT(cx, cy, rx, ry) ((float)(cx) / MAX_X) * VIEWPORT_WIDTH, \
|
|
((float)(cy) / MAX_Y) * VIEWPORT_HEIGHT, \
|
|
((float)(rx) / MAX_X) * VIEWPORT_WIDTH, \
|
|
((float)(ry) / MAX_Y) * VIEWPORT_HEIGHT
|
|
static void draw_calibration_rect(int cx, int cy, int rx, int ry)
|
|
{
|
|
if (coord_in_radius(last_x, last_y, cx, cy, rx, ry))
|
|
lcd_set_drawinfo(DRMODE_SOLID, LCD_RGBPACK(0xff, 0xff, 0xff), LCD_BLACK);
|
|
else
|
|
lcd_set_drawinfo(DRMODE_SOLID, LCD_RGBPACK(0xff, 0, 0), LCD_BLACK);
|
|
lcd_drawrect(ADAPT_TO_VIEWPORT(cx - rx, cy - ry, 2 * rx, 2 * ry));
|
|
}
|
|
|
|
bool button_debug_screen(void)
|
|
{
|
|
int last = 0;
|
|
struct point_t
|
|
{
|
|
int x;
|
|
int y;
|
|
};
|
|
struct point_t last_entries[MAX_ENTRIES];
|
|
struct viewport report_vp;
|
|
|
|
memset(&report_vp, 0, sizeof(report_vp));
|
|
report_vp.x = (LCD_WIDTH - VIEWPORT_WIDTH) / 2;
|
|
report_vp.y = (LCD_HEIGHT - VIEWPORT_HEIGHT) / 2;
|
|
report_vp.width = VIEWPORT_WIDTH;
|
|
report_vp.height = VIEWPORT_HEIGHT;
|
|
|
|
lcd_setfont(FONT_SYSFIXED);
|
|
lcd_clear_display();
|
|
|
|
while(1)
|
|
{
|
|
int button = get_action(CONTEXT_STD, HZ / 10);
|
|
switch(button)
|
|
{
|
|
case ACTION_STD_OK:
|
|
case ACTION_STD_MENU:
|
|
lcd_set_viewport(NULL);
|
|
lcd_setfont(FONT_UI);
|
|
lcd_clear_display();
|
|
return true;
|
|
case ACTION_STD_CANCEL:
|
|
lcd_set_viewport(NULL);
|
|
lcd_setfont(FONT_UI);
|
|
lcd_clear_display();
|
|
return false;
|
|
}
|
|
|
|
lcd_set_viewport(NULL);
|
|
lcd_putsf(0, 1, "(%d,%d) %s", last_x, last_y, touching ? "touching!" : "");
|
|
lcd_putsf(0, 0, "Type %s", imx233_pinctrl_get_gpio(0, 31) ? "CAP" : "REG");
|
|
lcd_set_viewport(&report_vp);
|
|
lcd_set_drawinfo(DRMODE_SOLID, LCD_RGBPACK(0, 0, 0xff), LCD_BLACK);
|
|
lcd_drawrect(0, 0, 100, 100);
|
|
float percent_x = ((float)(last_x) / MAX_X);
|
|
float percent_y = ((float)(last_y) / MAX_Y);
|
|
if (touching)
|
|
{
|
|
lcd_set_viewport(NULL);
|
|
if (last < MAX_ENTRIES)
|
|
{
|
|
last_entries[last].x = last_x;
|
|
last_entries[last].y = last_y;
|
|
last++;
|
|
lcd_putsf(0, 17, "Recording: %d captures left", MAX_ENTRIES - last);
|
|
}
|
|
else
|
|
{
|
|
int min_x = 9999;
|
|
int min_y = 9999;
|
|
int max_x = -1;
|
|
int max_y = -1;
|
|
int median_x = 0;
|
|
int median_y = 0;
|
|
for (int i = 0; i < MAX_ENTRIES; i++)
|
|
{
|
|
min_x = MIN(min_x, last_entries[i].x);
|
|
min_y = MIN(min_y, last_entries[i].y);
|
|
max_x = MAX(max_x, last_entries[i].x);
|
|
max_y = MAX(max_y, last_entries[i].y);
|
|
median_x += last_entries[i].x;
|
|
median_y += last_entries[i].y;
|
|
}
|
|
median_x /= MAX_ENTRIES;
|
|
median_y /= MAX_ENTRIES;
|
|
lcd_putsf(0, 17, "center(%d,%d)", median_x, median_y);
|
|
lcd_putsf(0, 18, "radius(%d,%d)", median_x / 2, median_y / 2);
|
|
}
|
|
lcd_set_viewport(&report_vp);
|
|
lcd_set_drawinfo(DRMODE_SOLID, LCD_RGBPACK(0xff, 0x8c, 0), LCD_BLACK);
|
|
lcd_fillrect(VIEWPORT_WIDTH * percent_x, VIEWPORT_HEIGHT * percent_y, 2, 2);
|
|
}
|
|
|
|
/* Draw current calibration settings */
|
|
lcd_set_viewport(&report_vp);
|
|
draw_calibration_rect(TOUCH_UP);
|
|
draw_calibration_rect(TOUCH_DOWN);
|
|
draw_calibration_rect(TOUCH_CENTER);
|
|
draw_calibration_rect(TOUCH_LEFT);
|
|
draw_calibration_rect(TOUCH_RIGHT);
|
|
|
|
lcd_update();
|
|
yield();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
#endif
|