/*************************************************************************** * __________ __ ___. * 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" #include "button-imx233.h" #ifndef BOOTLOADER #include "touchscreen.h" #include "touchscreen-imx233.h" #include "button.h" #include "font.h" #include "action.h" #endif #define CHAN 0 /* ADC channel for the buttons */ #define I_VDDIO 0 /* Mock button to define the relative voltage to compute voltage from ADC steps */ struct imx233_button_map_t imx233_button_map[] = { [I_VDDIO] = IMX233_BUTTON_(VDDIO, VDDIO(3760), "vddio"), /* we need VDDIO for relative */ IMX233_BUTTON_(HOLD, GPIO(0, 13), "hold"), IMX233_BUTTON(POWER, PSWITCH(1), "power"), IMX233_BUTTON(SELECT, PSWITCH(3), "select"), IMX233_BUTTON(VOL_UP, LRADC_REL(CHAN, 485, I_VDDIO), "vol up"), IMX233_BUTTON(VOL_DOWN, LRADC_REL(CHAN, 975, I_VDDIO), "vol down"), IMX233_BUTTON(BACK, LRADC_REL(CHAN, 1521, I_VDDIO), "back"), IMX233_BUTTON(FF, LRADC_REL(CHAN, 2000, I_VDDIO), "ff"), IMX233_BUTTON(REW, LRADC_REL(CHAN, 2480, I_VDDIO), "rew"), IMX233_BUTTON_(END, 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) { /* init button subsystem */ imx233_button_init(); #ifndef BOOTLOADER touchpad_pin_setup(); /* Now that is powered up, proceed with touchpad initialization */ imx233_touchscreen_init(); imx233_touchscreen_enable(true); #endif /* BOOTLOADER */ } /* 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; #ifndef BOOTLOADER /* handle the touchpad events */ 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 */ /* handle the generic events */ return imx233_button_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