/** * \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)); } }
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(); }
/** * \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; }
/** * \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; }
/** * \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(); }