/** * @brief Scroll vertically a section of the screen. * @note Optional. * @note If x,y + cx,cy is off the screen, the result is undefined. * @note If lines is >= cy, it is equivelent to a area fill with bgcolor. * * @param[in] x, y The start of the area to be scrolled * @param[in] cx, cy The size of the area to be scrolled * @param[in] lines The number of lines to scroll (Can be positive or negative) * @param[in] bgcolor The color to fill the newly exposed area. * * @notapi */ void GDISP_LLD(verticalscroll)(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { /* This is marked as "TODO: Test this" in the original GLCD driver. * For now we just leave the GDISP_HARDWARE_SCROLL off. */ static color_t buf[((SCREEN_HEIGHT > SCREEN_WIDTH ) ? SCREEN_HEIGHT : SCREEN_WIDTH)]; coord_t row0, row1; unsigned i, gap, abslines; abslines = lines < 0 ? -lines : lines; #if GDISP_NEED_VALIDATION if (cx < 1 || cy < 1 || x >= GDISP.Width || y >= GDISP.Height) return; if (x+cx > GDISP.Width) cx = GDISP.Width - x; if (y+cy > GDISP.Height) cy = GDISP.Height - y; #endif if (!abslines) return; if (abslines >= cy) { abslines = cy; gap = 0; } else { gap = cy - abslines; for(i = 0; i < gap; i++) { if(lines > 0) { row0 = y + i + lines; row1 = y + i; } else { row0 = (y - i - 1) + lines; row1 = (y - i - 1); } /* read row0 into the buffer and then write at row1*/ lld_lcdSetViewPort(x, row0, cx, 1); lld_lcdReadStreamStart(); lld_lcdReadStream(buf, cx); lld_lcdReadStreamStop(); lld_lcdSetViewPort(x, row1, cx, 1); lld_lcdWriteStreamStart(); lld_lcdWriteStream(buf, cx); lld_lcdWriteStreamStop(); } } /* fill the remaining gap */ lld_lcdSetViewPort(x, lines > 0 ? (y+gap) : y, cx, abslines); lld_lcdWriteStreamStart(); gap = cx*abslines; for(i = 0; i < gap; i++) lld_lcdWriteData(bgcolor); lld_lcdWriteStreamStop(); lld_lcdResetViewPort(); }
/** * @brief Scroll vertically a section of the screen. * @note Optional. * @note If x,y + cx,cy is off the screen, the result is undefined. * @note If lines is >= cy, it is equivelent to a area fill with bgcolor. * * @param[in] x, y The start of the area to be scrolled * @param[in] cx, cy The size of the area to be scrolled * @param[in] lines The number of lines to scroll (Can be positive or negative) * @param[in] bgcolor The color to fill the newly exposed area. * * @notapi */ void GDISP_LLD(verticalscroll)(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { static color_t buf[((SCREEN_HEIGHT > SCREEN_WIDTH ) ? SCREEN_HEIGHT : SCREEN_WIDTH)]; coord_t row0, row1; unsigned i, gap, abslines; #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; } if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; } if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x; if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y; #endif abslines = lines < 0 ? -lines : lines; if (abslines >= cy) { abslines = cy; gap = 0; } else { gap = cy - abslines; for(i = 0; i < gap; i++) { if(lines > 0) { row0 = y + i + lines; row1 = y + i; } else { row0 = (y - i - 1) + lines; row1 = (y - i - 1); } /* read row0 into the buffer and then write at row1*/ lld_lcdSetViewPort(x, row0, cx, 1); lld_lcdReadStreamStart(); lld_lcdReadStream(buf, cx); lld_lcdReadStreamStop(); lld_lcdSetViewPort(x, row1, cx, 1); lld_lcdWriteStreamStart(); lld_lcdWriteStream(buf, cx); lld_lcdWriteStreamStop(); } } /* fill the remaining gap */ lld_lcdSetViewPort(x, lines > 0 ? (y+gap) : y, cx, abslines); lld_lcdWriteStreamStart(); gap = cx*abslines; for(i = 0; i < gap; i++) lld_lcdWriteData(bgcolor); lld_lcdWriteStreamStop(); lld_lcdResetViewPort(); }