rendered paste body
#include "plugin.h"
PLUGIN_HEADER
static struct plugin_api* rb;
#include "eval.c"
struct point
{
int x;
int y;
};
struct plot_conf
{
int x_start;
int x_end;
int y_start;
int y_end;
int x_mod;
int y_mod;
int x_grid_step;
int y_grid_step;
char func[256];
};
struct point last_point;
bool use_last_point; /*Coordinates of last drawed point*/
/*bool exit; true if we must exit app*/
static struct plot_conf plot;
static void plot_set_default_values(void)
{
plot.x_start = -(LCD_WIDTH/2);
plot.x_end = (LCD_WIDTH/2);
plot.y_start = -(LCD_HEIGHT/2);
plot.y_end = (LCD_HEIGHT/2);
plot.x_mod = 1;
plot.y_mod = 1;
plot.x_grid_step = 10;
rb->strcpy(plot.func,"x*x") ;
}
static void draw_point(struct point p)
{
if (!use_last_point)
{
rb->lcd_drawpixel(p.x,p.y);
use_last_point = true;
}else
{
rb->lcd_drawline(last_point.x,last_point.y,p.x,p.y);
}
}
static struct point create_point(int _x, int _y)
{
struct point tmp;
tmp.x = _x;
tmp.y = _y;
return tmp;
}
static struct point coord_to_screen_pixel(struct point p)
{
struct point tmp;
tmp.x = (int)((LCD_WIDTH / 2)+p.x);
tmp.y = (int)((LCD_HEIGHT / 2)-p.y);
return tmp;
}
static void draw_grid(void)
{
rb->lcd_set_background(LCD_WHITE);
rb->lcd_set_foreground(LCD_BLACK);
rb->lcd_vline(LCD_WIDTH/2,0,LCD_HEIGHT);
rb->lcd_hline(0,LCD_WIDTH,LCD_HEIGHT/2);
int i;
int n=0;
int sign=1;
char buf[32];
for (i=0; i < LCD_WIDTH/2; i+=sign*plot.x_grid_step*plot.x_mod)
{
rb->lcd_vline(LCD_WIDTH/2+i,LCD_HEIGHT/2-2,LCD_HEIGHT/2+2);
rb->snprintf(buf,32,"%d",n);
rb->lcd_putsxy(LCD_WIDTH/2+i+1,LCD_HEIGHT/2+4,buf);
n+=sign*plot.x_grid_step;
}
n=0;
for (i=0; i < LCD_WIDTH/2 ; i+=plot.x_grid_step*plot.x_mod)
{
rb->lcd_vline(LCD_WIDTH/2-i,LCD_HEIGHT/2-2,LCD_HEIGHT/2+2);
rb->snprintf(buf,32,"%d",n);
DEBUGF("%s",buf);
rb->lcd_putsxy(LCD_WIDTH/2-i-1,LCD_HEIGHT/2+4,buf);
n-=plot.x_grid_step;
}
}
static int count(double x)
{
static double const_values[2];
const_values[0] = x;
const_values[1] = x;
const_values[2] = 0;
static const char *const_names[]={
"x",
"X",
0
};
return (int)x*x;/*ff_eval(plot.func, const_values, const_names, NULL, NULL, NULL, NULL, NULL);*/
}
static void draw_plot(void)
{
DEBUGF("Reach draw plot\n");
double i=1.0;
static struct point temp;
rb->lcd_clear_display();
draw_grid();
for (i=plot.x_start;i<=plot.x_end;i+=(double)(LCD_WIDTH/plot.x_mod))
{
//DEBUGF("Per pixel countion i = 0.%d\n",i*100);
temp.x = i*plot.x_mod;
temp.y = i*i;/*(int)(count(i)*plot.y_mod);*/
temp = coord_to_screen_pixel(temp);
DEBUGF("ym %x\n",plot.y_mod);
DEBUGF("y %x\n",temp.y);
if ((temp.x<LCD_WIDTH)&(temp.x>0)&\
(temp.y<LCD_HEIGHT)&(temp.y>0))
{
draw_point(temp);
last_point = temp;
}
}
use_last_point = false;
rb->lcd_update();
DEBUGF("Exit draw plot\n");
}
static bool start_grapher(void)
{
int button, quit = 0;
plot_set_default_values();
draw_plot();
while(!quit) {
button=rb->button_get(true);
switch(button) {
case BUTTON_LEFT:
if (plot.x_mod>1) plot.x_mod--;
draw_plot();
break;
case BUTTON_RIGHT:
plot.x_mod++;
draw_plot();
break;
case BUTTON_UP:
plot.y_mod++;
draw_plot();
break;
case BUTTON_DOWN:
if (plot.y_mod>1) plot.y_mod--;
draw_plot();
break;
case BUTTON_REC:
quit=true;
break;
}
}
return true;
}
static bool show_main_menu(void)
{
int m;
bool result;
bool rs = true;
static const struct menu_item items[] = {
{ "Grapher", start_grapher },
{ "Calculator", NULL },
{ "Exit", NULL },
};
m = rb->menu_init(items, sizeof(items) / sizeof(*items),
NULL, NULL, NULL, NULL);
result = rb->menu_run(m);
rb->menu_exit(m);
return rs;
}
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
{
(void)parameter;
rb = api;
show_main_menu();
return PLUGIN_OK;
}