diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index 4f05ec45..83eabeb0 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -31,6 +31,7 @@ add_subdirectory(PropWare_UARTTX) add_subdirectory(PropWare_Utility) add_subdirectory(PropWare_WatchDog) add_subdirectory(PropWare_WS2812) +add_subdirectory(PropWare_VGAText) add_subdirectory(Simple_FdSerial) add_subdirectory(Simple_libadcACpropab) add_subdirectory(Simple_MeasureVolts) diff --git a/Examples/PropWare_VGAText/CMakeLists.txt b/Examples/PropWare_VGAText/CMakeLists.txt new file mode 100644 index 00000000..fcf83e6d --- /dev/null +++ b/Examples/PropWare_VGAText/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required (VERSION 3.0.0) +find_package(PropWare REQUIRED) + +set(MODEL cmm) +set(COMMON_FLAGS "-Os") +set(C_FLAGS ) +set(CXX_FLAGS ) + +project(VGAText_Demo) + +create_simple_executable(${PROJECT_NAME} ${PROJECT_NAME}) diff --git a/Examples/PropWare_VGAText/VGAText_Demo.cpp b/Examples/PropWare_VGAText/VGAText_Demo.cpp new file mode 100644 index 00000000..46c91937 --- /dev/null +++ b/Examples/PropWare_VGAText/VGAText_Demo.cpp @@ -0,0 +1,20 @@ +#include + +int main() { + PropWare::VGAText Text; + int i; + + Text.start(8); + Text.str("\r VGA Text Demo...\r\r\x0C\x05 OBJ and VAR require only 5.0KB \x0C\x01"); + for (i = 0; i < 14; i++) { + Text.out(' '); + } + for (i = 0x0E; i <= 0xFF; i++) { + Text.out(i); + } + Text.str("\x0C\x06 Uses internal ROM font \x0C\x02"); + for (;;) { + Text.str("\x0A\x0C\x0B\x0E"); + Text.hex(i++, 8); + } +} diff --git a/PropWare/CMakeLists.txt b/PropWare/CMakeLists.txt index 863c768f..0c5d0172 100644 --- a/PropWare/CMakeLists.txt +++ b/PropWare/CMakeLists.txt @@ -19,6 +19,10 @@ set(PROPWARE_SOURCES ${CMAKE_CURRENT_LIST_DIR}/hmi/output/synchronousprinter.cpp ${CMAKE_CURRENT_LIST_DIR}/hmi/output/synchronousprinter.h ${CMAKE_CURRENT_LIST_DIR}/hmi/output/ws2812.h + ${CMAKE_CURRENT_LIST_DIR}/hmi/output/video/vgatext.cpp + ${CMAKE_CURRENT_LIST_DIR}/hmi/output/video/vgatext.h + ${CMAKE_CURRENT_LIST_DIR}/hmi/output/video/vga.h + ${CMAKE_CURRENT_LIST_DIR}/hmi/output/video/vga_driver.S ${CMAKE_CURRENT_LIST_DIR}/memory/blockstorage.h ${CMAKE_CURRENT_LIST_DIR}/memory/eeprom.h ${CMAKE_CURRENT_LIST_DIR}/memory/sd.h diff --git a/PropWare/hmi/output/video/vga.h b/PropWare/hmi/output/video/vga.h new file mode 100644 index 00000000..67080041 --- /dev/null +++ b/PropWare/hmi/output/video/vga.h @@ -0,0 +1,99 @@ +/** + * *************************************** + * * VGA Driver v1.1 * + * * Author: Chip Gracey * + * * Copyright (c) 2006 Parallax, Inc. * + * * See end of file for terms of use. * + * *************************************** + * v1.0 - 01 May 2006 - original version + * v1.1 - 15 May 2006 - pixel tile size can now be 16 x 32 to enable more efficient + * character displays utilizing the internal font - see 'vga_mode' + */ + +#pragma once + +#include +#include + +extern "C" { +extern int _VGADriverStartCog (void *arg); +} + +namespace PropWare { + +class VGA { +public: + /* + * VGA parameters - 21 contiguous longs + */ + struct { + uint32_t vga_status; // 0/1/2 = off/visible/invisible read-only + uint32_t vga_enable; // 0/non-0 = off/on write-only + uint32_t vga_pins; // %pppttt = pins write-only + uint32_t vga_mode; // %tihv = tile,interlace,hpol,vpol write-only + uint32_t vga_screen; // pointer to screen (words) write-only + uint32_t vga_colors; // pointer to colors (longs) write-only + uint32_t vga_ht; // horizontal tiles write-only + uint32_t vga_vt; // vertical tiles write-only + uint32_t vga_hx; // horizontal tile expansion write-only + uint32_t vga_vx; // vertical tile expansion write-only + uint32_t vga_ho; // horizontal offset write-only + uint32_t vga_vo; // vertical offset write-only + uint32_t vga_hd; // horizontal display ticks write-only + uint32_t vga_hf; // horizontal front porch ticks write-only + uint32_t vga_hs; // horizontal sync ticks write-only + uint32_t vga_hb; // horizontal back porch ticks write-only + uint32_t vga_vd; // vertical display lines write-only + uint32_t vga_vf; // vertical front porch lines write-only + uint32_t vga_vs; // vertical sync lines write-only + uint32_t vga_vb; // vertical back porch lines write-only + uint32_t vga_rate; // tick rate (Hz) write-only + } params; + + /* + * Start VGA driver - starts a cog + * returns false if no cog available + * + * vgaptr = pointer to VGA parameters + */ + int32_t start() { + int32_t okay = 0; + stop(); + okay = (cog = _VGADriverStartCog(¶ms) + 1); + return okay; + } + + /* + * Stop VGA driver - frees a cog + */ + int32_t stop() { +#define PostEffect__(X, Y) __extension__({ int32_t tmp__ = (X); (X) = (Y); tmp__; }) + if (cog) { + cogstop((PostEffect__(cog, 0) - 1)); + } + return 0; + } + +private: + int32_t cog; +}; + +} + +/* + ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ TERMS OF USE: MIT License │ + ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ + │Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │ + │files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │ + │modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│ + │is furnished to do so, subject to the following conditions: │ + │ │ + │The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│ + │ │ + │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │ + │WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │ + │COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │ + │ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ + └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + */ diff --git a/PropWare/hmi/output/video/vga_driver.S b/PropWare/hmi/output/video/vga_driver.S new file mode 100644 index 00000000..60af33b1 --- /dev/null +++ b/PropWare/hmi/output/video/vga_driver.S @@ -0,0 +1,586 @@ +# ******************************** +# * Assembly language VGA driver * +# ******************************** + + .pasm + .section .cog_vga_driver, "ax" + .compress off + + .equ paramcount, 21 + .equ colortable, $180 + + .org 0 + +# +# +# Entry +# +entry mov taskptr,#tasks 'reset tasks + + mov x,#8 'perform task sections initially +_init jmpret taskret,taskptr + djnz x,#_init +# +# +# Superfield +# +superfield mov hv,hvbase 'set hv + + mov interlace,#0 'reset interlace + + test _mode,#%0100 wz 'get interlace into nz +# +# +# Field +# +field wrlong visible,par 'set status to visible + + tjz vb,#_nobl 'do any visible back porch lines + mov x,vb + movd bcolor,#colortable + call #blank_line +_nobl + mov screen,_screen 'point to first tile (upper-leftmost) + mov y,_vt 'set vertical tiles +_line mov vx,_vx 'set vertical expand +_vert if_nz xor interlace,#1 'interlace skip? + if_nz tjz interlace,#_skip + + tjz hb,#_nobp 'do any visible back porch pixels + mov vscl,hb + waitvid colortable,#0 +_nobp + mov x,_ht 'set horizontal tiles + mov vscl,hx 'set horizontal expand + +_tile rdword tile,screen 'read tile + add tile,line 'set pointer bits into tile + rol tile,#6 'read tile pixels + rdlong pixels,tile '(8 clocks between reads) + shr tile,#10+6 'set tile colors + movd _color,tile + add screen,#2 'point to next tile +_color waitvid colortable,pixels 'pass colors and pixels to video + djnz x,#_tile 'another tile? + + sub screen,hc2x 'repoint to first tile in same line + + tjz hf,#_nofp 'do any visible front porch pixels + mov vscl,hf + waitvid colortable,#0 +_nofp + mov x,#1 'do hsync + call #blank_hsync '(x=0) + +_skip djnz vx,#_vert 'vertical expand? + ror line,linerot 'set next line + add line,lineadd wc + rol line,linerot + if_nc jmp #_line + add screen,hc2x 'point to first tile in next line + djnz y,#_line wc 'another tile line? (c=0) + + tjz vf,#_nofl 'do any visible front porch lines + mov x,vf + movd bcolor,#colortable + call #blank_line +_nofl + if_nz xor interlace,#1 wc,wz 'get interlace and field1 into nz (c=0/?) + + if_z wrlong invisible,par 'unless interlace and field1, set status to invisible + + mov taskptr,#tasks 'reset tasks + + addx x,_vf wc 'do invisible front porch lines (x=0 before, c=0 after) + call #blank_line + + mov x,_vs 'do vsync lines + call #blank_vsync + + mov x,_vb 'do invisible back porch lines, except last + call #blank_vsync + + if_nz jmp #field 'if interlace and field1, display field2 + jmp #superfield 'else, new superfield +# +# +# Blank line(s) +# +blank_vsync cmp interlace,#2 wc 'vsync (c=1) + +blank_line mov vscl,h1 'blank line or vsync-interlace? + if_nc add vscl,h2 + if_c_and_nz xor hv,#%01 + if_c waitvid hv,#0 + if_c mov vscl,h2 'blank line or vsync-normal? + if_c_and_z xor hv,#%01 +bcolor waitvid hv,#0 + + if_nc jmpret taskret,taskptr 'call task section (z undisturbed) + +blank_hsync mov vscl,_hf 'hsync, do invisible front porch pixels + waitvid hv,#0 + + mov vscl,_hs 'do invisble sync pixels + xor hv,#%10 + waitvid hv,#0 + + mov vscl,_hb 'do invisible back porch pixels + xor hv,#%10 + waitvid hv,#0 + + djnz x,#blank_line wc '(c=0) + + movd bcolor,#hv +blank_hsync_ret +blank_line_ret +blank_vsync_ret ret +# +# +# Tasks - performed in sections during invisible back porch lines +# +tasks mov t1,par 'load parameters + movd _par,#_enable '(skip _status) + mov t2,#paramcount - 1 +_load add t1,#4 +_par rdlong 0,t1 + add _par,d0 + djnz t2,#_load '+164 + + mov t1,#2 'set video pins and directions + shl t1,_pins '(if video disabled, pins will drive low) + sub t1,#1 + test _pins,#$20 wc + and _pins,#$38 + shr t1,_pins + movs vcfg,t1 + shl t1,_pins + shr _pins,#3 + movd vcfg,_pins + if_nc mov dira,t1 + if_nc mov dirb,#0 + if_c mov dira,#0 + if_c mov dirb,t1 '+14 + + tjz _enable,#disabled '+2, disabled? + + jmpret taskptr,taskret '+1=181, break and return later + + rdlong t1,#0 'make sure CLKFREQ => 16MHz + shr t1,#1 + cmp t1,m8 wc + if_c jmp #disabled '+8 + + min _rate,pllmin 'limit _rate to pll range + max _rate,pllmax '+2 + + mov t1,#%00001_011 'set ctra configuration +_max cmp m8,_rate wc 'adjust rate to be within 4MHz-8MHz + if_c shr _rate,#1 '(vco will be within 64MHz-128MHz) + if_c add t1,#%00000_001 + if_c jmp #_max +_min cmp _rate,m4 wc + if_c shl _rate,#1 + if_c sub x,#%00000_001 + if_c jmp #_min + movi ctra,t1 '+22 + + rdlong t1,#0 'divide _rate/CLKFREQ and set frqa + mov hvbase,#32+1 +_div cmpsub _rate,t1 wc + rcl t2,#1 + shl _rate,#1 + djnz hvbase,#_div '(hvbase=0) + mov frqa,t2 '+136 + + test _mode,#%0001 wc 'make hvbase + muxnc hvbase,vmask + test _mode,#%0010 wc + muxnc hvbase,hmask '+4 + + jmpret taskptr,taskret '+1=173, break and return later + + mov hx,_hx 'compute horizontal metrics + shl hx,#8 + or hx,_hx + shl hx,#4 + + mov hc2x,_ht + shl hc2x,#1 + + mov h1,_hd + neg h2,_hf + sub h2,_hs + sub h2,_hb + sub h1,h2 + shr h1,#1 wc + addx h2,h1 + + mov t1,_ht + mov t2,_hx + call #multiply + mov hf,_hd + sub hf,t1 + shr hf,#1 wc + mov hb,_ho + addx hb,hf + sub hf,_ho '+59 + + mov t1,_vt 'compute vertical metrics + mov t2,_vx + call #multiply + test _mode,#%1000 wc 'consider tile size + muxc linerot,#1 + mov lineadd,lineinc + if_c shr lineadd,#1 + if_c shl t1,#1 + test _mode,#%0100 wc 'consider interlace + if_c shr t1,#1 + mov vf,_vd + sub vf,t1 + shr vf,#1 wc + neg vb,_vo + addx vb,vf + add vf,_vo '+53 + + movi vcfg,#%01100_000 '+1, set video configuration + +_lcolors jmpret taskptr,taskret '+1=114/160, break and return later + + mov t1,#13 'load next 13 colors into colortable +_loop1 mov t2,_lcolor '5 times = 65 (all 64 colors loaded) + shr t2,#9-2 + and t2,#$FC + add t2,_colors + rdlong t2,t2 + and t2,colormask + or t2,hvbase +_lcolor mov colortable,t2 + add _lcolor,d0 + andn _lcolor,d6 + djnz t1,#_loop1 '+158 + + jmp #_lcolors '+1, keep loading colors +# +# +# Multiply t1 * t2 * 16 (t1, t2 = bytes) +# +multiply shl t2,#8+4-1 + + mov tile,#8 +_loop2 shr t1,#1 wc + if_c add t1,t2 + djnz tile,#_loop2 + +multiply_ret ret '+37 +# +# +# Disabled - reset status, nap ~4ms, try again +# +disabled mov ctra,#0 'reset ctra + mov vcfg,#0 'reset video + + wrlong outa,par 'set status to disabled + + rdlong t1,#0 'get CLKFREQ + shr t1,#8 'nap for ~4ms + min t1,#3 + add t1,cnt + waitcnt t1,#0 + + jmp #entry 'reload parameters +# +# +# Initialized data +# +pllmin long 500_000 'pll lowest output frequency +pllmax long 128_000_000 'pll highest output frequency +m8 long 8_000_000 '*16 = 128MHz (pll vco max) +m4 long 4_000_000 '*16 = 64MHz (pll vco min) +d0 long 1 << 9 << 0 +d6 long 1 << 9 << 6 +invisible long 1 +visible long 2 +line long $00060000 +lineinc long $10000000 +linerot long 0 +vmask long $01010101 +hmask long $02020202 +colormask long $FCFCFCFC +# +# +# Uninitialized data +# +taskptr res 1 'tasks +taskret res 1 +t1 res 1 +t2 res 1 + +x res 1 'display +y res 1 +hf res 1 +hb res 1 +vf res 1 +vb res 1 +hx res 1 +vx res 1 +hc2x res 1 +screen res 1 +tile res 1 +pixels res 1 +lineadd res 1 +interlace res 1 +hv res 1 +hvbase res 1 +h1 res 1 +h2 res 1 +# +# +# Parameter buffer +# +_enable res 1 '0/non-0 read-only +_pins res 1 '%pppttt read-only +_mode res 1 '%tihv read-only +_screen res 1 '@word read-only +_colors res 1 '@long read-only +_ht res 1 '1+ read-only +_vt res 1 '1+ read-only +_hx res 1 '1+ read-only +_vx res 1 '1+ read-only +_ho res 1 '0+- read-only +_vo res 1 '0+- read-only +_hd res 1 '1+ read-only +_hf res 1 '1+ read-only +_hs res 1 '1+ read-only +_hb res 1 '1+ read-only +_vd res 1 '1+ read-only +_vf res 1 '1+ read-only +_vs res 1 '1+ read-only +_vb res 1 '2+ read-only +_rate res 1 '500_000+ read-only + + fit colortable 'fit underneath colortable ($180-$1BF) + +/** + * function to start the SPI code in its own COG + * C interface is: + * int _VGADriverStartCog(void *arg) + * + * returns the number of the COG, or -1 if no COGs are left + */ + .compress default + .text + .global __VGADriverStartCog +__VGADriverStartCog '' linker magic for the start of the __load_start_cog_vga_driver section +#ifdef __PROPELLER_COG__ + mov r7, #__load_start_cog_vga_driver +#else + mviw r7, #__load_start_cog_vga_driver +#endif + shl r7, #2 + or r7, #8 '' 8 means first available cog + shl r0, #16 '' assumes bottom two bits of r0 are 0, i.e. arg must be long aligned + or r0, r7 + coginit r0 wc,wr + if_b neg r0, #1 '' if C is set, return -1 + // Temporary hack until fix for GCC is released +#ifdef __PROPELLER_CMM__ + lret +#else + mov pc, lr +#endif + +# +# ___ +# VAR 'VGA parameters - 21 contiguous longs +# +# long vga_status '0/1/2 = off/visible/invisible read-only +# long vga_enable '0/non-0 = off/on write-only +# long vga_pins '%pppttt = pins write-only +# long vga_mode '%tihv = tile,interlace,hpol,vpol write-only +# long vga_screen 'pointer to screen (words) write-only +# long vga_colors 'pointer to colors (longs) write-only +# long vga_ht 'horizontal tiles write-only +# long vga_vt 'vertical tiles write-only +# long vga_hx 'horizontal tile expansion write-only +# long vga_vx 'vertical tile expansion write-only +# long vga_ho 'horizontal offset write-only +# long vga_vo 'vertical offset write-only +# long vga_hd 'horizontal display ticks write-only +# long vga_hf 'horizontal front porch ticks write-only +# long vga_hs 'horizontal sync ticks write-only +# long vga_hb 'horizontal back porch ticks write-only +# long vga_vd 'vertical display lines write-only +# long vga_vf 'vertical front porch lines write-only +# long vga_vs 'vertical sync lines write-only +# long vga_vb 'vertical back porch lines write-only +# long vga_rate 'tick rate (Hz) write-only +# +# The preceding VAR section may be copied into your code. +# After setting variables, do start(@vga_status) to start driver. +# +# All parameters are reloaded each superframe, allowing you to make live +# changes. To minimize flicker, correlate changes with vga_status. +# +# Experimentation may be required to optimize some parameters. +# +# Parameter descriptions: +# __________ +# vga_status +# +# driver sets this to indicate status: +# 0: driver disabled (vga_enable = 0 or CLKFREQ < 16MHz) +# 1: currently outputting invisible sync data +# 2: currently outputting visible screen data +# __________ +# vga_enable +# +# 0: disable (pins will be driven low, reduces power) +# non-0: enable +# ________ +# vga_pins +# +# bits 5..3 select pin group: +# %000: pins 7..0 +# %001: pins 15..8 +# %010: pins 23..16 +# %011: pins 31..24 +# %100: pins 39..32 +# %101: pins 47..40 +# %110: pins 55..48 +# %111: pins 63..56 +# +# bits 2..0 select top pin within group +# for example: %01111 (15) will use pins %01000-%01111 (8-15) +# ________ +# vga_mode +# +# bit 3 selects between 16x16 and 16x32 pixel tiles: +# 0: 16x16 pixel tiles (tileheight = 16) +# 1: 16x32 pixel tiles (tileheight = 32) +# +# bit 2 controls interlace: +# 0: progressive scan (less flicker, good for motion, required for LCD monitors) +# 1: interlaced scan (allows you to double vga_vt, good for text) +# +# bits 1 and 0 select horizontal and vertical sync polarity, respectively +# 0: active low +# 1: active high +# __________ +# vga_screen +# +# pointer to words which define screen contents (left-to-right, top-to-bottom) +# number of words must be vga_ht * vga_vt +# each word has two bitfields: a 6-bit colorset ptr and a 10-bit pixelgroup ptr +# bits 15..10: select the colorset* for the associated pixel tile +# bits 9..0: select the pixelgroup** address %ppppppppppcccc00 (p=address, c=0..15) +# +# * colorsets are longs which each define four 8-bit colors +# +# ** pixelgroups are longs which define (left-to-right, top-to-bottom) the 2-bit +# (four color) pixels that make up a 16x16 or a 16x32 pixel tile +# __________ +# vga_colors +# +# pointer to longs which define colorsets +# number of longs must be 1..64 +# each long has four 8-bit fields which define colors for 2-bit (four color) pixels +# first long's bottom color is also used as the screen background color +# 8-bit color fields are as follows: +# bits 7..2: actual state of pins 7..2 within pin group* +# bits 1..0: don't care (used within driver for hsync and vsync) +# +# * it is suggested that: +# bits/pins 7..6 are used for red +# bits/pins 5..4 are used for green +# bits/pins 3..2 are used for blue +# for each bit/pin set, sum 240 and 470-ohm resistors to form 75-ohm 1V signals +# connect signal sets to RED, GREEN, and BLUE on VGA connector +# always connect group pin 1 to HSYNC on VGA connector via 240-ohm resistor +# always connect group pin 0 to VSYNC on VGA connector via 240-ohm resistor +# ______ +# vga_ht +# +# horizontal number of pixel tiles - must be at least 1 +# ______ +# vga_vt +# +# vertical number of pixel tiles - must be at least 1 +# ______ +# vga_hx +# +# horizontal tile expansion factor - must be at least 1 +# +# make sure 16 * vga_ht * vga_hx + ||vga_ho is equal to or at least 16 less than vga_hd +# ______ +# vga_vx +# +# vertical tile expansion factor - must be at least 1 +# +# make sure * vga_vt * vga_vx + ||vga_vo does not exceed vga_vd +# (for interlace, use / 2 * vga_vt * vga_vx + ||vga_vo) +# ______ +# vga_ho +# +# horizontal offset in ticks - pos/neg value (0 recommended) +# shifts the display right/left +# ______ +# vga_vo +# +# vertical offset in lines - pos/neg value (0 recommended) +# shifts the display up/down +# ______ +# vga_hd +# +# horizontal display ticks +# ______ +# vga_hf +# +# horizontal front porch ticks +# ______ +# vga_hs +# +# horizontal sync ticks +# ______ +# vga_hb +# +# horizontal back porch ticks +# ______ +# vga_vd +# +# vertical display lines +# ______ +# vga_vf +# +# vertical front porch lines +# ______ +# vga_vs +# +# vertical sync lines +# ______ +# vga_vb +# +# vertical back porch lines +# ________ +# vga_rate +# +# tick rate in Hz +# +# driver will limit value to be within 500KHz and 128MHz +# pixel rate (vga_rate / vga_hx) should be no more than CLKFREQ / 4 + +# ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +# │ TERMS OF USE: MIT License │ +# ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ +# │Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │ +# │files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │ +# │modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│ +# │is furnished to do so, subject to the following conditions: │ +# │ │ +# │The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│ +# │ │ +# │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │ +# │WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │ +# │COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │ +# │ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ +# └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/PropWare/hmi/output/video/vgatext.cpp b/PropWare/hmi/output/video/vgatext.cpp new file mode 100644 index 00000000..cf86ba62 --- /dev/null +++ b/PropWare/hmi/output/video/vgatext.cpp @@ -0,0 +1,231 @@ +// *************************************** +// * VGA Text 32x15 v1.0 * +// * Author: Chip Gracey * +// * Copyright (c) 2006 Parallax, Inc. * +// * See end of file for terms of use. * +// *************************************** + +#include +#include + +#define INLINE__ static inline +#define PostEffect__(X, Y) __extension__({ int32_t tmp__ = (X); (X) = (Y); tmp__; }) + +namespace PropWare { + +static inline int32_t Rotl__ (uint32_t a, uint32_t b) { + return (a << b) | (a >> (32 - b)); +} + +static inline int32_t Rotr__ (uint32_t a, uint32_t b) { + return (a >> b) | (a << (32 - b)); +} + +static inline int32_t Between__ (int32_t x, int32_t a, int32_t b) { + if (a <= b) + return x >= a && x <= b; + return x >= b && x <= a; +} + +static inline int32_t Lookup__ (int32_t x, int32_t b, int32_t a[], int32_t n) { + int32_t i = (x) - (b); + return ((unsigned) i >= n) ? 0 : (a)[i]; +} + +/** + * Default color palette + */ +static uint8_t palette[] = { + 0x3f, 0x01, // 0 white / dark blue + 0x3c, 0x14, // 1 yellow / brown + 0x22, 0x00, // 2 magenta / black + 0x15, 0x3f, // 3 grey / white + 0x0f, 0x05, // 4 cyan / dark cyan + 0x08, 0x2e, // 5 green / gray-green + 0x10, 0x35, // 6 red / pink + 0x0f, 0x03 // 7 cyan / blue +}; + +int32_t VGAText::start (int32_t basepin) { + int32_t okay = 0; + + setcolors(palette); + out(0); + + vga.params.vga_status = 0; // 0/1/2 = off/visible/invisible read-only + vga.params.vga_enable = 1; // 0/non-0 = off/on write-only + vga.params.vga_pins = basepin | 0x7; // %pppttt = pins write-only + vga.params.vga_mode = 0b1000; // %tihv = tile,interlace,hpol,vpol write-only + vga.params.vga_screen = (int32_t) &screen[0]; // pointer to screen (words) write-only + vga.params.vga_colors = (int32_t) &colors[0]; // pointer to colors (longs) write-only + vga.params.vga_ht = cols; // horizontal tiles write-only + vga.params.vga_vt = rows; // vertical tiles write-only + vga.params.vga_hx = 1; // horizontal tile expansion write-only + vga.params.vga_vx = 1; // vertical tile expansion write-only + vga.params.vga_ho = 0; // horizontal offset write-only + vga.params.vga_vo = 0; // vertical offset write-only + vga.params.vga_hd = 512; // horizontal display ticks write-only + vga.params.vga_hf = 10; // horizontal front porch ticks write-only + vga.params.vga_hs = 75; // horizontal sync ticks write-only + vga.params.vga_hb = 43; // horizontal back porch ticks write-only + vga.params.vga_vd = 480; // vertical display lines write-only + vga.params.vga_vf = 11; // vertical front porch lines write-only + vga.params.vga_vs = 2; // vertical sync lines write-only + vga.params.vga_vb = 31; // vertical back porch lines write-only + vga.params.vga_rate = CLKFREQ >> 2; // tick rate (Hz) write-only + + okay = vga.start(); + + return okay; +} + +void VGAText::stop (void) { + vga.stop(); +} + +void VGAText::str (const char *stringptr) { + while (*stringptr != 0) { + out(*stringptr++); + } +} + +void VGAText::dec (int32_t value) { + int32_t i, idx; + int32_t result = 0; + + if (value < 0) { + value = -value; + out('-'); + } + i = 1000000000; + for (idx = 1; idx <= 10; idx = idx + 1) { + if (value >= i) { + out(((value / i) + '0')); + value = value % i; + result = -1; + } else { + if ((result) || (i == 1)) { + out('0'); + } + } + i = i / 10; + } +} + +void VGAText::hex (int32_t value, int32_t digits) { + int32_t idx; + int32_t limit = digits; + static int32_t look__0003[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + + value = value << ((8 - digits) << 2); + for (idx = 1; idx <= limit; idx = idx + 1) { + out(Lookup__(((value = Rotl__(value, 4)) & 0xf), 0, look__0003, 16)); + } +} + +void VGAText::bin (int32_t value, int32_t digits) { + int32_t idx; + int32_t limit = digits; + + value = value << (32 - digits); + for (idx = 1; idx <= limit; idx = idx + 1) { + out((((value = Rotl__(value, 1)) & 0x1) + '0')); + } +} + +int32_t VGAText::out (char c) { + int32_t result = 0; + + if (flag == 0) { + if (c == 0) { + int32_t fill; + uint16_t *ptr = (uint16_t *) &screen[0]; + uint16_t val = 0x220; + for (fill = screensize; fill > 0; --fill) { + *ptr++ = val; + } + col = (row = 0); + } else if (c == 1) { + col = (row = 0); + } else if (c == 8) { + if (col) { + (col--); + } + } else if (c == 9) { + do { + print(' '); + } while (col & 0x7); + } else if (Between__(c, 10, 12)) { + flag = c; + return result; + } else if (c == 13) { + newline(); + } else if (1) { + print(c); + } + } else if (flag == 10) { + col = c % cols; + } else if (flag == 11) { + row = c % rows; + } else if (flag == 12) { + color = c & 0x7; + } + flag = 0; + return result; +} + +void VGAText::setcolors (uint8_t *colorptr) { + int32_t i, fore, back; + + for (i = 0; i <= 7; i = i + 1) { + fore = (colorptr)[(i << 1)] << 2; + back = (colorptr)[((i << 1) + 1)] << 2; + colors[(i << 1)] = (((fore << 24) + (back << 16)) + (fore << 8)) + back; + colors[((i << 1) + 1)] = (((fore << 24) + (fore << 16)) + (back << 8)) + back; + } +} + +void VGAText::print (int32_t c) { + screen[((row * cols) + col)] = ((((color << 1) + (c & 0x1)) << 10) + 512) + (c & 0xfe); + if ((++col) == cols) { + newline(); + } +} + +void VGAText::newline (void) { + col = 0; + if ((++row) == rows) { + (row--); + // scroll lines + memmove((void *) &screen[0], (void *) &screen[cols], 2 * (lastrow)); + // clear new line + { + int32_t fill; + uint16_t *ptr = (uint16_t *) &screen[lastrow]; + uint16_t val = 0x220; + for (fill = cols; fill > 0; --fill) { + *ptr++ = val; + } + }; + } +} + +} + +/* + ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ TERMS OF USE: MIT License │ + ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ + │Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │ + │files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │ + │modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│ + │is furnished to do so, subject to the following conditions: │ + │ │ + │The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│ + │ │ + │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │ + │WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │ + │COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │ + │ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ + └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + */ diff --git a/PropWare/hmi/output/video/vgatext.h b/PropWare/hmi/output/video/vgatext.h new file mode 100644 index 00000000..1c8de36b --- /dev/null +++ b/PropWare/hmi/output/video/vgatext.h @@ -0,0 +1,113 @@ +// *************************************** +// * VGA Text 32x15 v1.0 * +// * Author: Chip Gracey * +// * Copyright (c) 2006 Parallax, Inc. * +// * See end of file for terms of use. * +// *************************************** + +#pragma once + +#include + +namespace PropWare { + +class VGAText { +public: + static const int cols = 32; + static const int rows = 15; + static const int screensize = (cols * rows); + static const int lastrow = (screensize - cols); + + /** + * Start terminal - starts a cog + * returns false if no cog available + * + * requires at least 80MHz system clock + */ + int32_t start(int32_t basepin); + + /** + * Stop terminal - frees a cog + */ + void stop(); + + /** + * Print a zero-terminated string + */ + void str(const char *stringptr); + + /** + * Print a decimal number + */ + void dec(int32_t value); + + /** + * Print a hexadecimal number + */ + void hex(int32_t value, int32_t digits); + + /** + * Print a binary number + */ + void bin(int32_t value, int32_t digits); + + /** + * Output a character + * + * $00 = clear screen + * $01 = home + * $08 = backspace + * $09 = tab (8 spaces per) + * $0A = set X position (X follows) + * $0B = set Y position (Y follows) + * $0C = set color (color follows) + * $0D = return + * others = printable characters + */ + int32_t out(char c); + + /** + * Override default color palette + * + * colorptr must point to a list of up to 8 colors + * arranged as follows (where r, g, b are 0..3): + * + * fore back + * ------------ + * palette byte %%rgb, %%rgb 'color 0 + * byte %%rgb, %%rgb 'color 1 + * byte %%rgb, %%rgb 'color 2 + */ + void setcolors(uint8_t *colorptr); + +private: + VGA vga; + + volatile int32_t col, row, color, flag; + volatile int32_t colors[16]; + volatile uint16_t screen[480]; + + void print(int32_t c); + + void newline(); +}; + +} + +/* + ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ TERMS OF USE: MIT License │ + ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ + │Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │ + │files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │ + │modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│ + │is furnished to do so, subject to the following conditions: │ + │ │ + │The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│ + │ │ + │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │ + │WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │ + │COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │ + │ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ + └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + */