void copyarray(byte *customchar,byte PROGMEM *progmemp){ for(byte i = 0; i < 8; i++){ customchar[i] = pgm_read_word_near(progmemp + i); } } int availableMemory(){ int size = 2048; byte *buf; while ((buf = (byte *) malloc(--size)) == NULL); free(buf); return size; } //modulus like function to cycle numbers back to within a range int mod(int current, int bottom, int top){ unsigned period = (top - bottom) + 1; while (current < bottom || current > top){ if(current < bottom) current += period; else current -= period; } return current; } //write the fat numbers 0-9, 10 means leave blank void write_number(byte number, byte row){ byte towrite; if(number > 10) print_error(number,__LINE__); if(!row){ towrite = pgm_read_byte(numUpperLeft+number); lcd.write(towrite); towrite = pgm_read_byte(numUpperCenter+number); lcd.write(towrite); towrite = pgm_read_byte(numUpperRight+number); lcd.write(towrite); }else{ towrite = pgm_read_byte(numLowerLeft+number); lcd.write(towrite); lcd.write(pgm_read_byte(numLowerCenter+number)); lcd.write(pgm_read_byte(numLowerRight+number)); } } void print_error(int file, int line){ strcpy_P(outstring2, error_s); sprintf(outstring,outstring2, time.hour, time.minute, time.second, file); print_top(outstring); strcpy_P(outstring2, line_s); sprintf(outstring,outstring2,line-ARDUINO_OFFSET,(line-FILE_LENGTH)-ARDUINO_OFFSET); print_bot(outstring); analogWrite(LCD_BACKLIGHT, 128); while(1); } /*since we run continuously we must accomodate for an overflow (or wrap) of time //millis() returns a 4-byte result or a number up to 4,294,967,296 ms or 49.7 days //regardless, if that happens in the middle of a game it will really mess things up //this simple method subtracts HALF_32BIT if indicated by wrap_time, so time can //run past the half way point without any wrapping troubles and then adjust current_time //and this function concurrently so they match */ unsigned long adjusted_millis(){ //tbt - force system time to be over and just under HALF_32BIT to make sure this works if(wrap_time) return(millis() + HALF_32BIT); return(millis()); } void pause(unsigned mils){ paused = true; pause_end_time = adjusted_millis() + mils; } //print to the upper line of the LCD void print_top(char *outstr){ lcd.setCursor(0,0); lcd.print(outstr); strcpy_P(outstring2, space_s); lcd.print(outstring2); //strcpy_P(outstring2, lcd_line_s); } //print to the lower line of the LCD void print_bot(char *outstr){ lcd.setCursor(0,1); lcd.print(outstr); strcpy_P(outstring2, space_s); lcd.print(outstring2); } //print to the lower line of the LCD void print_bot_c(char *outstr){ lcd.setCursor(0,1); lcd.print(outstr); strcpy_P(outstring2, space_s); lcd.print(outstring2); lcd.setCursor(1,1); } //print to the upper line of the LCD void print_top(){ lcd.setCursor(0,0); strcpy_P(outstring2, space_s); lcd.print(outstring2); //strcpy_P(outstring2, lcd_line_s); } //print to the lower line of the LCD void print_bot(){ lcd.setCursor(0,1); strcpy_P(outstring2, space_s); lcd.print(outstring2); } //print to the lower line of the LCD void print_bot(byte number){ lcd.setCursor(0,1); lcd.print(number,DEC); strcpy_P(outstring2, space_s); lcd.print(outstring2); } //get persistent data from eeprom void get_eeprom(){ unsigned eeprom_index = 0; for(int i=0; i= 60){ alarm_onetime.minute++; snoooze_remainder -= 60; } alarm_onetime.enabled = true; if(alarm_onetime.minute >= 60){ alarm_onetime.minute = 0; alarm_onetime.hour++; if(alarm_onetime.hour >= 24){ alarm_onetime.hour = 0; } } } void factory_init(){ eeprom.magic_number = MAGIC_NUMBER; strcpy_P(outstring, fact_s); print_top(outstring); strcpy_P(outstring, init_s); print_bot(outstring); pause(3000); //set the initial time and date, this might as well be as close as possible to the time and date when the device is programmed (set these values above) time.ms = 0; time.second = START_SECONDS; time.minute = START_MINUTE; time.hour = START_HOUR; time.day = START_DAY; alarm_onetime.hour = ALARM_ONETIME_HOUR; alarm_onetime.minute = ALARM_ONETIME_MINUTE; alarm_onetime.enabled = ALARM_ONETIME_ENABLED; alarm_persistent.hour = ALARM_PERSISTENT_HOUR; alarm_persistent.minute = ALARM_PERSISTENT_MINUTE; alarm_persistent.enabled = ALARM_PERSISTENT_ENABLED; eeprom.lcd_backlight = LCD_BACKLIGHT_DEFAULT; eeprom.thicker = true; eeprom.two_six = true; eeprom.snooze_number = SNOOZE_NUMBER_DEF; eeprom.snooze_time_min = SNOOZE_TIME_DEF; eeprom.snooze_time_sec = SNOOZE_TIME_SEC_DEF; eeprom.tetris_clear_lines = AWAKE_LINES; eeprom.extras = true; eeprom.snooze_relative = false; set_eeprom(); } //return true if the piece fits boolean piece_fit(){ get_adjusted_piece(); if(!(adj_piece[0]&board[piece_y+3]) && !(adj_piece[1]&board[piece_y+2]) && !(adj_piece[2]&board[piece_y+1]) && !(adj_piece[3]&board[piece_y+0])) return true; return false; } void remove_piece(){ get_adjusted_piece(); board[piece_y+3] &= ~adj_piece[0]; board[piece_y+2] &= ~adj_piece[1]; board[piece_y+1] &= ~adj_piece[2]; board[piece_y+0] &= ~adj_piece[3]; } void set_piece(){ get_adjusted_piece(); board[piece_y+3] |= adj_piece[0]; board[piece_y+2] |= adj_piece[1]; board[piece_y+1] |= adj_piece[2]; board[piece_y+0] |= adj_piece[3]; } /*if this function seems to be slowing things down and we have plenty of RAM space we can increase //speed by storing the piece definitions in four unsigned variables and eliminating the first half //of this function */ void get_adjusted_piece(){ adj_piece[0] = (pieces[piece_id][piece_rot] & 0xF000) >> 12; adj_piece[1] = (pieces[piece_id][piece_rot] & 0x0F00) >> 8; adj_piece[2] = (pieces[piece_id][piece_rot] & 0x00F0) >> 4; adj_piece[3] = (pieces[piece_id][piece_rot] & 0x000F) >> 0; if(piece_x <= 12){ //not sure if you can shift a negative amount adj_piece[0] <<= (12-piece_x); //a for loop has enough overhead adj_piece[1] <<= (12-piece_x); //that this might be less code adj_piece[2] <<= (12-piece_x); //and it's definately faster (no adj_piece[3] <<= (12-piece_x); //compare each time) }else{ adj_piece[0] >>= (piece_x-12); //a for loop has enough overhead adj_piece[1] >>= (piece_x-12); //that this might be less code adj_piece[2] >>= (piece_x-12); //and it's definately faster (no adj_piece[3] >>= (piece_x-12); //compare each time) } } void get_new_piece(){ piece_id = millis()%7; piece_rot = 0; piece_x = 7; if(piece_id == PIECE_I) piece_x--; piece_y = 36; } void zero_outs(void *ptr, unsigned memsize){ memset(ptr,0,memsize); } void zero_outvs(volatile void *ptr, unsigned memsize){ for(unsigned i = 0; i= combined_alarm) return true; else return false; case MON: case TUE: case WED: case THU: return true; case FRI: if(combined_time <= combined_alarm) return true; else return false; case SAT: return false; default: error; } } //boolean persistant_on() /* Uses arrow keys to input an unsigned number * digits - the total number of digits to input, the number 12345 would have 5 digits */ byte input_byte(byte initial_value){ byte i; char menu,mult; byte fact[3]; byte div; unsigned factor; byte digits = 3; //div = 10^(digits-1) // div = 1; // for(i=0;i=9) fact[mult]=0; else fact[mult]++; }else if(buttons[BUTTON_MENUDOWN]){ buttons[BUTTON_MENUDOWN]--; if(fact[mult] ==0) fact[mult]=9; else fact[mult]--; }else if(buttons[BUTTON_GOBACK]){ buttons[BUTTON_GOBACK]--; if(mult>0) mult-- ; else{ div = 100; factor = 0; for(i=0;i