Understanding the language, error messages, etc.
by Montiey » Mon Mar 21, 2016 9:22 pm
I'm trying to make a simple paint program, basically choose which pixels are black or white.
This is my code currently:
- Code: Select all
#include <SPI.h>
#include <Gamebuino.h>
Gamebuino gb;
const unsigned char PROGMEM player[] = {
8,8,
B00000000,
B01111000,
B01100000,
B01010000,
B01001000,
B00000100,
B00000010,
B00000001,
};
int player_x = 0;
int player_y = 0;
int player_size = 8; //width, height
int button_repeat = 5;
int paintMap[8][8];
void setup(){
gb.begin();
gb.titleScreen(F("Jason's" ));
}
void loop(){
if(gb.update()){
for(int x = 0; x < 8; x++){
for(int y = 0; y < 8; y++){
gb.display.setColor(paintMap[x][y]); //choose color at possition
gb.display.drawPixel(x, y); //draw that pixel
}
}
moveWithButtons(1); //move the cursor
paintWithButtons(); //set value in matrix on button press
}
}
int paintWithButtons(){
if(gb.buttons.repeat(BTN_A, button_repeat)){
paintMap[player_x][player_y] = 1;
}
if(gb.buttons.repeat(BTN_B, button_repeat)){
paintMap[player_x][player_y] = 0;
}
}
int moveWithButtons(int velocity){
if(gb.buttons.repeat(BTN_RIGHT, button_repeat)){
player_x = player_x + velocity;
}
if(gb.buttons.repeat(BTN_LEFT, button_repeat)){
player_x = player_x - velocity;
}
if(gb.buttons.repeat(BTN_UP, button_repeat)){
player_y = player_y - velocity;
}
if(gb.buttons.repeat(BTN_DOWN, button_repeat)){
player_y = player_y + velocity;
}
if((player_x) > LCDWIDTH){ //keep cursor on screen
player_x = LCDWIDTH;
}
if(player_x < 0){
player_x = 0;
}
if(player_y < 0){
player_y = 0;
}
if((player_y) > LCDHEIGHT){
player_y = LCDHEIGHT;
}
gb.display.setColor(1);
gb.display.drawBitmap(player_x, player_y, player);
}
It does some pretty weird things, but really you'd need to play it yourself to see.
If the size of the matrix is much larger than 20 * 20, the gamebuino either displays a corrupt image on startup, plays a buzzing when B is pressed (on startup), or cycles in a reboot loop.
Setting it to something like 8*8 works "well". Sometimes while creating a magnificent 64 pixel masterpiece I will get a low battery alarm. These have usually registered at 4.1 volts, or 4157mV as actually reported. Thats definitely not a drained battery of any sorts, so maybe some sort of spike due to high CPU load? I can't really see how i'm pushing the limits with a 20*20 matrix when the same device, but i'm sure there's a reason.
Have any ideas? I found the For Loop structure in a matrix example somewhere, maybe there is a more efficient way to store the pixel values?
Last edited by
Montiey on Mon Mar 28, 2016 8:22 pm, edited 1 time in total.
-
Montiey
-
- Posts: 68
- Joined: Sat Jan 17, 2015 5:38 pm
-
by Sorunome » Mon Mar 21, 2016 10:39 pm
Some of those issues you described seem to me as if you use too much ram (random sound etc.)
If you are using a 20x20 matrix you are using 800 bytes of ram as you set it to variable type 'int'.
As you only store colors in it which are within the 0-255 range you should try using type 'byte' instead.
I'd recommend taking a look at this:
http://gamebuino.com/wiki/index.php?tit ... #Variables
-
Sorunome
-
- Posts: 629
- Joined: Sun Mar 01, 2015 1:58 pm
-
by Montiey » Fri Mar 25, 2016 1:20 am
Using byte seemed to help, but I still can't get the matrix up above 20*20. It seems like some of my problems come from when the cursor leave the "canvas" area. I guess this could cause some rapid looping in the for loops. What you you noted that I had previously said still seems to be a problem; Random buzzing, intermittent backlight, and the battery status indicator disappearing / corrupted. The Arduino IDE says that I use about 11 kilobytes, but maybe only a small portion available is RAM?
- Code: Select all
#include <SPI.h>
#include <Gamebuino.h>
Gamebuino gb;
const unsigned char PROGMEM player[] = {
8,8,
B00000000,
B01111000,
B01100000,
B01010000,
B01001000,
B00000100,
B00000010,
B00000001,
};
int player_x = 0;
int player_y = 0;
int player_size = 8; //width, height
int button_repeat = 5;
const unsigned canvas_x_size = 20;
const unsigned canvas_y_size = 20;
byte paintMap[canvas_x_size][canvas_y_size];
void setup(){
gb.begin();
gb.titleScreen(F("Jason's" ));
}
void loop(){
if(gb.update()){
if(player_x < canvas_y_size && player_y < canvas_x_size){
for(int x = 0; x < canvas_x_size; x++){
for(int y = 0; y < canvas_y_size; y++){
gb.display.setColor(paintMap[x][y]); //choose color at possition
gb.display.drawPixel(x, y); //draw that pixel
}
}
}
moveWithButtons(1); //move the cursor
paintWithButtons(); //set value in matrix on button press
}
}
int paintWithButtons(){
if(gb.buttons.repeat(BTN_A, button_repeat)){
paintMap[player_x][player_y] = 1;
}
if(gb.buttons.repeat(BTN_B, button_repeat)){
paintMap[player_x][player_y] = 0;
}
}
int moveWithButtons(int velocity){
if(gb.buttons.repeat(BTN_RIGHT, button_repeat)){
player_x = player_x + velocity;
}
if(gb.buttons.repeat(BTN_LEFT, button_repeat)){
player_x = player_x - velocity;
}
if(gb.buttons.repeat(BTN_UP, button_repeat)){
player_y = player_y - velocity;
}
if(gb.buttons.repeat(BTN_DOWN, button_repeat)){
player_y = player_y + velocity;
}
if((player_x) > LCDWIDTH){ //keep cursor on screen
player_x = LCDWIDTH;
}
if(player_x < 0){
player_x = 0;
}
if(player_y < 0){
player_y = 0;
}
if((player_y) > LCDHEIGHT){
player_y = LCDHEIGHT;
}
gb.display.setColor(1);
gb.display.drawBitmap(player_x, player_y, player);
}
-
Montiey
-
- Posts: 68
- Joined: Sat Jan 17, 2015 5:38 pm
-
by Sorunome » Fri Mar 25, 2016 9:24 am
I just notice you limit the cursor to LCDWIDTH/LCDHEIGHT, but you need to limit it to your matrix. Else you'll be overwriting random ram areas resulting in random stuff.
-
Sorunome
-
- Posts: 629
- Joined: Sun Mar 01, 2015 1:58 pm
-
by Montiey » Sat Mar 26, 2016 12:21 am
Is that what happens when you write to coords that are outside of the bounds? I'd assume that it would just return 0 or something, but I guess I should disable writing to the matrix if the cursor is outside of the canvas. Good thinking!
-
Montiey
-
- Posts: 68
- Joined: Sat Jan 17, 2015 5:38 pm
-
by Sorunome » Sat Mar 26, 2016 9:29 am
Yes, C/C++ is known for not checking array offsets/where pointers actually point, so you, the programmer, has to make sure that nothing is violated.
-
Sorunome
-
- Posts: 629
- Joined: Sun Mar 01, 2015 1:58 pm
-
by Montiey » Sun Mar 27, 2016 1:40 pm
Well, I have absolutely not worked out all the quirks yet.
I've gotten the code to export the images to the serial monitor, and also added some (currently non-functional) sidebar buttons. That's where the fun begins:
- Code: Select all
#include <SPI.h>
#include <Gamebuino.h>
Gamebuino gb;
const unsigned char PROGMEM player[] = {
8,8,
B00000000,
B01111000,
B01100000,
B01010000,
B01001000,
B00000100,
B00000000,
B00000000,
};
const unsigned char PROGMEM smallBrush[] = {
8,8,
B00111111,
B01000000,
B10000000,
B10001100,
B10001100,
B10000000,
B01000000,
B00111111,
};
const unsigned char PROGMEM largeBrush[] = {
8,8,
B00111111,
B01000000,
B10001100,
B10011110,
B10011110,
B10001100,
B01000000,
B00111111,
};
const unsigned char PROGMEM smallEraser[] = {
8,8,
B00111111,
B01000000,
B10001100,
B10010010,
B10010010,
B10001100,
B01000000,
B00111111,
};
const unsigned char PROGMEM largeEraser[] = {
8,8,
B00111111,
B01001100,
B10010010,
B10100001,
B10100001,
B10010010,
B01001100,
B00111111,
};
#define canvas_x_size 20 //define, not int to save memory (maybe?)
#define canvas_y_size 20
#define player_size 8
#define button_repeat 2
////////////////////////////////////////
////////////////////////////////////////
int player_x = 0;
int player_y = 0;
int activeIcon = 1; //which tool is active at start
byte activeIconOffset[4]; //the offset distance at any (4) given position(s)
byte canvas[canvas_x_size][canvas_y_size];
void setup(){
gb.begin();
Serial.begin(19200);
gb.battery.show = false;
activeIconOffset[1] = 2;
}
void loop(){
if(gb.update()){
updateCanvas(); //draw the pixels in the matrix (once per frame)
moveWithButtons(1); //move the player
if(gb.buttons.repeat(BTN_A, 1)){ //set value in matrix on button press
canvas[player_x][player_y] = 1;
}
exportMatrix(); //experamental
updateIcons(); //draw & set state of tool indicators
}
}
////////////////////////////////////////
////////////////////////////////////////
int updateIcons(){
if(gb.buttons.pressed(BTN_B)){
activeIconOffset[activeIcon] = 0;
if(activeIcon < 4){ //only if not on the last one!
activeIconOffset[activeIcon + 1] = 2;
}
activeIcon++; //move to next tool
if(activeIcon > 4){
activeIcon = 1; //go back to first tool
activeIconOffset[1] = 2; //imediately set its offset to 2
}
Serial.println();
Serial.println(activeIcon);
Serial.println();
Serial.println(activeIconOffset[1]);
Serial.println(activeIconOffset[2]);
Serial.println(activeIconOffset[3]);
Serial.println(activeIconOffset[4]);
}
gb.display.drawBitmap(LCDWIDTH - activeIconOffset[1] - 8, 4, smallBrush); //position the icons according to set values in the array
gb.display.drawBitmap(LCDWIDTH - activeIconOffset[2] - 8, 13, largeBrush);
gb.display.drawBitmap(LCDWIDTH - activeIconOffset[3] - 8, 22, smallEraser);
gb.display.drawBitmap(LCDWIDTH - activeIconOffset[4] - 8, 31, largeEraser);
}
int updateCanvas(){
for(int x = 0; x < canvas_x_size; x++){
for(int y = 0; y < canvas_y_size; y++){
gb.display.setColor(canvas[x][y]); //get corosponding color at position
gb.display.drawPixel(x, y); //draw that pixel for the current frame
}
}
}
int exportMatrix(){ //start the serial monitor before you paint something
if(gb.buttons.repeat(BTN_C, 1000)){
for(int y = 0; y < canvas_x_size; y++){ //row-scanning export
Serial.println();
for(int x = 0; x < canvas_y_size; x++){
Serial.print(canvas[x][y]); //makes the picture look better via double print
Serial.print(canvas[x][y]);
}
}
Serial.println();
}
}
int moveWithButtons(int velocity){
if(gb.buttons.repeat(BTN_RIGHT, button_repeat)){
player_x = player_x + velocity;
}
if(gb.buttons.repeat(BTN_LEFT, button_repeat)){
player_x = player_x - velocity;
}
if(gb.buttons.repeat(BTN_UP, button_repeat)){
player_y = player_y - velocity;
}
if(gb.buttons.repeat(BTN_DOWN, button_repeat)){
player_y = player_y + velocity;
}
if((player_x) > LCDWIDTH){ //keep the cursor on screen
player_x = LCDWIDTH;
}
if(player_x < 0){
player_x = 0;
}
if(player_y < 0){
player_y = 0;
}
if((player_y) > LCDHEIGHT){
player_y = LCDHEIGHT;
}
gb.display.setColor(1);
gb.display.drawBitmap(player_x, player_y, player);
}
For some reason, somehow, the X position of the lower sidebar icon (#4) is linked to the Y position of the cursor! I've looked through the code at least 10 times now looking for anything that could this, but I think it has something to to with memory again. Maybe it looses track of which one is which somewhere, and starts controlling both with the same values?
-
Montiey
-
- Posts: 68
- Joined: Sat Jan 17, 2015 5:38 pm
-
Return to Programming Questions
Who is online
Users browsing this forum: No registered users and 6 guests