/**
 * \brief Draws a string located in program memory to the display
 *
 * This function will draw a string located in program memory to the display,
 * this differs from gfx_mono_draw_string() by using constant string data from
 * the program memory instead of string data in RAM.
 *
 * Using program memory for constant strings will reduce the applications need
 * for RAM, and thus lower the overall size footprint.
 *
 * \param str       Pointer to string located in program memory
 * \param x         X coordinate on screen.
 * \param y         Y coordinate on screen.
 * \param font      Font to draw string in
 */
void gfx_mono_draw_progmem_string(char PROGMEM_PTR_T str, gfx_coord_t x,
		gfx_coord_t y, const struct font *font)
{
	char temp_char;

	/* Sanity check on parameters, assert if str or font is NULL. */
	Assert(str != NULL);
	Assert(font != NULL);

	/* Save X in order to know where to return to on CR. */
	const gfx_coord_t start_of_string_position_x = x;

	/* Draw characters until trailing null byte */
	temp_char = PROGMEM_READ_BYTE((uint8_t PROGMEM_PTR_T)str);

	while (temp_char) {
		/* Handle '\n' as newline, draw normal characters. */
		if (temp_char == '\n') {
			x = start_of_string_position_x;
			y += font->height + 1;
		} else if (temp_char == '\r') {
			/* Skip '\r' characters. */
		} else {
			gfx_mono_draw_char(temp_char, x, y, font);
			x += font->width;
		}

		temp_char = PROGMEM_READ_BYTE((uint8_t PROGMEM_PTR_T)(++str));
	}
}
示例#2
0
void rf230_frame_write_P(uint8_t length, PROGMEM_BYTE_ARRAY_T wr_buffer) {
    ENTER_CRITICAL_REGION();
 
    RF230_SS_LOW();
    
    /*SEND FRAME WRITE COMMAND AND FRAME LENGTH.*/
    RF230_SPI_DATA_REG = RF230_TRX_CMD_FW;
    RF230_WAIT_FOR_SPI_TX_COMPLETE();
    uint8_t dummy_read = RF230_SPI_DATA_REG;
        
    RF230_SPI_DATA_REG = length;
    RF230_WAIT_FOR_SPI_TX_COMPLETE();
    dummy_read = RF230_SPI_DATA_REG;
    
    /*Download to the Frame Buffer. */
    do {
        
        RF230_SPI_DATA_REG = PROGMEM_READ_BYTE(wr_buffer);
        wr_buffer++;
        --length;
        
        RF230_WAIT_FOR_SPI_TX_COMPLETE();
        
        dummy_read = RF230_SPI_DATA_REG;
    } while (length != 0);
    
    RF230_SS_HIGH();
    
    LEAVE_CRITICAL_REGION();
}
示例#3
0
/**
 * \brief Compute 32-bit CRC for Flash address range using table lookup.
 *
 * This function returns the 32-bit CRC of the specified Flash address range.
 *
 * \param origDataptr Address of Flash location to start CRC computation at.
 * \param numBytes Number of bytes of the data.
 * \param pchecksum Pointer to the checksum stored in EEPROM.
 *
 * \note No sanity checking of addresses is done.
 */
uint32_t CLASSB_CRC32_Flash_SW(flashptr_t origDataptr, crcbytenum_t numBytes,
		eeprom_uint32ptr_t pchecksum)
{
	flash_uint8ptr_t dataptr = origDataptr;
	uint32_t remainder = CRC32_INITIAL_REMAINDER;
	uint8_t dataTemp;

	/* Compute CRC for the specified data. */
	for (; numBytes != 0; numBytes--) {

#if (PROGMEM_SIZE >= 0x10000UL)
		dataTemp = PROGMEM_READ_BYTE(dataptr++);
#else
		dataTemp = PROGMEM_READ_BYTE(dataptr++);
#endif

#if defined(CRC_USE_32BIT_LOOKUP_TABLE)
		CLASSB_CRC_REFL_TABLE_32(dataTemp, remainder,
				CLASSB_CRC32Table);
#else
		CLASSB_CRC_REFL(dataTemp, remainder, CRC32_POLYNOMIAL, 32);
#endif
	}

#ifdef CRC32_FINAL_XOR_VALUE
	remainder ^= CRC32_FINAL_XOR_VALUE;
#endif

#if defined(__ICCAVR__)
	/* Compare checksums and handle error if necessary. */
	if (remainder != *pchecksum) {
		CLASSB_ERROR_HANDLER_CRC();
	}
#elif defined(__GCC__)
	/* Ensure that EEPROM is memory mapped. */
	CLASSB_EEMAP_BEGIN();
	/* Compare checksums and handle error if necessary. */
	if (remainder != (*(eeprom_uint32ptr_t)(MAPPED_EEPROM_START
			+ (uintptr_t) pchecksum))) {
		CLASSB_ERROR_HANDLER_CRC();
	}
	/* Disable memory mapping of EEPROM, if necessary. */
	CLASSB_EEMAP_END();
#endif

	return remainder;
}
示例#4
0
/**
 * \internal
 * \brief Helper function that draws a character from a font in progmem
 *        to the display
 *
 * This function will first calculate the start offset in the font character
 * data before iterating over the specific character data.
 *
 * Only pixels in the character that should be enabled are done so, the caller
 * is required to prepare the drawing area before printing a character to it.
 * This is done by the gfx_draw_string() and gfx_draw_progmem_string()
 * functions.
 *
 * \param ch       Character to be drawn
 * \param x        X coordinate on screen.
 * \param y        Y coordinate on screen.
 * \param font     Font to draw character in
 * \param color    Foreground color to draw the character in
 */
static void gfx_draw_inverted_char_progmem(const char ch, const gfx_coord_t x,
		const gfx_coord_t y, const struct font *font,
		const gfx_color_t color)
{
	uint8_t PROGMEM_PTR_T glyph_data;
	uint16_t glyph_data_offset;
	uint8_t char_row_size;
	uint8_t rows_left;
	uint8_t i;

	/* Sanity check on parameters, assert if font is NULL. */
	Assert(font != NULL);

	gfx_coord_t inc_x = x;
	gfx_coord_t inc_y = y;

//	char_row_size = font->width / CONFIG_FONT_PIXELS_PER_BYTE;
//	if (font->width % CONFIG_FONT_PIXELS_PER_BYTE) {
//		char_row_size++;
//	}

	char_row_size = font->height / CONFIG_FONT_PIXELS_PER_BYTE;
	
	if (font->height % CONFIG_FONT_PIXELS_PER_BYTE) {
		char_row_size++;
	}

	glyph_data_offset = char_row_size * font->width *
			((uint8_t)ch - font->first_char);
	glyph_data = font->data.progmem + glyph_data_offset;
	rows_left = font->width;

	do {
		uint8_t glyph_byte = 0;
		uint8_t pixelsToDraw = font->height;

		for (i = pixelsToDraw; i >0; i--) {
			if (i % CONFIG_FONT_PIXELS_PER_BYTE == 0) {
				glyph_byte = PROGMEM_READ_BYTE(glyph_data);
				glyph_data++;
			}

			if ((glyph_byte & 0x80)) {
				gfx_draw_pixel(inc_x, inc_y, color);
			//	gfx_draw_pixel(inc_y, inc_x, color);
			}

//			inc_x += 1;
			inc_y += 1;
			glyph_byte <<= 1;
		}

		inc_x += 1;
		inc_y = y;
		rows_left--;
	} while (rows_left > 0);
}
/**
 * \brief Compute 16-bit CRC for Flash address range using hardware CRC module.
 *
 * This function returns the 16-bit CRC of the specified Flash address range.
 *
 * \param origDataptr Address of Flash location to start CRC computation at.
 * \param numBytes Number of bytes of the data.
 * \param pchecksum Pointer to the checksum stored in EEPROM.
 *
 * \note 16-bit flash CRC is much slower than 32-bit for flash checking.
 * \note No sanity checking of addresses is done.
 */
uint16_t CLASSB_CRC16_Flash_HW(flashptr_t origDataptr, crcbytenum_t numBytes,
		eeprom_uint16ptr_t pchecksum)
{
	uint32_t checksum;
	flash_uint8ptr_t dataptr = origDataptr;
	uint8_t dataTemp;

	crc_set_initial_value(CRC16_INITIAL_REMAINDER);

	crc_io_checksum_byte_start(CRC_16BIT);

	/* Compute CRC for the specified data. */
	for (; numBytes != 0; numBytes--) {
#if (PROGMEM_SIZE >= 0x10000UL)
		dataTemp = PROGMEM_READ_BYTE(dataptr++);
#else
		dataTemp = PROGMEM_READ_BYTE(dataptr++);
#endif
		crc_io_checksum_byte_add(dataTemp);
	}

	checksum = crc_io_checksum_byte_stop();

#if defined(__ICCAVR__)
	/* Compare checksums and handle error if necessary. */
	if (checksum != *pchecksum) {
		CLASSB_ERROR_HANDLER_CRC();
	}
#elif defined(__GCC__)
	/* Ensure that EEPROM is memory mapped. */
	CLASSB_EEMAP_BEGIN();
	/* Compare checksums and handle error if necessary. */
	if (checksum != (*(eeprom_uint16ptr_t)(MAPPED_EEPROM_START
			+ (uintptr_t)pchecksum))) {
		CLASSB_ERROR_HANDLER_CRC();
	}
	/* Disable memory mapping of EEPROM, if necessary. */
	CLASSB_EEMAP_END();
#endif
	/* Return 16 bits */
	return checksum & (uint32_t)0x0000FFFF;
}
/**
 * \brief Computes the bounding box of a string located in program memory
 *
 * \note If string is empty the returned width will be 1 pixel and the height
 * equal to the font height.
 *
 * \param str      String in program memory to calculate bounding box for
 * \param font     Font used
 * \param width    Pointer to width result
 * \param height   Pointer to height result
 */
void gfx_mono_get_progmem_string_bounding_box(char PROGMEM_PTR_T str,
		const struct font *font, gfx_coord_t *width,
		gfx_coord_t *height)
{
	gfx_coord_t font_width = font->width;
	gfx_coord_t font_height = font->height;

	char temp_char;
	gfx_coord_t max_width = 1;
	gfx_coord_t max_height = font_height;
	gfx_coord_t x = 0;

	/* Sanity check on parameters, assert if str or font is NULL. */
	Assert(str != NULL);
	Assert(font != NULL);

	/* Handle each character until trailing null byte */
	temp_char = PROGMEM_READ_BYTE((uint8_t PROGMEM_PTR_T)str);

	while (temp_char) {
		/* Handle '\n' as newline, draw normal characters. */
		if (temp_char == '\n') {
			x = 0;
			max_height += font_height;
		} else if (*str == '\r') {
			/* Skip '\r' characters. */
		} else {
			x += font_width;
			if (x > max_width) {
				max_width = x;
			}
		}

		temp_char = PROGMEM_READ_BYTE((uint8_t PROGMEM_PTR_T)(++str));
	}

	/* Return values through references */
	*width = max_width;
	*height = max_height;
}
示例#7
0
/**
 * \brief Draws an aligned string located in program memory to the display
 *
 * This function will draw a string located in program memory to the display
 * with the specified alignment. This differs from gfx_draw_aligned_string() by
 * using constant string data from the program memory instead of string data in
 * RAM.
 *
 * \param str         Pointer to string located in program memory
 * \param x           X coordinate on screen.
 * \param y           Y coordinate on screen.
 * \param font        Font to draw string in
 * \param bg_color    Background color to draw behind the text string
 * \param text_color  Foreground color to draw the text string in
 * \param text_pos    Position of the coordinate relative to the text paragraph
 * \param text_align  Alignment of text lines within the paragraph bounding box
 */
void gfx_draw_progmem_string_aligned(char PROGMEM_PTR_T str,
		gfx_coord_t x, gfx_coord_t y, const struct font *font,
		const gfx_color_t bg_color, const gfx_color_t text_color,
		enum gfx_text_position text_pos,
		enum gfx_text_alignment text_align)
{
	gfx_coord_t bounding_x, bounding_y;
	char curr_str_char;

	/* Sanity check on parameters, assert if str or font is NULL. */
	Assert(str != NULL);
	Assert(font != NULL);

	/* Retrieve the bounding box of the overall text paragraph */
	gfx_get_progmem_string_bounding_box(str, font,
			&bounding_x, &bounding_y);

	/* Move the Y coordinate according to the Y positional setting given */
	if (text_pos & TEXT_POS_CENTER_Y) {
		y -= bounding_y / 2;
	} else if (text_pos & TEXT_POS_BOTTOM) {
		y -= bounding_y;
	}

	/* Move the X coordinate according to the X positional setting given */
	if (text_pos & TEXT_POS_CENTER_X) {
		x -= bounding_x / 2;
	} else if (text_pos & TEXT_POS_RIGHT) {
		x -= bounding_x;
	}

	curr_str_char = PROGMEM_READ_BYTE((uint8_t PROGMEM_PTR_T)str);

	/* Need to draw each line of the text paragraph individually */
	while (curr_str_char != '\0') {
		char PROGMEM_PTR_T curr_line_text = str;
		char curr_line_char;
		gfx_coord_t curr_line_x = x;
		gfx_coord_t curr_line_width = 0;

		/* Determine width of current line in the the paragraph */
		do {
			if (curr_str_char == '\n') {
				curr_str_char
					= PROGMEM_READ_BYTE(
						(uint8_t PROGMEM_PTR_T)(++str));
				break;
			} else if (curr_str_char != '\r') {
				curr_line_width += font->width;
			}

			curr_str_char = PROGMEM_READ_BYTE(
					(uint8_t PROGMEM_PTR_T)(++str));
		} while (curr_str_char != '\0');

		/* Move the line starting X coordinate on the display according
		 * to the line width and the specified text alignment parameter
		 */
		if (text_align == TEXT_ALIGN_CENTER) {
			curr_line_x += (bounding_x / 2) - (curr_line_width / 2);
		} else if (text_align == TEXT_ALIGN_RIGHT) {
			curr_line_x += bounding_x - curr_line_width;
		}

		curr_line_char = PROGMEM_READ_BYTE(
				(uint8_t PROGMEM_PTR_T)curr_line_text);

		/* Draw current line to the display with the calculated
		 * coordinates
		 */
		do {
			if (*curr_line_text == '\n') {
				break;
			} else if (*curr_line_text != '\r') {
				gfx_draw_char(*curr_line_text, curr_line_x, y,
						font, bg_color, text_color);

				/* Step to the next character display X
				 *coordinate
				 */
				curr_line_x += font->width;
			}

			curr_line_char = PROGMEM_READ_BYTE(
					(uint8_t PROGMEM_PTR_T)(++curr_line_text));
		} while (curr_line_char != '\0');

		/* Step to the next Y line coordinate for the next line in
		 * paragraph
		 */
		y += font->height + 1;
	}
}
/*
 * Manage the GET DESCRIPTOR request. The device descriptor,
 * the configuration descriptor and the device qualifier are supported. All
 * other descriptors must be supported by the specificGetDescriptor
 * function.
 * Only 1 configuration is supported.
 */
void
OSUsbDeviceImpl::usb_get_descriptor(void)
{
  unsigned short wLength;
  unsigned char descriptor_type;
  unsigned char descriptor_index;
  //U8 dummy;
  unsigned short dummy16;
  unsigned char nb_byte;

  zlp = false; /* no zero length packet */
  descriptor_index = OSUsbDeviceImpl::readByte(); /* read LSB of wValue    */
  descriptor_type = OSUsbDeviceImpl::readByte(); /* read MSB of wValue    */

#if defined(DEBUG) && defined(OS_DEBUG_OSUSBDEVICE_REQUEST)
  OSDeviceDebug::putString("GET_DESCRIPTOR");
  OSDeviceDebug::putString(" ty/ix=");
  OSDeviceDebug::putHex(descriptor_type);
  OSDeviceDebug::putString("/");
  OSDeviceDebug::putHex(descriptor_index);
  OSDeviceDebug::putString(" ");
#endif

  switch (descriptor_type)
    {
  case DEVICE_DESCRIPTOR: // 0x01
#if defined(DEBUG) && defined(OS_DEBUG_OSUSBDEVICE_REQUEST)
    OSDeviceDebug::putString("DEVICE");
#endif
    //OSDeviceDebug::putNewLine();
    data_to_transfer = sizeof(usb_dev_desc); //!< sizeof(usb_user_device_descriptor);
    pbuffer = &(usb_dev_desc);
    break;

  case CONFIGURATION_DESCRIPTOR: // 0x02
#if defined(DEBUG) && defined(OS_DEBUG_OSUSBDEVICE_REQUEST)
    OSDeviceDebug::putString("CONFIGURATION");
#endif
    //OSDeviceDebug::putNewLine();
#if defined(OS_INCLUDE_USB_CDC_DUAL_CONFIGURATION)

    if (descriptor_index == 0)
      {
        data_to_transfer = sizeof(usb_conf_desc);
        pbuffer = &usb_conf_desc;
      }
    else if (descriptor_index == 1)
      {
        data_to_transfer = sizeof(usb_conf2_desc);
        pbuffer = &usb_conf2_desc;
      }
    else
      {
        OSUsbDeviceImpl::Usb_enable_stall_handshake();
        OSUsbDeviceImpl::Usb_ack_receive_setup();
        return;
      }
#else
    data_to_transfer = sizeof(usb_conf2_desc);
    pbuffer = &usb_conf2_desc;
#endif
    break;

  default:
    if (specificGetDescriptor(descriptor_type, descriptor_index))
      break;

    OSUsbDeviceImpl::Usb_enable_stall_handshake();
    OSUsbDeviceImpl::Usb_ack_receive_setup();
    return;
    }

  dummy16 = OSUsbDevice::readWord(); // don't care of wIndex field
  wLength = OSUsbDevice::readWord(); // read wLength
#if defined(DEBUG) && defined(OS_DEBUG_OSUSBDEVICE_REQUEST)
  OSDeviceDebug::putString(" ix=");
  OSDeviceDebug::putHex(dummy16);
  OSDeviceDebug::putString(" len=");
  OSDeviceDebug::putHex(wLength);
  OSDeviceDebug::putNewLine();
#endif

  OSUsbDeviceImpl::Usb_ack_receive_setup(); // clear the receive setup flag

  if (wLength > data_to_transfer)
    {
      if ((data_to_transfer % EP_CONTROL_LENGTH) == 0)
        {
          zlp = true;
        }
      else
        {
          zlp = false;
        } // no need of zero length packet
    }
  else
    {
      data_to_transfer = (unsigned char) wLength; // send only requested number of data
    }

  while ((data_to_transfer != 0) && (!OSUsbDeviceImpl::isInterruptReceiveOut()))
    {
      while (!OSUsbDeviceImpl::Is_usb_read_control_enabled())
        {
          ;
        }

      nb_byte = 0;
      while (data_to_transfer != 0) // Send data until necessary
        {
          if (nb_byte++ == EP_CONTROL_LENGTH) // Check endpoint 0 size
            {
              break;
            }
#if defined(OS_INCLUDE_SEPARATE_PROGMEM)
          // assumes devices descriptors are stored in the lower 64Kbytes of on-chip flash memory
          OSUsbDeviceImpl::writeByte(PROGMEM_READ_BYTE(pbuffer));
          //OSUsbDeviceImpl::writeByte(pgm_read_byte_near((unsigned int) pbuffer));
#else
          OSUsbDeviceImpl::writeByte(*((unsigned char*) pbuffer));
#endif
          pbuffer = (unsigned char*) pbuffer + 1;

          data_to_transfer--;
        }
      OSUsbDeviceImpl::Usb_send_control_in();
    }

  OSUsbDeviceImpl::Usb_send_control_in();

  if (OSUsbDeviceImpl::isInterruptReceiveOut())
    {
      OSUsbDeviceImpl::Usb_ack_receive_out();
      return;
    } // abort from Host

  if (zlp)
    {
      while (!OSUsbDeviceImpl::Is_usb_read_control_enabled())
        {
          ;
        }
      OSUsbDeviceImpl::Usb_send_control_in();
    }

  while (!OSUsbDeviceImpl::isInterruptReceiveOut())
    {
      ;
    }
  OSUsbDeviceImpl::Usb_ack_receive_out();
}