void u8g_DrawFullScreenBitmapPLL(u8g_t *u8g, u8g_dev_t *dev, uint8_t *bitmap) { u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem); uint8_t i, j; uint8_t page_height; uint8_t *ptr; u8g->state_cb(U8G_STATE_MSG_BACKUP_ENV); u8g->state_cb(U8G_STATE_MSG_RESTORE_U8G); u8g_FirstPageLL( u8g, dev ); do { page_height = pb->p.page_y1; page_height -= pb->p.page_y0; page_height++; ptr = pb->buf; for( i = 0; i < page_height; i++ ) { /* for each line in the page... */ for ( j = 0; j < pb->width; j++ ) { /* for each pixel in the line... */ *ptr++ = u8g_pgm_read( bitmap++ ); *ptr++ = u8g_pgm_read( bitmap++ ); *ptr++ = u8g_pgm_read( bitmap++ ); } } } while ( u8g_NextPageLL( u8g, dev ) ); u8g->state_cb(U8G_STATE_MSG_RESTORE_ENV); }
static uint16_t u8g_font_get_word(const u8g_fntpgm_uint8_t *font, uint8_t offset) { uint16_t pos; font += offset; pos = u8g_pgm_read( (u8g_pgm_uint8_t *)font ); font++; pos <<= 8; pos += u8g_pgm_read( (u8g_pgm_uint8_t *)font); return pos; }
static void u8g_CopyGlyphDataToCache(u8g_t *u8g, u8g_glyph_t g) { uint8_t tmp; switch( u8g_font_GetFormat(u8g->font) ) { case 0: case 2: /* format 0 glyph information offset 0 BBX width unsigned 1 BBX height unsigned 2 data size unsigned (BBX width + 7)/8 * BBX height 3 DWIDTH signed 4 BBX xoffset signed 5 BBX yoffset signed byte 0 == 255 indicates empty glyph */ u8g->glyph_width = u8g_pgm_read( ((u8g_pgm_uint8_t *)g) + 0 ); u8g->glyph_height = u8g_pgm_read( ((u8g_pgm_uint8_t *)g) + 1 ); u8g->glyph_dx = u8g_pgm_read( ((u8g_pgm_uint8_t *)g) + 3 ); u8g->glyph_x = u8g_pgm_read( ((u8g_pgm_uint8_t *)g) + 4 ); u8g->glyph_y = u8g_pgm_read( ((u8g_pgm_uint8_t *)g) + 5 ); break; case 1: default: /* format 1 0 BBX xoffset signed --> upper 4 Bit 0 BBX yoffset signed --> lower 4 Bit 1 BBX width unsigned --> upper 4 Bit 1 BBX height unsigned --> lower 4 Bit 2 data size unsigned -(BBX width + 7)/8 * BBX height --> lower 4 Bit 2 DWIDTH signed --> upper 4 Bit byte 0 == 255 indicates empty glyph */ tmp = u8g_pgm_read( ((u8g_pgm_uint8_t *)g) + 0 ); u8g->glyph_y = tmp & 15; u8g->glyph_y-=2; tmp >>= 4; u8g->glyph_x = tmp; tmp = u8g_pgm_read( ((u8g_pgm_uint8_t *)g) + 1 ); u8g->glyph_height = tmp & 15; tmp >>= 4; u8g->glyph_width = tmp; tmp = u8g_pgm_read( ((u8g_pgm_uint8_t *)g) + 2 ); tmp >>= 4; u8g->glyph_dx = tmp; break; } }
void u8g_DrawHBitmapP(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, u8g_uint_t cnt, const u8g_pgm_uint8_t *bitmap) { while( cnt > 0 ) { u8g_Draw8Pixel(u8g, x, y, 0, u8g_pgm_read(bitmap)); bitmap++; cnt--; x+=8; } }
/* calculate the overall length of the font, only used to create the picture for the google wiki */ size_t u8g_font_GetSize(const void *font) { uint8_t *p = (uint8_t *)(font); uint8_t font_format = u8g_font_GetFormat(font); uint8_t data_structure_size = u8g_font_GetFontGlyphStructureSize(font); uint8_t start, end; uint8_t i; uint8_t mask = 255; start = u8g_font_GetFontStartEncoding(font); end = u8g_font_GetFontEndEncoding(font); if ( font_format == 1 ) mask = 15; p += U8G_FONT_DATA_STRUCT_SIZE; /* skip font general information */ i = start; for(;;) { if ( u8g_pgm_read((u8g_pgm_uint8_t *)(p)) == 255 ) { p += 1; } else { p += u8g_pgm_read( ((u8g_pgm_uint8_t *)(p)) + 2 ) & mask; p += data_structure_size; } if ( i == end ) break; i++; } return p - (uint8_t *)font; }
u8g_uint_t u8g_DrawStr270P(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, const u8g_pgm_uint8_t *s) { u8g_uint_t t = 0; int8_t d; x += u8g->font_calc_vref(u8g); while( *s != '\0' ) { d = u8g_DrawGlyph270(u8g, x, y, u8g_pgm_read(s)); y -= d; t += d; s++; } return t; }
int8_t u8g_draw_glyph270(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t encoding) { const u8g_pgm_uint8_t *data; uint8_t w, h; uint8_t i, j; u8g_uint_t ix, iy; { u8g_glyph_t g = u8g_GetGlyph(u8g, encoding); if ( g == NULL ) return 0; data = u8g_font_GetGlyphDataStart(u8g->font, g); } w = u8g->glyph_width; h = u8g->glyph_height; x -= u8g->glyph_y; x--; y -= u8g->glyph_x; if ( u8g_IsBBXIntersection(u8g, x-(h-1), y-(w-1), h, w) == 0 ) return u8g->glyph_dx; /* now, w is reused as bytes per line */ w += 7; w /= 8; ix = x; ix -= h; ix++; for( j = 0; j < h; j++ ) { iy = y; for( i = 0; i < w; i++ ) { u8g_Draw8Pixel(u8g, ix, iy, 3, u8g_pgm_read(data)); data++; iy-=8; } ix++; } return u8g->glyph_dx; }
u8g_uint_t u8g_DrawStrP(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, const u8g_pgm_uint8_t *s) { u8g_uint_t t = 0; int8_t d; uint8_t c; y += u8g->font_calc_vref(u8g); for(;;) { c = u8g_pgm_read(s); if ( c == '\0' ) break; d = u8g_draw_glyph(u8g, x, y, c); x += d; t += d; s++; } return t; }
uint8_t u8g_com_atmega_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { switch(msg) { case U8G_COM_MSG_STOP: break; case U8G_COM_MSG_INIT: u8g_SetPIOutput(u8g, U8G_PI_CS); u8g_SetPIOutput(u8g, U8G_PI_A0); DDRB |= _BV(3); /* D0, MOSI */ DDRB |= _BV(5); /* SCK */ PORTB &= ~_BV(3); /* D0, MOSI = 0 */ PORTB &= ~_BV(5); /* SCK = 0 */ u8g_SetPILevel(u8g, U8G_PI_CS, 1); /* SPR1 SPR0 0 0 fclk/4 0 1 fclk/16 1 0 fclk/64 1 1 fclk/128 */ SPCR = 0; SPCR = (1<<SPE) | (1<<MSTR)|(0<<SPR1)|(0<<SPR0)|(0<<CPOL)|(0<<CPHA); break; case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */ u8g_SetPILevel(u8g, U8G_PI_A0, arg_val); break; case U8G_COM_MSG_CHIP_SELECT: if ( arg_val == 0 ) { /* disable */ u8g_SetPILevel(u8g, U8G_PI_CS, 1); } else { PORTB &= ~_BV(5); /* SCK = 0 */ /* enable */ u8g_SetPILevel(u8g, U8G_PI_CS, 0); /* CS = 0 (low active) */ } break; case U8G_COM_MSG_RESET: u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val); break; case U8G_COM_MSG_WRITE_BYTE: u8g_atmega_spi_out(arg_val); break; case U8G_COM_MSG_WRITE_SEQ: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_atmega_spi_out(*ptr++); arg_val--; } } break; case U8G_COM_MSG_WRITE_SEQ_P: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_atmega_spi_out(u8g_pgm_read(ptr)); ptr++; arg_val--; } } break; } return 1; }
//static uint8_t u8g_font_get_byte(const u8g_fntpgm_uint8_t *font, uint8_t offset) U8G_NOINLINE; static uint8_t u8g_font_get_byte(const u8g_fntpgm_uint8_t *font, uint8_t offset) { font += offset; return u8g_pgm_read( (u8g_pgm_uint8_t *)font ); }
uint8_t u8g_com_arduino_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { switch(msg) { case U8G_COM_MSG_STOP: break; case U8G_COM_MSG_INIT: u8g_com_arduino_assign_pin_output_high(u8g); pinMode(PIN_SCK, OUTPUT); digitalWrite(PIN_SCK, LOW); pinMode(PIN_MOSI, OUTPUT); digitalWrite(PIN_MOSI, LOW); /* pinMode(PIN_MISO, INPUT); */ pinMode(PIN_CS, OUTPUT); /* system chip select for the atmega board */ digitalWrite(PIN_CS, HIGH); /* SPR1 SPR0 0 0 fclk/4 0 1 fclk/16 1 0 fclk/64 1 1 fclk/128 */ SPCR = 0; SPCR = (1<<SPE) | (1<<MSTR)|(0<<SPR1)|(0<<SPR0)|(0<<CPOL)|(0<<CPHA); break; case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */ u8g_com_arduino_digital_write(u8g, U8G_PI_A0, arg_val); break; case U8G_COM_MSG_CHIP_SELECT: if ( arg_val == 0 ) { /* disable */ u8g_com_arduino_digital_write(u8g, U8G_PI_CS, HIGH); } else { /* enable */ u8g_com_arduino_digital_write(u8g, U8G_PI_SCK, LOW); u8g_com_arduino_digital_write(u8g, U8G_PI_CS, LOW); } break; case U8G_COM_MSG_RESET: if ( u8g->pin_list[U8G_PI_RESET] != U8G_PIN_NONE ) u8g_com_arduino_digital_write(u8g, U8G_PI_RESET, arg_val); break; case U8G_COM_MSG_WRITE_BYTE: u8g_spi_out(arg_val); break; case U8G_COM_MSG_WRITE_SEQ: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_spi_out(*ptr++); arg_val--; } } break; case U8G_COM_MSG_WRITE_SEQ_P: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_spi_out(u8g_pgm_read(ptr)); ptr++; arg_val--; } } break; } return 1; }
/* Draw a glyph x,y: left baseline position of the glyph */ int8_t u8g_DrawGlyphDir(u8g_t *u8g, u8g_uint_t x, u8g_uint_t y, uint8_t dir, uint8_t encoding) { u8g_glyph_t g; uint8_t w, h, i, j; const u8g_pgm_uint8_t *data; uint8_t bytes_per_line; u8g_uint_t ix, iy; g = u8g_GetGlyph(u8g, encoding); if ( g == NULL ) return 0; w = u8g->glyph_width; h = u8g->glyph_height; bytes_per_line = w; bytes_per_line += 7; bytes_per_line /= 8; data = u8g_font_GetGlyphDataStart(u8g->font, g); switch(dir) { case 0: x += u8g->glyph_x; y -= u8g->glyph_y; y--; //u8g_DrawFrame(u8g, x, y-h+1, w, h); if ( u8g_IsBBXIntersection(u8g, x, y-h+1, w, h) == 0 ) return u8g->glyph_dx; iy = y; iy -= h; iy++; for( j = 0; j < h; j++ ) { ix = x; for( i = 0; i < bytes_per_line; i++ ) { u8g_Draw8Pixel(u8g, ix, iy, dir, u8g_pgm_read(data)); data++; ix+=8; } iy++; } break; case 1: x += u8g->glyph_y; x++; y += u8g->glyph_x; //printf("enc %d, dir %d, x %d, y %d, w %d, h %d\n", encoding, dir, x, y, w, h); //u8g_DrawFrame(u8g, x, y, h, w); if ( u8g_IsBBXIntersection(u8g, x, y, h, w) == 0 ) return u8g->glyph_dx; ix = x; ix += h; ix--; for( j = 0; j < h; j++ ) { iy = y; for( i = 0; i < bytes_per_line; i++ ) { u8g_Draw8Pixel(u8g, ix, iy, dir, u8g_pgm_read(data)); data++; iy+=8; } ix--; } break; case 2: x -= u8g->glyph_x; y += u8g->glyph_y; y++; if ( u8g_IsBBXIntersection(u8g, x-w-1, y, w, h) == 0 ) return u8g->glyph_dx; iy = y; iy += h; iy--; for( j = 0; j < h; j++ ) { ix = x; for( i = 0; i < bytes_per_line; i++ ) { u8g_Draw8Pixel(u8g, ix, iy, dir, u8g_pgm_read(data)); data++; ix-=8; } iy--; } break; case 3: x -= u8g->glyph_y; x--; y -= u8g->glyph_x; if ( u8g_IsBBXIntersection(u8g, x-h-1, y-w-1, h, w) == 0 ) return u8g->glyph_dx; ix = x; ix -= h; ix++; for( j = 0; j < h; j++ ) { iy = y; for( i = 0; i < bytes_per_line; i++ ) { u8g_Draw8Pixel(u8g, ix, iy, dir, u8g_pgm_read(data)); data++; iy-=8; } ix++; } break; } return u8g->glyph_dx; }
uint8_t u8g_com_atxmega_st7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { switch(msg) { case U8G_COM_MSG_INIT: u8g_SetPIOutput(u8g, U8G_PI_CS); //u8g_SetPIOutput(u8g, U8G_PI_A0); //U8G_ATOMIC_START(); PORTC.DIR |= PIN4_bm | PIN5_bm | PIN7_bm; PORTC.DIR &= ~PIN6_bm; //U8G_ATOMIC_END(); u8g_SetPILevel(u8g, U8G_PI_CS, 1); SPIC.CTRL = 0; SPIC.CTRL = SPI_PRESCALER_DIV4_gc | // SPI prescaler. //SPI_CLK2X_bm | //SPI Clock double. SPI_ENABLE_bm | //Enable SPI module. //SPI_DORD_bm | //Data order. SPI_MASTER_bm | //SPI master. SPI_MODE_0_gc; // SPI mode. #ifdef U8G_HW_SPI_2X SPIC.CTRL |= SPI_CLK2X_bm; /* double speed, issue 89 */ #endif u8g->pin_list[U8G_PI_A0_STATE] = 0; /* inital RS state: command mode */ break; case U8G_COM_MSG_STOP: break; case U8G_COM_MSG_RESET: u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val); break; case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */ u8g->pin_list[U8G_PI_A0_STATE] = arg_val; break; case U8G_COM_MSG_CHIP_SELECT: if ( arg_val == 0 ) { /* disable, note: the st7920 has an active high chip select */ u8g_SetPILevel(u8g, U8G_PI_CS, 0); } else { /* u8g_SetPILevel(u8g, U8G_PI_SCK, 0 ); */ /* enable */ u8g_SetPILevel(u8g, U8G_PI_CS, 1); /* CS = 1 (high active) */ } break; case U8G_COM_MSG_WRITE_BYTE: u8g_com_atxmega_st7920_write_byte_hw_spi(u8g, u8g->pin_list[U8G_PI_A0_STATE], arg_val); //u8g->pin_list[U8G_PI_A0_STATE] = 2; break; case U8G_COM_MSG_WRITE_SEQ: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_com_atxmega_st7920_write_byte_hw_spi(u8g, u8g->pin_list[U8G_PI_A0_STATE], *ptr++); //u8g->pin_list[U8G_PI_A0_STATE] = 2; arg_val--; } } break; case U8G_COM_MSG_WRITE_SEQ_P: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_com_atxmega_st7920_write_byte_hw_spi(u8g, u8g->pin_list[U8G_PI_A0_STATE], u8g_pgm_read(ptr)); //u8g->pin_list[U8G_PI_A0_STATE] = 2; ptr++; arg_val--; } } break; } return 1; }
uint8_t u8g_com_arduino_st7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { switch(msg) { case U8G_COM_MSG_INIT: u8g_com_arduino_assign_pin_output_high(u8g); u8g_com_arduino_digital_write(u8g, U8G_PI_CS, LOW); DDRB |= _BV(3); /* D0, MOSI */ DDRB |= _BV(5); /* SCK */ DDRB |= _BV(2); /* slave select */ PORTB &= ~_BV(3); /* D0, MOSI = 0 */ PORTB &= ~_BV(5); /* SCK = 0 */ /* SPR1 SPR0 0 0 fclk/4 0 1 fclk/16 1 0 fclk/64 1 1 fclk/128 */ SPCR = 0; /* 20 Dez 2012: set CPOL and CPHA to 1 !!! */ SPCR = (1<<SPE) | (1<<MSTR)|(0<<SPR1)|(0<<SPR0)|(1<<CPOL)|(1<<CPHA); #ifdef U8G_HW_SPI_2X SPSR = (1 << SPI2X); /* double speed, issue 89 */ #endif u8g->pin_list[U8G_PI_A0_STATE] = 0; /* inital RS state: command mode */ break; case U8G_COM_MSG_STOP: break; case U8G_COM_MSG_RESET: if ( u8g->pin_list[U8G_PI_RESET] != U8G_PIN_NONE ) u8g_com_arduino_digital_write(u8g, U8G_PI_RESET, arg_val); break; case U8G_COM_MSG_CHIP_SELECT: if ( arg_val == 0 ) { /* disable, note: the st7920 has an active high chip select */ u8g_com_arduino_digital_write(u8g, U8G_PI_CS, LOW); } else { /* enable */ //u8g_com_arduino_digital_write(u8g, U8G_PI_SCK, LOW); u8g_com_arduino_digital_write(u8g, U8G_PI_CS, HIGH); } break; case U8G_COM_MSG_WRITE_BYTE: u8g_com_arduino_st7920_write_byte_hw_spi(u8g, u8g->pin_list[U8G_PI_A0_STATE], arg_val); // u8g->pin_list[U8G_PI_A0_STATE] = 2; //u8g_arduino_sw_spi_shift_out(u8g->pin_list[U8G_PI_MOSI], u8g->pin_list[U8G_PI_SCK], arg_val); break; case U8G_COM_MSG_WRITE_SEQ: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_com_arduino_st7920_write_byte_hw_spi(u8g, u8g->pin_list[U8G_PI_A0_STATE], *ptr++); // u8g->pin_list[U8G_PI_A0_STATE] = 2; arg_val--; } } break; case U8G_COM_MSG_WRITE_SEQ_P: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_com_arduino_st7920_write_byte_hw_spi(u8g, u8g->pin_list[U8G_PI_A0_STATE], u8g_pgm_read(ptr) ); // u8g->pin_list[U8G_PI_A0_STATE] = 2; ptr++; arg_val--; } } break; case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */ u8g->pin_list[U8G_PI_A0_STATE] = arg_val; break; } return 1; }
uint8_t u8g_com_arduino_ssd_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { switch(msg) { case U8G_COM_MSG_INIT: //u8g_com_arduino_digital_write(u8g, U8G_PI_SCL, HIGH); //u8g_com_arduino_digital_write(u8g, U8G_PI_SDA, HIGH); //u8g->pin_list[U8G_PI_A0_STATE] = 0; /* inital RS state: unknown mode */ u8g_i2c_init(u8g->pin_list[U8G_PI_I2C_OPTION]); break; case U8G_COM_MSG_STOP: break; case U8G_COM_MSG_RESET: /* Currently disabled, but it could be enable. Previous restrictions have been removed */ /* u8g_com_arduino_digital_write(u8g, U8G_PI_RESET, arg_val); */ break; case U8G_COM_MSG_CHIP_SELECT: u8g->pin_list[U8G_PI_A0_STATE] = 0; u8g->pin_list[U8G_PI_SET_A0] = 1; /* force a0 to set again, also forces start condition */ if ( arg_val == 0 ) { /* disable chip, send stop condition */ u8g_i2c_stop(); } else { /* enable, do nothing: any byte writing will trigger the i2c start */ } break; case U8G_COM_MSG_WRITE_BYTE: //u8g->pin_list[U8G_PI_SET_A0] = 1; if ( u8g_com_arduino_ssd_start_sequence(u8g) == 0 ) return u8g_i2c_stop(), 0; if ( u8g_i2c_send_byte(arg_val) == 0 ) return u8g_i2c_stop(), 0; // u8g_i2c_stop(); break; case U8G_COM_MSG_WRITE_SEQ: //u8g->pin_list[U8G_PI_SET_A0] = 1; if ( u8g_com_arduino_ssd_start_sequence(u8g) == 0 ) return u8g_i2c_stop(), 0; { register uint8_t *ptr = (uint8_t*)arg_ptr; while( arg_val > 0 ) { if ( u8g_i2c_send_byte(*ptr++) == 0 ) return u8g_i2c_stop(), 0; arg_val--; } } // u8g_i2c_stop(); break; case U8G_COM_MSG_WRITE_SEQ_P: //u8g->pin_list[U8G_PI_SET_A0] = 1; if ( u8g_com_arduino_ssd_start_sequence(u8g) == 0 ) return u8g_i2c_stop(), 0; { register uint8_t *ptr = (uint8_t*)arg_ptr; while( arg_val > 0 ) { if ( u8g_i2c_send_byte(u8g_pgm_read(ptr)) == 0 ) return 0; ptr++; arg_val--; } } // u8g_i2c_stop(); break; case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */ u8g->pin_list[U8G_PI_A0_STATE] = arg_val; u8g->pin_list[U8G_PI_SET_A0] = 1; /* force a0 to set again */ #ifdef OLD_CODE if ( i2c_state != 0 ) { u8g_i2c_stop(); i2c_state = 0; } if ( u8g_com_arduino_ssd_start_sequence(arg_val) == 0 ) return 0; /* setup bus, might be a repeated start */ /* if ( u8g_i2c_start(I2C_SLA) == 0 ) return 0; if ( arg_val == 0 ) { i2c_state = 1; if ( u8g_i2c_send_byte(I2C_CMD_MODE) == 0 ) return 0; } else { i2c_state = 2; if ( u8g_i2c_send_byte(I2C_DATA_MODE) == 0 ) return 0; } */ #endif break; } return 1; }
uint8_t u8g_com_arduino_std_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { switch(msg) { case U8G_COM_MSG_INIT: u8g_com_arduino_assign_pin_output_high(u8g); u8g_com_arduino_digital_write(u8g, U8G_PI_SCK, LOW); u8g_com_arduino_digital_write(u8g, U8G_PI_MOSI, LOW); break; case U8G_COM_MSG_STOP: break; case U8G_COM_MSG_RESET: if ( u8g->pin_list[U8G_PI_RESET] != U8G_PIN_NONE ) u8g_com_arduino_digital_write(u8g, U8G_PI_RESET, arg_val); break; case U8G_COM_MSG_CHIP_SELECT: if ( arg_val == 0 ) { /* disable */ u8g_com_arduino_digital_write(u8g, U8G_PI_CS, HIGH); } else { /* enable */ u8g_com_arduino_digital_write(u8g, U8G_PI_SCK, LOW); u8g_com_arduino_digital_write(u8g, U8G_PI_CS, LOW); } break; case U8G_COM_MSG_WRITE_BYTE: u8g_arduino_sw_spi_shift_out(u8g->pin_list[U8G_PI_MOSI], u8g->pin_list[U8G_PI_SCK], arg_val); break; case U8G_COM_MSG_WRITE_SEQ: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_arduino_sw_spi_shift_out(u8g->pin_list[U8G_PI_MOSI], u8g->pin_list[U8G_PI_SCK], *ptr++); arg_val--; } } break; case U8G_COM_MSG_WRITE_SEQ_P: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_arduino_sw_spi_shift_out(u8g->pin_list[U8G_PI_MOSI], u8g->pin_list[U8G_PI_SCK], u8g_pgm_read(ptr)); ptr++; arg_val--; } } break; case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */ u8g_com_arduino_digital_write(u8g, U8G_PI_A0, arg_val); break; } return 1; }
uint8_t u8g_com_arduino_t6963_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { switch(msg) { case U8G_COM_MSG_INIT: u8g->pin_list[U8G_PI_A0_STATE] = 0; u8g_com_arduino_t6963_init(u8g); /* setup the RW (equal to WR) pin as output and force it to high */ if ( u8g->pin_list[U8G_PI_WR] != U8G_PIN_NONE ) { pinMode(u8g->pin_list[U8G_PI_WR], OUTPUT); u8g_com_arduino_digital_write(u8g, U8G_PI_WR, HIGH); } /* set all pins (except WR pin) */ u8g_com_arduino_assign_pin_output_high(u8g); break; case U8G_COM_MSG_STOP: break; case U8G_COM_MSG_CHIP_SELECT: if ( arg_val == 0 ) { /* disable, active low chip select */ u8g_com_arduino_digital_write(u8g, U8G_PI_CS, HIGH); } else { /* enable */ u8g_com_arduino_digital_write(u8g, U8G_PI_CS, LOW); } break; case U8G_COM_MSG_WRITE_BYTE: if ( u8g->pin_list[U8G_PI_A0_STATE] == 0 ) { u8g_com_arduino_t6963_write_data(u8g, arg_val); } else { u8g_com_arduino_t6963_write_cmd(u8g, arg_val); } break; case U8G_COM_MSG_WRITE_SEQ: { register uint8_t *ptr = arg_ptr; u8g_com_arduino_t6963_write_cmd(u8g, 0x0b0); /* auto write */ while( arg_val > 0 ) { if ( u8g_com_arduino_t6963_write_auto_data(u8g, *ptr++) == 0 ) break; arg_val--; } u8g_com_arduino_t6963_write_cmd(u8g, 0x0b2); /* auto reset */ } break; case U8G_COM_MSG_WRITE_SEQ_P: { register uint8_t *ptr = arg_ptr; u8g_com_arduino_t6963_write_cmd(u8g, 0x0b0); /* auto write */ while( arg_val > 0 ) { if ( u8g_com_arduino_t6963_write_auto_data(u8g, u8g_pgm_read(ptr)) == 0 ) break; ptr++; arg_val--; } u8g_com_arduino_t6963_write_cmd(u8g, 0x0b2); /* auto reset */ } break; case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 1) or data mode (arg_val = 0) */ u8g->pin_list[U8G_PI_A0_STATE] = arg_val; //u8g_com_arduino_digital_write(u8g, U8G_PI_DI, arg_val); break; case U8G_COM_MSG_RESET: if ( u8g->pin_list[U8G_PI_RESET] != U8G_PIN_NONE ) u8g_com_arduino_digital_write(u8g, U8G_PI_RESET, arg_val); break; } return 1; }
uint8_t u8g_com_atxmega_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { switch(msg) { case U8G_COM_MSG_STOP: break; case U8G_COM_MSG_INIT: u8g_SetPIOutput(u8g, U8G_PI_CS); u8g_SetPIOutput(u8g, U8G_PI_A0); u8g_SetPIOutput(u8g, U8G_PI_RESET); //U8G_ATOMIC_START(); PORTC.DIR |= PIN4_bm | PIN5_bm | PIN7_bm; PORTC.DIR &= ~PIN6_bm; //U8G_ATOMIC_END(); u8g_SetPILevel(u8g, U8G_PI_CS, 1); SPIC.CTRL = 0; SPIC.CTRL = SPI_PRESCALER_DIV4_gc | // SPI prescaler. //SPI_CLK2X_bm | //SPI Clock double. SPI_ENABLE_bm | //Enable SPI module. //SPI_DORD_bm | //Data order. SPI_MASTER_bm | //SPI master. SPI_MODE_0_gc; // SPI mode. #ifdef U8G_HW_SPI_2X SPIC.CTRL |= SPI_CLK2X_bm; /* double speed, issue 89 */ #endif break; case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */ u8g_SetPILevel(u8g, U8G_PI_A0, arg_val); break; case U8G_COM_MSG_CHIP_SELECT: if ( arg_val == 0 ) { /* disable */ u8g_SetPILevel(u8g, U8G_PI_CS, 1); } else { //PORTB &= ~_BV(5); /* SCK = 0 */ PORTC.OUT &= ~PIN7_bm; /* enable */ u8g_SetPILevel(u8g, U8G_PI_CS, 0); /* CS = 0 (low active) */ } break; case U8G_COM_MSG_RESET: u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val); break; case U8G_COM_MSG_WRITE_BYTE: u8g_atxmega_spi_out(arg_val); break; case U8G_COM_MSG_WRITE_SEQ: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_atxmega_spi_out(*ptr++); arg_val--; } } break; case U8G_COM_MSG_WRITE_SEQ_P: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_atxmega_spi_out(u8g_pgm_read(ptr)); ptr++; arg_val--; } } break; } return 1; }
/* sequence := { direct_value | escape_sequence } direct_value := 0..254 escape_sequence := value_255 | sequence_end | delay | adr | cs | not_used value_255 := 255 255 sequence_end = 255 254 delay := 255 0..127 adr := 255 0x0e0 .. 0x0ef cs := 255 0x0d0 .. 0x0df not_used := 255 101..254 #define U8G_ESC_DLY(x) 255, ((x) & 0x7f) #define U8G_ESC_CS(x) 255, (0xd0 | ((x)&0x0f)) #define U8G_ESC_ADR(x) 255, (0xe0 | ((x)&0x0f)) #define U8G_ESC_VCC(x) 255, (0xbe | ((x)&0x01)) #define U8G_ESC_END 255, 254 #define U8G_ESC_255 255, 255 #define U8G_ESC_RST(x) 255, (0xc0 | ((x)&0x0f)) */ uint8_t u8g_WriteEscSeqP(u8g_t *u8g, u8g_dev_t *dev, const uint8_t *esc_seq) { uint8_t is_escape = 0; uint8_t value; for(;;) { value = u8g_pgm_read(esc_seq); if ( is_escape == 0 ) { if ( value != 255 ) { if ( u8g_WriteByte(u8g, dev, value) == 0 ) return 0; } else { is_escape = 1; } } else { if ( value == 255 ) { if ( u8g_WriteByte(u8g, dev, value) == 0 ) return 0; } else if ( value == 254 ) { break; } else if ( value >= 0x0f0 ) { /* not yet used, do nothing */ } else if ( value >= 0xe0 ) { u8g_SetAddress(u8g, dev, value & 0x0f); } else if ( value >= 0xd0 ) { u8g_SetChipSelect(u8g, dev, value & 0x0f); } else if ( value >= 0xc0 ) { u8g_SetResetLow(u8g, dev); value &= 0x0f; value <<= 4; value+=2; u8g_Delay(value); u8g_SetResetHigh(u8g, dev); u8g_Delay(value); } else if ( value >= 0xbe ) { /* not yet implemented */ /* u8g_SetVCC(u8g, dev, value & 0x01); */ } else if ( value <= 127 ) { u8g_Delay(value); } is_escape = 0; } esc_seq++; } return 1; }
uint8_t u8g_com_atmega_st7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { switch(msg) { case U8G_COM_MSG_INIT: u8g_SetPIOutput(u8g, U8G_PI_CS); //u8g_SetPIOutput(u8g, U8G_PI_A0); U8G_ATOMIC_START(); DDRB |= U8G_ATMEGA_HW_SPI_MOSI_PIN; DDRB |= U8G_ATMEGA_HW_SPI_SCK_PIN; DDRB |= U8G_ATMEGA_HW_SPI_SLAVE_SELECT_PIN; PORTB &= ~U8G_ATMEGA_HW_SPI_MOSI_PIN; PORTB &= ~U8G_ATMEGA_HW_SPI_SCK_PIN; U8G_ATOMIC_END(); u8g_SetPILevel(u8g, U8G_PI_CS, 1); /* SPR1 SPR0 0 0 fclk/4 0 1 fclk/16 1 0 fclk/64 1 1 fclk/128 */ SPCR = 0; /* maybe set CPOL and CPHA to 1 */ /* 20 Dez 2012: did set CPOL and CPHA to 1 in Arduino variant! */ /* 24 Jan 2014: implemented, see also issue 221 */ SPCR = (1<<SPE) | (1<<MSTR)|(0<<SPR1)|(0<<SPR0)|(1<<CPOL)|(1<<CPHA); #ifdef U8G_HW_SPI_2X SPSR = (1 << SPI2X); /* double speed, issue 89 */ #endif u8g->pin_list[U8G_PI_A0_STATE] = 0; /* inital RS state: command mode */ break; case U8G_COM_MSG_STOP: break; case U8G_COM_MSG_RESET: u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val); break; case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */ u8g->pin_list[U8G_PI_A0_STATE] = arg_val; break; case U8G_COM_MSG_CHIP_SELECT: if ( arg_val == 0 ) { /* disable, note: the st7920 has an active high chip select */ u8g_SetPILevel(u8g, U8G_PI_CS, 0); } else { /* u8g_SetPILevel(u8g, U8G_PI_SCK, 0 ); */ /* enable */ u8g_SetPILevel(u8g, U8G_PI_CS, 1); /* CS = 1 (high active) */ } break; case U8G_COM_MSG_WRITE_BYTE: u8g_com_atmega_st7920_write_byte_hw_spi(u8g, u8g->pin_list[U8G_PI_A0_STATE], arg_val); //u8g->pin_list[U8G_PI_A0_STATE] = 2; break; case U8G_COM_MSG_WRITE_SEQ: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_com_atmega_st7920_write_byte_hw_spi(u8g, u8g->pin_list[U8G_PI_A0_STATE], *ptr++); //u8g->pin_list[U8G_PI_A0_STATE] = 2; arg_val--; } } break; case U8G_COM_MSG_WRITE_SEQ_P: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_com_atmega_st7920_write_byte_hw_spi(u8g, u8g->pin_list[U8G_PI_A0_STATE], u8g_pgm_read(ptr)); //u8g->pin_list[U8G_PI_A0_STATE] = 2; ptr++; arg_val--; } } break; } return 1; }
/* Find (with some speed optimization) and return a pointer to the glyph data structure Also uncompress (format 1) and copy the content of the data structure to the u8g structure */ u8g_glyph_t u8g_GetGlyph(u8g_t *u8g, uint8_t requested_encoding) { uint8_t *p = (uint8_t *)(u8g->font); uint8_t font_format = u8g_font_GetFormat(u8g->font); uint8_t data_structure_size = u8g_font_GetFontGlyphStructureSize(u8g->font); uint8_t start, end; uint16_t pos; uint8_t i; uint8_t mask = 255; if ( font_format == 1 ) mask = 15; start = u8g_font_GetFontStartEncoding(u8g->font); end = u8g_font_GetFontEndEncoding(u8g->font); pos = u8g_font_GetEncoding97Pos(u8g->font); if ( requested_encoding >= 97 && pos > 0 ) { p+= pos; start = 97; } else { pos = u8g_font_GetEncoding65Pos(u8g->font); if ( requested_encoding >= 65 && pos > 0 ) { p+= pos; start = 65; } else p += U8G_FONT_DATA_STRUCT_SIZE; /* skip font general information */ } if ( requested_encoding > end ) { u8g_FillEmptyGlyphCache(u8g); return NULL; /* not found */ } i = start; if ( i <= end ) { for(;;) { if ( u8g_pgm_read((u8g_pgm_uint8_t *)(p)) == 255 ) { p += 1; } else { if ( i == requested_encoding ) { u8g_CopyGlyphDataToCache(u8g, p); return p; } p += u8g_pgm_read( ((u8g_pgm_uint8_t *)(p)) + 2 ) & mask; p += data_structure_size; } if ( i == end ) break; i++; } } u8g_FillEmptyGlyphCache(u8g); return NULL; }
uint8_t u8g_com_arduino_parallel_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { switch(msg) { case U8G_COM_MSG_INIT: /* setup the RW pin as output and force it to low */ if ( u8g->pin_list[U8G_PI_RW] != U8G_PIN_NONE ) { pinMode(u8g->pin_list[U8G_PI_RW], OUTPUT); u8g_com_arduino_digital_write(u8g, U8G_PI_RW, LOW); } /* set all pins (except RW pin) */ u8g_com_arduino_assign_pin_output_high(u8g); break; case U8G_COM_MSG_STOP: break; case U8G_COM_MSG_CHIP_SELECT: if ( arg_val == 0 ) { /* disable */ u8g_com_arduino_digital_write(u8g, U8G_PI_CS1, HIGH); u8g_com_arduino_digital_write(u8g, U8G_PI_CS2, HIGH); } else if ( arg_val == 1 ) { /* enable */ u8g_com_arduino_digital_write(u8g, U8G_PI_CS1, LOW); u8g_com_arduino_digital_write(u8g, U8G_PI_CS2, HIGH); } else if ( arg_val == 2 ) { /* enable */ u8g_com_arduino_digital_write(u8g, U8G_PI_CS1, HIGH); u8g_com_arduino_digital_write(u8g, U8G_PI_CS2, LOW); } else { /* enable */ u8g_com_arduino_digital_write(u8g, U8G_PI_CS1, LOW); u8g_com_arduino_digital_write(u8g, U8G_PI_CS2, LOW); } break; case U8G_COM_MSG_WRITE_BYTE: u8g_com_arduino_parallel_write(u8g, arg_val); break; case U8G_COM_MSG_WRITE_SEQ: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_com_arduino_parallel_write(u8g, *ptr++); arg_val--; } } break; case U8G_COM_MSG_WRITE_SEQ_P: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_com_arduino_parallel_write(u8g, u8g_pgm_read(ptr)); ptr++; arg_val--; } } break; case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */ u8g_com_arduino_digital_write(u8g, U8G_PI_DI, arg_val); break; case U8G_COM_MSG_RESET: if ( u8g->pin_list[U8G_PI_RESET] != U8G_PIN_NONE ) u8g_com_arduino_digital_write(u8g, U8G_PI_RESET, arg_val); break; } return 1; }
uint8_t u8g_com_rx_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { /* Conditions: Channel not yet open. */ uint8_t chan = 0; rspi_chnl_settings_t my_config; rspi_cmd_baud_t my_setbaud_struct; rspi_err_t rspi_result; switch(msg) { case U8G_COM_MSG_INIT: my_config.gpio_ssl = RSPI_IF_MODE_3WIRE; my_config.master_slave_mode = RSPI_MS_MODE_MASTER; my_config.bps_target = 1000000; // Bit rate in bits-per-second. rspi_result = R_RSPI_Open(chan, &my_config, rspi_callback, &handle ); if (RSPI_SUCCESS != rspi_result) { while(1); } my_setbaud_struct.bps_target = 1000000; rspi_result = R_RSPI_Control(handle, RSPI_CMD_SET_BAUD, &my_setbaud_struct); if (RSPI_SUCCESS != rspi_result) { while(1); } break; case U8G_COM_MSG_STOP: break; case U8G_COM_MSG_CHIP_SELECT: if ( arg_val == 0 ) { /* disable, note: the st7920 has an active high chip select */ LCD_CS = 0; } else { /* enable */ LCD_CS = 1; } break; case U8G_COM_MSG_WRITE_BYTE: u8g_com_rx_st7920_write_byte_hw_spi(u8g, u8g->pin_list[U8G_PI_A0_STATE], arg_val); break; case U8G_COM_MSG_WRITE_SEQ: u8g_com_rx_st7920_write_byte_hw_spi_seq(u8g, u8g->pin_list[U8G_PI_A0_STATE], (uint8_t *)arg_ptr, arg_val); break; case U8G_COM_MSG_WRITE_SEQ_P: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_com_rx_st7920_write_byte_hw_spi(u8g, u8g->pin_list[U8G_PI_A0_STATE], u8g_pgm_read(ptr) ); // u8g->pin_list[U8G_PI_A0_STATE] = 2; ptr++; arg_val--; } } break; case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */ u8g->pin_list[U8G_PI_A0_STATE] = arg_val; break; } return 1; }
uint8_t u8g_com_arduino_st7920_custom_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { switch(msg) { case U8G_COM_MSG_INIT: u8g_com_arduino_assign_pin_output_high(u8g); u8g_com_arduino_digital_write(u8g, U8G_PI_CS, LOW); // u8g_com_arduino_digital_write(u8g, U8G_PI_SCK, LOW); u8g_com_arduino_digital_write(u8g, U8G_PI_SCK, HIGH); u8g_com_arduino_digital_write(u8g, U8G_PI_MOSI, LOW); u8g_com_arduino_init_shift_out(u8g->pin_list[U8G_PI_MOSI], u8g->pin_list[U8G_PI_SCK]); u8g->pin_list[U8G_PI_A0_STATE] = 0; /* inital RS state: command mode */ break; case U8G_COM_MSG_STOP: break; case U8G_COM_MSG_RESET: if ( u8g->pin_list[U8G_PI_RESET] != U8G_PIN_NONE ) u8g_com_arduino_digital_write(u8g, U8G_PI_RESET, arg_val); break; case U8G_COM_MSG_CHIP_SELECT: if ( arg_val == 0 ) { /* disable, note: the st7920 has an active high chip select */ u8g_com_arduino_digital_write(u8g, U8G_PI_CS, LOW); } else { /* enable */ //u8g_com_arduino_digital_write(u8g, U8G_PI_SCK, HIGH); u8g_com_arduino_digital_write(u8g, U8G_PI_CS, HIGH); } break; case U8G_COM_MSG_WRITE_BYTE: u8g_com_arduino_st7920_write_byte( u8g->pin_list[U8G_PI_A0_STATE], arg_val); //u8g->pin_list[U8G_PI_A0_STATE] = 2; //u8g_arduino_sw_spi_shift_out(u8g->pin_list[U8G_PI_MOSI], u8g->pin_list[U8G_PI_SCK], arg_val); break; case U8G_COM_MSG_WRITE_SEQ: u8g_com_arduino_st7920_write_byte_seq(u8g->pin_list[U8G_PI_A0_STATE], (uint8_t *)arg_ptr, arg_val); break; case U8G_COM_MSG_WRITE_SEQ_P: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_com_arduino_st7920_write_byte(u8g->pin_list[U8G_PI_A0_STATE], u8g_pgm_read(ptr) ); //u8g->pin_list[U8G_PI_A0_STATE] = 2; ptr++; arg_val--; } } break; case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */ u8g->pin_list[U8G_PI_A0_STATE] = arg_val; break; } return 1; }
uint8_t u8g_com_atmega_parallel_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { switch(msg) { case U8G_COM_MSG_INIT: /* setup the RW pin as output and force it to low */ u8g_SetPIOutput(u8g, U8G_PI_RW); u8g_SetPILevel(u8g, U8G_PI_RW, 0); u8g_SetPIOutput(u8g, U8G_PI_D0); u8g_SetPIOutput(u8g, U8G_PI_D1); u8g_SetPIOutput(u8g, U8G_PI_D2); u8g_SetPIOutput(u8g, U8G_PI_D3); u8g_SetPIOutput(u8g, U8G_PI_D4); u8g_SetPIOutput(u8g, U8G_PI_D5); u8g_SetPIOutput(u8g, U8G_PI_D6); u8g_SetPIOutput(u8g, U8G_PI_D7); u8g_SetPIOutput(u8g, U8G_PI_EN); u8g_SetPIOutput(u8g, U8G_PI_CS1); u8g_SetPIOutput(u8g, U8G_PI_CS2); u8g_SetPIOutput(u8g, U8G_PI_DI); u8g_SetPILevel(u8g, U8G_PI_CS1, 1); u8g_SetPILevel(u8g, U8G_PI_CS2, 1); break; case U8G_COM_MSG_STOP: break; case U8G_COM_MSG_CHIP_SELECT: if ( arg_val == 0 ) { /* disable */ u8g_SetPILevel(u8g, U8G_PI_CS1, 1); u8g_SetPILevel(u8g, U8G_PI_CS2, 1); } else if ( arg_val == 1 ) { /* enable */ u8g_SetPILevel(u8g, U8G_PI_CS1, 0); u8g_SetPILevel(u8g, U8G_PI_CS2, 1); } else if ( arg_val == 2 ) { /* enable */ u8g_SetPILevel(u8g, U8G_PI_CS1, 1); u8g_SetPILevel(u8g, U8G_PI_CS2, 0); } else { /* enable */ u8g_SetPILevel(u8g, U8G_PI_CS1, 0); u8g_SetPILevel(u8g, U8G_PI_CS2, 0); } break; case U8G_COM_MSG_WRITE_BYTE: u8g_com_atmega_parallel_write(u8g, arg_val); break; case U8G_COM_MSG_WRITE_SEQ: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_com_atmega_parallel_write(u8g, *ptr++); arg_val--; } } break; case U8G_COM_MSG_WRITE_SEQ_P: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { u8g_com_atmega_parallel_write(u8g, u8g_pgm_read(ptr)); ptr++; arg_val--; } } break; case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */ u8g_SetPILevel(u8g, U8G_PI_DI, arg_val); break; } return 1; }