mirror of https://github.com/wwarthen/RomWBW.git
36 changed files with 1862 additions and 15845 deletions
Binary file not shown.
@ -1,2 +0,0 @@ |
|||
rem ..\..\..\Tools\bst\bstc -Ox -ls -e -p0 -dCOM5: PropIO2.spin |
|||
..\..\..\Tools\bst\bstc -Ox -ls -e PropIO2.spin |
|||
@ -1 +0,0 @@ |
|||
{{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// E555 Speaker Engine
//
// Author: Kwabena W. Agyeman
// Updated: 7/27/2010
// Designed For: P8X32A
// Version: 1.1
//
// Copyright (c) 2010 Kwabena W. Agyeman
// See end of file for terms of use.
//
// Update History:
//
// v1.0 - Original release - 8/26/2009.
// v1.1 - Added support for variable pin assignments - 7/27/2010.
//
// For each included copy of this object only one spin interpreter should access it at a time.
//
// Nyamekye,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Speaker Circuit:
//
// SpeakerPinNumber --- Speaker Driver (Active High).
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}}
PUB speakerFrequency(newFrequency, speakerPinNumber) '' 10 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Changes the speaker frequency using the SPIN interpreter's counter modules.
'' //
'' // NewFrequency - The new frequency. Between 0 Hz and 80MHz @ 80MHz. -1 to reset the pin and counter modules.
'' // SpeakerPinNumber - Pin to use to drive the speaker circuit. Between 0 and 31.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
speakerSetup((newFrequency <> -1), speakerPinNumber)
newFrequency := ((newFrequency <# clkfreq) #> 0)
result := 1
repeat 32
newFrequency <<= 1
result <-= 1
if(newFrequency => clkfreq)
newFrequency -= clkfreq
result += 1
frqa := result~
phsb := 0
PUB speakerVolume(newVolume, speakerPinNumber) '' 10 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Changes the speaker volume using the SPIN interpreter's counter modules.
'' //
'' // NewVolume - The new volume. Between 0% and 100%. -1 to reset the pin and counter modules.
'' // SpeakerPinNumber - Pin to use to drive the speaker circuit. Between 0 and 31.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
speakerSetup((newVolume <> -1), speakerPinNumber)
frqb := (((100 - ((newVolume <# 100) #> 0)) * constant(posx / 50)) | $7)
PRI speakerSetup(activeOrInactive, speakerPinNumber) ' 5 Stack Longs
speakerPinNumber := ((speakerPinNumber <# 31) #> 0)
dira[speakerPinNumber] := activeOrInactive
outa[speakerPinNumber] := false
ctra := ((constant(%0_0100 << 26) + speakerPinNumber) & activeOrInactive)
ctrb := ((constant(%0_0110 << 26) + speakerPinNumber) & activeOrInactive)
{{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}} |
|||
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Binary file not shown.
@ -1,920 +0,0 @@ |
|||
{{ |
|||
SPI interface routines for SD & SDHC & MMC cards |
|||
|
|||
Jonathan "lonesock" Dummer |
|||
version 0.3.0 2009 July 19 |
|||
|
|||
Using multiblock SPI mode exclusively. |
|||
|
|||
This is the "SAFE" version...uses |
|||
* 1 instruction per bit writes |
|||
* 2 instructions per bit reads |
|||
|
|||
For the fsrw project: |
|||
fsrw.sf.net |
|||
}} |
|||
|
|||
CON |
|||
' possible card types |
|||
type_MMC = 1 |
|||
type_SD = 2 |
|||
type_SDHC = 3 |
|||
|
|||
' Error codes |
|||
ERR_CARD_NOT_RESET = -1 |
|||
ERR_3v3_NOT_SUPPORTED = -2 |
|||
ERR_OCR_FAILED = -3 |
|||
ERR_BLOCK_NOT_LONG_ALIGNED = -4 |
|||
'... |
|||
' These errors are for the assembly engine...they are negated inside, and need to be <= 511 |
|||
ERR_ASM_NO_READ_TOKEN = 100 |
|||
ERR_ASM_BLOCK_NOT_WRITTEN = 101 |
|||
' NOTE: errors -128 to -255 are reserved for reporting R1 response errors |
|||
'... |
|||
ERR_SPI_ENGINE_NOT_RUNNING = -999 |
|||
ERR_CARD_BUSY_TIMEOUT = -1000 |
|||
|
|||
' SDHC/SD/MMC command set for SPI |
|||
CMD0 = $40+0 ' GO_IDLE_STATE |
|||
CMD1 = $40+1 ' SEND_OP_COND (MMC) |
|||
ACMD41 = $C0+41 ' SEND_OP_COND (SDC) |
|||
CMD8 = $40+8 ' SEND_IF_COND |
|||
CMD9 = $40+9 ' SEND_CSD |
|||
CMD10 = $40+10 ' SEND_CID |
|||
CMD12 = $40+12 ' STOP_TRANSMISSION |
|||
CMD13 = $40+13 ' SEND_STATUS |
|||
ACMD13 = $C0+13 ' SD_STATUS (SDC) |
|||
CMD16 = $40+16 ' SET_BLOCKLEN |
|||
CMD17 = $40+17 ' READ_SINGLE_BLOCK |
|||
CMD18 = $40+18 ' READ_MULTIPLE_BLOCK |
|||
CMD23 = $40+23 ' SET_BLOCK_COUNT (MMC) |
|||
ACMD23 = $C0+23 ' SET_WR_BLK_ERASE_COUNT (SDC) |
|||
CMD24 = $40+24 ' WRITE_BLOCK |
|||
CMD25 = $40+25 ' WRITE_MULTIPLE_BLOCK |
|||
CMD55 = $40+55 ' APP_CMD |
|||
CMD58 = $40+58 ' READ_OCR |
|||
CMD59 = $40+59 ' CRC_ON_OFF |
|||
|
|||
' buffer size for my debug cmd log |
|||
'LOG_SIZE = 256<<1 |
|||
|
|||
{ |
|||
VAR |
|||
long SPI_engine_cog |
|||
' these are used for interfacing with the assembly engine | temporary initialization usage |
|||
long SPI_command ' "t", "r", "w", 0 =>done, <0 => error | pin mask |
|||
long SPI_block_index ' which 512-byte block to read/write | cnt at init |
|||
long SPI_buffer_address ' where to get/put the data in Hub RAM | unused |
|||
'} |
|||
DAT |
|||
'' I'm placing these variables in a DAT section to make this driver a singleton. |
|||
'' If for some reason you really need more than one driver (e.g. if you have more |
|||
'' than a single SD socket), move these back into VAR. |
|||
SPI_engine_cog long 0 |
|||
' these are used for interfacing with the assembly engine | temporary initialization usage |
|||
SPI_command long 0 ' "t", "r", "w", 0 =>done, <0 => error | unused |
|||
SPI_block_index long 0 ' which 512-byte block to read/write | cnt at init |
|||
SPI_buffer_address long 0 ' where to get/put the data in Hub RAM | unused |
|||
|
|||
{ |
|||
VAR |
|||
' for debug ONLY |
|||
byte log_cmd_resp[LOG_SIZE+1] |
|||
PUB get_log_pointer |
|||
return @log_cmd_resp |
|||
'} |
|||
|
|||
PUB start( basepin ) |
|||
{{ |
|||
This is a compatibility wrapper, and requires that the pins be |
|||
both consecutive, and in the order DO CLK DI CS. |
|||
}} |
|||
return start_explicit( basepin, basepin+1, basepin+2, basepin+3 ) |
|||
|
|||
PUB readblock( block_index, buffer_address ) |
|||
if SPI_engine_cog == 0 |
|||
abort ERR_SPI_ENGINE_NOT_RUNNING |
|||
if (buffer_address & 3) |
|||
abort ERR_BLOCK_NOT_LONG_ALIGNED |
|||
SPI_block_index := block_index |
|||
SPI_buffer_address := buffer_address |
|||
SPI_command := "r" |
|||
repeat while SPI_command == "r" |
|||
if SPI_command < 0 |
|||
abort SPI_command |
|||
|
|||
PUB writeblock( block_index, buffer_address ) |
|||
if SPI_engine_cog == 0 |
|||
abort ERR_SPI_ENGINE_NOT_RUNNING |
|||
if (buffer_address & 3) |
|||
abort ERR_BLOCK_NOT_LONG_ALIGNED |
|||
SPI_block_index := block_index |
|||
SPI_buffer_address := buffer_address |
|||
SPI_command := "w" |
|||
repeat while SPI_command == "w" |
|||
if SPI_command < 0 |
|||
abort SPI_command |
|||
|
|||
PUB get_seconds |
|||
if SPI_engine_cog == 0 |
|||
abort ERR_SPI_ENGINE_NOT_RUNNING |
|||
SPI_command := "t" |
|||
repeat while SPI_command == "t" |
|||
' secods are in SPI_block_index, remainder is in SPI_buffer_address |
|||
return SPI_block_index |
|||
|
|||
PUB get_milliseconds : ms |
|||
if SPI_engine_cog == 0 |
|||
abort ERR_SPI_ENGINE_NOT_RUNNING |
|||
SPI_command := "t" |
|||
repeat while SPI_command == "t" |
|||
' secods are in SPI_block_index, remainder is in SPI_buffer_address |
|||
ms := SPI_block_index * 1000 |
|||
ms += SPI_buffer_address * 1000 / clkfreq |
|||
|
|||
PUB start_explicit( DO, CLK, DI, CS ) : card_type | tmp, i |
|||
{{ |
|||
Do all of the card initialization in SPIN, then hand off the pin |
|||
information to the assembly cog for hot SPI block R/W action! |
|||
}} |
|||
' Start from scratch |
|||
stop |
|||
' clear my log buffer |
|||
{ |
|||
bytefill( @log_cmd_resp, 0, LOG_SIZE+1 ) |
|||
dbg_ptr := @log_cmd_resp |
|||
dbg_end := dbg_ptr + LOG_SIZE |
|||
'} |
|||
' wait ~4 milliseconds |
|||
waitcnt( 500 + (clkfreq>>8) + cnt ) |
|||
' (start with cog variables, _BEFORE_ loading the cog) |
|||
pinDO := DO |
|||
maskDO := |< DO |
|||
pinCLK := CLK |
|||
pinDI := DI |
|||
maskDI := |< DI |
|||
maskCS := |< CS |
|||
adrShift := 9 ' block = 512 * index, and 512 = 1<<9 |
|||
' pass the output pin mask via the command register |
|||
maskAll := maskCS | (|<pinCLK) | maskDI |
|||
dira |= maskAll |
|||
' get the card in a ready state: set DI and CS high, send => 74 clocks |
|||
outa |= maskAll |
|||
repeat 4096 |
|||
outa[CLK]~~ |
|||
outa[CLK]~ |
|||
' time-hack |
|||
SPI_block_index := cnt |
|||
' reset the card |
|||
tmp~ |
|||
repeat i from 0 to 9 |
|||
if tmp <> 1 |
|||
tmp := send_cmd_slow( CMD0, 0, $95 ) |
|||
if (tmp & 4) |
|||
' the card said CMD0 ("go idle") was invalid, so we're possibly stuck in read or write mode |
|||
if i & 1 |
|||
' exit multiblock read mode |
|||
repeat 4 |
|||
read_32_slow ' these extra clocks are required for some MMC cards |
|||
send_slow( $FD, 8 ) ' stop token |
|||
read_32_slow |
|||
repeat while read_slow <> $FF |
|||
else |
|||
' exit multiblock read mode |
|||
send_cmd_slow( CMD12, 0, $61 ) |
|||
if tmp <> 1 |
|||
' the reset command failed! |
|||
crash( ERR_CARD_NOT_RESET ) |
|||
' Is this a SD type 2 card? |
|||
if send_cmd_slow( CMD8, $1AA, $87 ) == 1 |
|||
' Type2 SD, check to see if it's a SDHC card |
|||
tmp := read_32_slow |
|||
' check the supported voltage |
|||
if (tmp & $1FF) <> $1AA |
|||
crash( ERR_3v3_NOT_SUPPORTED ) |
|||
' try to initialize the type 2 card with the High Capacity bit |
|||
repeat while send_cmd_slow( ACMD41, |<30, $77 ) |
|||
' the card is initialized, let's read back the High Capacity bit |
|||
if send_cmd_slow( CMD58, 0, $FD ) <> 0 |
|||
crash( ERR_OCR_FAILED ) |
|||
' get back the data |
|||
tmp := read_32_slow |
|||
' check the bit |
|||
if tmp & |<30 |
|||
card_type := type_SDHC |
|||
adrShift := 0 |
|||
else |
|||
card_type := type_SD |
|||
else |
|||
' Either a type 1 SD card, or it's MMC, try SD 1st |
|||
if send_cmd_slow( ACMD41, 0, $E5 ) < 2 |
|||
' this is a type 1 SD card (1 means busy, 0 means done initializing) |
|||
card_type := type_SD |
|||
repeat while send_cmd_slow( ACMD41, 0, $E5 ) |
|||
else |
|||
' mark that it's MMC, and try to initialize |
|||
card_type := type_MMC |
|||
repeat while send_cmd_slow( CMD1, 0, $F9 ) |
|||
' some SD or MMC cards may have the wrong block size, set it here |
|||
send_cmd_slow( CMD16, 512, $15 ) |
|||
' card is mounted, make sure the CRC is turned off |
|||
send_cmd_slow( CMD59, 0, $91 ) |
|||
' check the status |
|||
'send_cmd_slow( CMD13, 0, $0D ) |
|||
' done with the SPI bus for now |
|||
outa |= maskCS |
|||
' set my counter modes for super fast SPI operation |
|||
' writing: NCO single-ended mode, output on DI |
|||
writeMode := (%00100 << 26) | (DI << 0) |
|||
' reading |
|||
'readMode := (%11000 << 26) | (DO << 0) | (CLK << 9) |
|||
' clock |
|||
'clockLineMode := (%00110 << 26) | (CLK << 0) ' DUTY, 25% duty cycle |
|||
' clock |
|||
clockLineMode := (%00100 << 26) | (CLK << 0) ' NCO, 50% duty cycle |
|||
' how many bytes (8 clocks, >>3) fit into 1/2 of a second (>>1), 4 clocks per instruction (>>2)? |
|||
N_in8_500ms := clkfreq >> constant(1+2+3) |
|||
' how long should we wait before auto-exiting any multiblock mode? |
|||
idle_limit := 125 ' ms, NEVER make this > 1000 |
|||
idle_limit := clkfreq / (1000 / idle_limit) ' convert to counts |
|||
' Hand off control to the assembly engine's cog |
|||
bufAdr := @SPI_buffer_address |
|||
sdAdr := @SPI_block_index |
|||
SPI_command := 0 ' just make sure it's not 1 |
|||
' start my driver cog and wait till I hear back that it's done |
|||
SPI_engine_cog := cognew( @SPI_engine_entry, @SPI_command ) + 1 |
|||
if( SPI_engine_cog == 0 ) |
|||
crash( ERR_SPI_ENGINE_NOT_RUNNING ) |
|||
repeat while SPI_command <> -1 |
|||
' and we no longer need to control any pins from here |
|||
dira &= !maskAll |
|||
' the return variable is card_type |
|||
|
|||
PUB release |
|||
{{ |
|||
I do not want to abort if the cog is not |
|||
running, as this is called from stop, which |
|||
is called from start/ [8^) |
|||
}} |
|||
if SPI_engine_cog |
|||
SPI_command := "z" |
|||
repeat while SPI_command == "z" |
|||
|
|||
PUB stop |
|||
{{ |
|||
kill the assembly driver cog. |
|||
}} |
|||
release |
|||
if SPI_engine_cog |
|||
cogstop( SPI_engine_cog~ - 1 ) |
|||
|
|||
PRI crash( abort_code ) |
|||
{{ |
|||
In case of Bad Things(TM) happening, |
|||
exit as gracefully as possible. |
|||
}} |
|||
' and we no longer need to control any pins from here |
|||
dira &= !maskAll |
|||
' and report our error |
|||
abort abort_code |
|||
|
|||
PRI send_cmd_slow( cmd, val, crc ) : reply | time_stamp |
|||
{{ |
|||
Send down a command and return the reply. |
|||
Note: slow is an understatement! |
|||
Note: this uses the assembly DAT variables for pin IDs, |
|||
which means that if you run this multiple times (say for |
|||
multiple SD cards), these values will change for each one. |
|||
But this is OK as all of these functions will be called |
|||
during the initialization only, before the PASM engine is |
|||
running. |
|||
}} |
|||
' if this is an application specific command, handle it |
|||
if (cmd & $80) |
|||
' ACMD<n> is the command sequense of CMD55-CMD<n> |
|||
cmd &= $7F |
|||
reply := send_cmd_slow( CMD55, 0, $65 ) |
|||
if (reply > 1) |
|||
return reply |
|||
' the CS line needs to go low during this operation |
|||
outa |= maskCS |
|||
outa &= !maskCS |
|||
' give the card a few cocks to finish whatever it was doing |
|||
read_32_slow |
|||
' send the command byte |
|||
send_slow( cmd, 8 ) |
|||
' send the value long |
|||
send_slow( val, 32 ) |
|||
' send the CRC byte |
|||
send_slow( crc, 8 ) |
|||
' is this a CMD12?, if so, stuff byte |
|||
if cmd == CMD12 |
|||
read_slow |
|||
' read back the response (spec declares 1-8 reads max for SD, MMC is 0-8) |
|||
time_stamp := 9 |
|||
repeat |
|||
reply := read_slow |
|||
while( reply & $80 ) and ( time_stamp-- ) |
|||
' done, and 'reply' is already pre-loaded |
|||
{ |
|||
if dbg_ptr < (dbg_end-1) |
|||
byte[dbg_ptr++] := cmd |
|||
byte[dbg_ptr++] := reply |
|||
if (cmd&63) == 13 |
|||
' get the second byte |
|||
byte[dbg_ptr++] := cmd |
|||
byte[dbg_ptr++] := read_slow |
|||
'} |
|||
|
|||
PRI send_slow( value, bits_to_send ) |
|||
value ><= bits_to_send |
|||
repeat bits_to_send |
|||
outa[pinCLK]~ |
|||
outa[pinDI] := value |
|||
value >>= 1 |
|||
outa[pinCLK]~~ |
|||
|
|||
PRI read_32_slow : r |
|||
repeat 4 |
|||
r <<= 8 |
|||
r |= read_slow |
|||
|
|||
PRI read_slow : r |
|||
{{ |
|||
Read back 8 bits from the card |
|||
}} |
|||
' we need the DI line high so a read can occur |
|||
outa[pinDI]~~ |
|||
' get 8 bits (remember, r is initialized to 0 by SPIN) |
|||
repeat 8 |
|||
outa[pinCLK]~ |
|||
outa[pinCLK]~~ |
|||
r += r + ina[pinDO] |
|||
' error check |
|||
if( (cnt - SPI_block_index) > (clkfreq << 2) ) |
|||
crash( ERR_CARD_BUSY_TIMEOUT ) |
|||
|
|||
DAT |
|||
{{ |
|||
This is the assembly engine for doing fast block |
|||
reads and writes. This is *ALL* it does! |
|||
}} |
|||
ORG 0 |
|||
SPI_engine_entry |
|||
' Counter A drives data out |
|||
mov ctra,writeMode |
|||
' Counter B will always drive my clock line |
|||
mov ctrb,clockLineMode |
|||
' set our output pins to match the pin mask |
|||
mov dira,maskAll |
|||
' handshake that we now control the pins |
|||
neg user_request,#1 |
|||
wrlong user_request,par |
|||
' start my seconds' counter here |
|||
mov last_time,cnt |
|||
|
|||
waiting_for_command |
|||
' update my seconds counter, but also track the idle |
|||
' time so we can to release the card after timeout. |
|||
call #handle_time |
|||
' read the command, and make sure it's from the user (> 0) |
|||
rdlong user_request,par |
|||
cmps user_request,#0 wz,wc |
|||
if_be jmp #waiting_for_command |
|||
' handle our card based commands |
|||
cmp user_request,#"r" wz |
|||
if_z jmp #read_ahead |
|||
cmp user_request,#"w" wz |
|||
if_z jmp #write_behind |
|||
cmp user_request,#"z" wz |
|||
if_z jmp #release_card |
|||
' time requests are handled differently |
|||
cmp user_request,#"t" wz ' time |
|||
if_z wrlong seconds,sdAdr ' seconds goes into the SD index register |
|||
if_z wrlong dtime,bufAdr ' the remainder goes into the buffer address register |
|||
' in all other cases, clear the user's request |
|||
mov user_request,#0 |
|||
wrlong user_request,par |
|||
jmp #waiting_for_command |
|||
|
|||
|
|||
release_card |
|||
mov user_cmd,#"z" ' request a release |
|||
neg lastIndexPlus,#1 ' reset the last block index |
|||
neg user_idx,#1 ' and make this match it |
|||
call #handle_command |
|||
mov user_request,user_cmd |
|||
wrlong user_request,par |
|||
jmp #waiting_for_command |
|||
|
|||
read_ahead |
|||
rdlong user_idx,sdAdr |
|||
' if the correct block is not already loaded, load it |
|||
mov tmp1,user_idx |
|||
add tmp1,#1 |
|||
cmp tmp1,lastIndexPlus wz |
|||
if_z cmp lastCommand,#"r" wz |
|||
if_z jmp #:get_on_with_it |
|||
mov user_cmd,#"r" |
|||
call #handle_command |
|||
:get_on_with_it |
|||
' copy the data up into Hub RAM |
|||
movi transfer_long,#%000010_000 'set to wrlong |
|||
call #hub_cog_transfer |
|||
' signify that the data is ready, Spin can continue |
|||
mov user_request,user_cmd |
|||
wrlong user_request,par |
|||
' request the next block |
|||
mov user_cmd,#"r" |
|||
add user_idx,#1 |
|||
call #handle_command |
|||
' done |
|||
jmp #waiting_for_command |
|||
|
|||
write_behind |
|||
rdlong user_idx,sdAdr |
|||
' copy data in from Hub RAM |
|||
movi transfer_long,#%000010_001 'set to rdlong |
|||
call #hub_cog_transfer |
|||
' signify that we have the data, Spin can continue |
|||
mov user_request,user_cmd |
|||
wrlong user_request,par |
|||
' write out the block |
|||
mov user_cmd,#"w" |
|||
call #handle_command |
|||
' done |
|||
jmp #waiting_for_command |
|||
|
|||
{{ |
|||
Set user_cmd and user_idx before calling this |
|||
}} |
|||
handle_command |
|||
' Can we stay in the old mode? (address = old_address+1) && (old mode == new_mode) |
|||
cmp lastIndexPlus,user_idx wz |
|||
if_z cmp user_cmd,lastCommand wz |
|||
if_z jmp #:execute_block_command |
|||
' we fell through, must exit the old mode! (except if the old mode was "release") |
|||
cmp lastCommand,#"w" wz |
|||
if_z call #stop_mb_write |
|||
cmp lastCommand,#"r" wz |
|||
if_z call #stop_mb_read |
|||
' and start up the new mode! |
|||
cmp user_cmd,#"w" wz |
|||
if_z call #start_mb_write |
|||
cmp user_cmd,#"r" wz |
|||
if_z call #start_mb_read |
|||
cmp user_cmd,#"z" wz |
|||
if_z call #release_DO |
|||
:execute_block_command |
|||
' track the (new) last index and command |
|||
mov lastIndexPlus,user_idx |
|||
add lastIndexPlus,#1 |
|||
mov lastCommand,user_cmd |
|||
' do the block read or write or terminate! |
|||
cmp user_cmd,#"w" wz |
|||
if_z call #write_single_block |
|||
cmp user_cmd,#"r" wz |
|||
if_z call #read_single_block |
|||
cmp user_cmd,#"z" wz |
|||
if_z mov user_cmd,#0 |
|||
' done |
|||
handle_command_ret |
|||
ret |
|||
|
|||
{=== these PASM functions get me in and out of multiblock mode ===} |
|||
release_DO |
|||
' we're already out of multiblock mode, so |
|||
' deselect the card and send out some clocks |
|||
or outa,maskCS |
|||
call #in8 |
|||
call #in8 |
|||
' if you are using pull-up resistors, and need all |
|||
' lines tristated, then uncomment the following line. |
|||
' for Cluso99 |
|||
'mov dira,#0 |
|||
release_DO_ret |
|||
ret |
|||
|
|||
start_mb_read |
|||
movi block_cmd,#CMD18<<1 |
|||
call #send_SPI_command_fast |
|||
start_mb_read_ret |
|||
ret |
|||
|
|||
stop_mb_read |
|||
movi block_cmd,#CMD12<<1 |
|||
call #send_SPI_command_fast |
|||
call #busy_fast |
|||
stop_mb_read_ret |
|||
ret |
|||
|
|||
start_mb_write |
|||
movi block_cmd,#CMD25<<1 |
|||
call #send_SPI_command_fast |
|||
start_mb_write_ret |
|||
ret |
|||
|
|||
stop_mb_write |
|||
call #busy_fast |
|||
' only some cards need these extra clocks |
|||
mov tmp1,#16 |
|||
:loopity |
|||
call #in8 |
|||
djnz tmp1,#:loopity |
|||
' done with hack |
|||
movi phsa,#$FD<<1 |
|||
call #out8 |
|||
call #in8 ' stuff byte |
|||
call #busy_fast |
|||
stop_mb_write_ret |
|||
ret |
|||
|
|||
send_SPI_command_fast |
|||
' make sure we have control of the output lines |
|||
mov dira,maskAll |
|||
' make sure the CS line transitions low |
|||
or outa,maskCS |
|||
andn outa,maskCS |
|||
' 8 clocks |
|||
call #in8 |
|||
' send the data |
|||
mov phsa,block_cmd ' do which ever block command this is (already in the top 8 bits) |
|||
call #out8 ' write the byte |
|||
mov phsa,user_idx ' read in the desired block index |
|||
shl phsa,adrShift ' this will multiply by 512 (bytes/sector) for MMC and SD |
|||
call #out8 ' move out the 1st MSB ' |
|||
rol phsa,#1 |
|||
call #out8 ' move out the 1st MSB ' |
|||
rol phsa,#1 |
|||
call #out8 ' move out the 1st MSB ' |
|||
rol phsa,#1 |
|||
call #out8 ' move out the 1st MSB ' |
|||
' bogus CRC value |
|||
call #in8 ' in8 looks like out8 with $FF |
|||
' CMD12 requires a stuff byte |
|||
shr block_cmd,#24 |
|||
cmp block_cmd,#CMD12 wz |
|||
if_z call #in8 ' 8 clocks |
|||
' get the response |
|||
mov tmp1,#9 |
|||
:cmd_response |
|||
call #in8 |
|||
test readback,#$80 wc,wz |
|||
if_c djnz tmp1,#:cmd_response |
|||
if_nz neg user_cmd,readback |
|||
' done |
|||
send_SPI_command_fast_ret |
|||
ret |
|||
|
|||
|
|||
busy_fast |
|||
mov tmp1,N_in8_500ms |
|||
:still_busy |
|||
call #in8 |
|||
cmp readback,#$FF wz |
|||
if_nz djnz tmp1,#:still_busy |
|||
busy_fast_ret |
|||
ret |
|||
|
|||
|
|||
out8 |
|||
andn outa,maskDI |
|||
'movi phsb,#%11_0000000 |
|||
mov phsb,#0 |
|||
movi frqb,#%01_0000000 |
|||
rol phsa,#1 |
|||
rol phsa,#1 |
|||
rol phsa,#1 |
|||
rol phsa,#1 |
|||
rol phsa,#1 |
|||
rol phsa,#1 |
|||
rol phsa,#1 |
|||
mov frqb,#0 |
|||
' don't shift out the final bit...already sent, but be aware |
|||
' of this when sending consecutive bytes (send_cmd, for e.g.) |
|||
out8_ret |
|||
ret |
|||
|
|||
{ |
|||
in8 |
|||
or outa,maskDI |
|||
mov ctra,readMode |
|||
' Start my clock |
|||
mov frqa,#1<<7 |
|||
mov phsa,#0 |
|||
movi phsb,#%11_0000000 |
|||
movi frqb,#%01_0000000 |
|||
' keep reading in my value, one bit at a time! (Kuneko - "Wh) |
|||
shr frqa,#1 |
|||
shr frqa,#1 |
|||
shr frqa,#1 |
|||
shr frqa,#1 |
|||
shr frqa,#1 |
|||
shr frqa,#1 |
|||
shr frqa,#1 |
|||
mov frqb,#0 ' stop the clock |
|||
mov readback,phsa |
|||
mov frqa,#0 |
|||
mov ctra,writeMode |
|||
in8_ret |
|||
ret |
|||
} |
|||
in8 |
|||
neg phsa,#1' DI high |
|||
mov readback,#0 |
|||
' set up my clock, and start it |
|||
movi phsb,#%011_000000 |
|||
movi frqb,#%001_000000 |
|||
' keep reading in my value |
|||
test maskDO,ina wc |
|||
rcl readback,#1 |
|||
test maskDO,ina wc |
|||
rcl readback,#1 |
|||
test maskDO,ina wc |
|||
rcl readback,#1 |
|||
test maskDO,ina wc |
|||
rcl readback,#1 |
|||
test maskDO,ina wc |
|||
rcl readback,#1 |
|||
test maskDO,ina wc |
|||
rcl readback,#1 |
|||
test maskDO,ina wc |
|||
rcl readback,#1 |
|||
test maskDO,ina wc |
|||
mov frqb,#0 ' stop the clock |
|||
rcl readback,#1 |
|||
mov phsa,#0 'DI low |
|||
in8_ret |
|||
ret |
|||
|
|||
|
|||
' this is called more frequently than 1 Hz, and |
|||
' is only called when the user command is 0. |
|||
handle_time |
|||
mov tmp1,cnt ' get the current timestamp |
|||
add idle_time,tmp1 ' add the current time to my idle time counter |
|||
sub idle_time,last_time ' subtract the last time from my idle counter (hence delta) |
|||
add dtime,tmp1 ' add to my accumulator, |
|||
sub dtime,last_time ' and subtract the old (adding delta) |
|||
mov last_time,tmp1 ' update my "last timestamp" |
|||
rdlong tmp1,#0 ' what is the clock frequency? |
|||
cmpsub dtime,tmp1 wc ' if I have more than a second in my accumulator |
|||
addx seconds,#0 ' then add it to "seconds" |
|||
' this part is to auto-release the card after a timeout |
|||
cmp idle_time,idle_limit wz,wc |
|||
if_b jmp #handle_time_ret ' don't clear if we haven't hit the limit |
|||
mov user_cmd,#"z" ' we can't overdo it, the command handler makes sure |
|||
neg lastIndexPlus,#1 ' reset the last block index |
|||
neg user_idx,#1 ' and make this match it |
|||
call #handle_command ' release the card, but don't mess with the user's request register |
|||
handle_time_ret |
|||
ret |
|||
|
|||
hub_cog_transfer |
|||
' setup for all 4 passes |
|||
mov ctrb,clockXferMode |
|||
mov frqb,#1 |
|||
rdlong buf_ptr,bufAdr |
|||
mov ops_left,#4 |
|||
movd transfer_long,#speed_buf |
|||
four_transfer_passes |
|||
' sync to the Hub RAM access |
|||
rdlong tmp1,tmp1 |
|||
' how many long to move on this pass? (512 bytes / 4)longs / 4 passes |
|||
mov tmp1,#(512 / 4 / 4) |
|||
' get my starting address right (phsb is incremented 1 per clock, so 16 each Hub access) |
|||
mov phsb,buf_ptr |
|||
' write the longs, stride 4...low 2 bits of phsb are ignored |
|||
transfer_long |
|||
rdlong 0-0,phsb |
|||
add transfer_long,incDest4 |
|||
djnz tmp1,#transfer_long |
|||
' go back to where I started, but advanced 1 long |
|||
sub transfer_long,decDestNminus1 |
|||
' offset my Hub pointer by one long per pass |
|||
add buf_ptr,#4 |
|||
' do all 4 passes |
|||
djnz ops_left,#four_transfer_passes |
|||
' restore the counter mode |
|||
mov frqb,#0 |
|||
mov phsb,#0 |
|||
mov ctrb,clockLineMode |
|||
hub_cog_transfer_ret |
|||
ret |
|||
|
|||
|
|||
read_single_block |
|||
' where am I sending the data? |
|||
movd :store_read_long,#speed_buf |
|||
mov ops_left,#128 |
|||
' wait until the card is ready |
|||
mov tmp1,N_in8_500ms |
|||
:get_resp |
|||
call #in8 |
|||
cmp readback,#$FE wz |
|||
if_nz djnz tmp1,#:get_resp |
|||
if_nz neg user_cmd,#ERR_ASM_NO_READ_TOKEN |
|||
if_nz jmp #read_single_block_ret |
|||
' set DI high |
|||
neg phsa,#1 |
|||
' read the data |
|||
mov ops_left,#128 |
|||
:read_loop |
|||
mov tmp1,#4 |
|||
movi phsb,#%011_000000 |
|||
:in_byte |
|||
' Start my clock |
|||
movi frqb,#%001_000000 |
|||
' keep reading in my value, BACKWARDS! (Brilliant idea by Tom Rokicki!) |
|||
test maskDO,ina wc |
|||
rcl readback,#8 |
|||
test maskDO,ina wc |
|||
muxc readback,#2 |
|||
test maskDO,ina wc |
|||
muxc readback,#4 |
|||
test maskDO,ina wc |
|||
muxc readback,#8 |
|||
test maskDO,ina wc |
|||
muxc readback,#16 |
|||
test maskDO,ina wc |
|||
muxc readback,#32 |
|||
test maskDO,ina wc |
|||
muxc readback,#64 |
|||
test maskDO,ina wc |
|||
mov frqb,#0 ' stop the clock |
|||
muxc readback,#128 |
|||
' go back for more |
|||
djnz tmp1,#:in_byte |
|||
' make it...NOT backwards [8^) |
|||
rev readback,#0 |
|||
:store_read_long |
|||
mov 0-0,readback ' due to some counter weirdness, we need this mov |
|||
add :store_read_long,const512 |
|||
djnz ops_left,#:read_loop |
|||
|
|||
' set DI low |
|||
mov phsa,#0 |
|||
|
|||
' now read 2 trailing bytes (CRC) |
|||
call #in8 ' out8 is 2x faster than in8 |
|||
call #in8 ' and I'm not using the CRC anyway |
|||
' give an extra 8 clocks in case we pause for a long time |
|||
call #in8 ' in8 looks like out8($FF) |
|||
|
|||
' all done successfully |
|||
mov idle_time,#0 |
|||
mov user_cmd,#0 |
|||
read_single_block_ret |
|||
ret |
|||
|
|||
write_single_block |
|||
' where am I getting the data? (all 512 bytes / 128 longs of it?) |
|||
movs :write_loop,#speed_buf |
|||
' read in 512 bytes (128 longs) from Hub RAM and write it to the card |
|||
mov ops_left,#128 |
|||
' just hold your horses |
|||
call #busy_fast |
|||
' $FC for multiblock, $FE for single block |
|||
movi phsa,#$FC<<1 |
|||
call #out8 |
|||
mov phsb,#0 ' make sure my clock accumulator is right |
|||
'movi phsb,#%11_0000000 |
|||
:write_loop |
|||
' read 4 bytes |
|||
mov phsa,speed_buf |
|||
add :write_loop,#1 |
|||
' a long in LE order is DCBA |
|||
rol phsa,#24 ' move A7 into position, so I can do the swizzled version |
|||
movi frqb,#%010000000 ' start the clock (remember A7 is already in place) |
|||
rol phsa,#1 ' A7 is going out, at the end of this instr, A6 is in place |
|||
rol phsa,#1 ' A5 |
|||
rol phsa,#1 ' A4 |
|||
rol phsa,#1 ' A3 |
|||
rol phsa,#1 ' A2 |
|||
rol phsa,#1 ' A1 |
|||
rol phsa,#1 ' A0 |
|||
rol phsa,#17 ' B7 |
|||
rol phsa,#1 ' B6 |
|||
rol phsa,#1 ' B5 |
|||
rol phsa,#1 ' B4 |
|||
rol phsa,#1 ' B3 |
|||
rol phsa,#1 ' B2 |
|||
rol phsa,#1 ' B1 |
|||
rol phsa,#1 ' B0 |
|||
rol phsa,#17 ' C7 |
|||
rol phsa,#1 ' C6 |
|||
rol phsa,#1 ' C5 |
|||
rol phsa,#1 ' C4 |
|||
rol phsa,#1 ' C3 |
|||
rol phsa,#1 ' C2 |
|||
rol phsa,#1 ' C1 |
|||
rol phsa,#1 ' C0 |
|||
rol phsa,#17 ' D7 |
|||
rol phsa,#1 ' D6 |
|||
rol phsa,#1 ' D5 |
|||
rol phsa,#1 ' D4 |
|||
rol phsa,#1 ' D3 |
|||
rol phsa,#1 ' D2 |
|||
rol phsa,#1 ' D1 |
|||
rol phsa,#1 ' D0 will be in place _after_ this instruction |
|||
mov frqb,#0 ' shuts the clock off, _after_ this instruction |
|||
djnz ops_left,#:write_loop |
|||
' write out my two (bogus, using $FF) CRC bytes |
|||
call #in8 |
|||
call #in8 |
|||
' now read response (I need this response, so can't spoof using out8) |
|||
call #in8 |
|||
and readback,#$1F |
|||
cmp readback,#5 wz |
|||
if_z mov user_cmd,#0 ' great |
|||
if_nz neg user_cmd,#ERR_ASM_BLOCK_NOT_WRITTEN ' oops |
|||
' send out another 8 clocks |
|||
call #in8 |
|||
' all done |
|||
mov idle_time,#0 |
|||
write_single_block_ret |
|||
ret |
|||
|
|||
|
|||
{=== Assembly Interface Variables ===} |
|||
pinDO long 0 ' pin is controlled by a counter |
|||
pinCLK long 0 ' pin is controlled by a counter |
|||
pinDI long 0 ' pin is controlled by a counter |
|||
maskDO long 0 ' mask for reading the DO line from the card |
|||
maskDI long 0 ' mask for setting the pin high while reading |
|||
maskCS long 0 ' mask = (1<<pin), and is controlled directly |
|||
maskAll long 0 |
|||
adrShift long 9 ' will be 0 for SDHC, 9 for MMC & SD |
|||
bufAdr long 0 ' where in Hub RAM is the buffer to copy to/from? |
|||
sdAdr long 0 ' where on the SD card does it read/write? |
|||
writeMode long 0 ' the counter setup in NCO single ended, clocking data out on pinDI |
|||
'clockOutMode long 0 ' the counter setup in NCO single ended, driving the clock line on pinCLK |
|||
N_in8_500ms long 1_000_000 ' used for timeout checking in PASM |
|||
'readMode long 0 |
|||
clockLineMode long 0 |
|||
clockXferMode long %11111 << 26 |
|||
const512 long 512 |
|||
const1024 long 1024 |
|||
incDest4 long 4 << 9 |
|||
decDestNminus1 long (512 / 4 - 1) << 9 |
|||
|
|||
{=== Initialized PASM Variables ===} |
|||
seconds long 0 |
|||
dtime long 0 |
|||
idle_time long 0 |
|||
idle_limit long 0 |
|||
|
|||
{=== Multiblock State Machine ===} |
|||
lastIndexPlus long -1 ' state handler will check against lastIndexPlus, which will not have been -1 |
|||
lastCommand long 0 ' this will never be the last command. |
|||
|
|||
{=== Debug Logging Pointers ===} |
|||
{ |
|||
dbg_ptr long 0 |
|||
dbg_end long 0 |
|||
'} |
|||
|
|||
{=== Assembly Scratch Variables ===} |
|||
ops_left res 1 ' used as a counter for bytes, words, longs, whatever (start w/ # byte clocks out) |
|||
readback res 1 ' all reading from the card goes through here |
|||
tmp1 res 1 ' this may get used in all subroutines...don't use except in lowest |
|||
user_request res 1 ' the main command variable, read in from Hub: "r"-read single, "w"-write single |
|||
user_cmd res 1 ' used internally to handle actual commands to be executed |
|||
user_idx res 1 ' the pointer to the Hub RAM where the data block is/goes |
|||
block_cmd res 1 ' one of the SD/MMC command codes, no app-specific allowed |
|||
buf_ptr res 1 ' moving pointer to the Hub RAM buffer |
|||
last_time res 1 ' tracking the timestamp |
|||
|
|||
{{ |
|||
496 longs is my total available space in the cog, |
|||
and I want 128 longs for eventual use as one 512- |
|||
byte buffer. This gives me a total of 368 longs |
|||
to use for umount, and a readblock and writeblock |
|||
for both Hub RAM and Cog buffers. |
|||
}} |
|||
speed_buf res 128 ' 512 bytes to be used for read-ahead / write-behind |
|||
|
|||
'fit 467 |
|||
FIT 496 |
|||
|
|||
'' 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. |
|||
}} |
|||
File diff suppressed because it is too large
@ -1 +0,0 @@ |
|||
bstc -Ox -ls -e -p0 -dCOM5: vgademo.spin |
|||
@ -1,17 +0,0 @@ |
|||
SPINC= bstc.linux |
|||
SPINC_FLAGS= -Ox -ls -e -p0 -d/dev/ttyS0 |
|||
INCLUDES= -L../lib |
|||
|
|||
VERSION= 0.0.4 |
|||
|
|||
all: vgademo |
|||
|
|||
vgademo: vgademo.spin vga8x8d.spin vt100.spin |
|||
$(SPINC) $(SPINC_FLAGS) $(INCLUDES) -o $@ $< |
|||
|
|||
clean: |
|||
rm -f *.eeprom *.lst *.list *.bck *.o |
|||
|
|||
dist: clean |
|||
cd .. && rm -f vgademo-$(VERSION).zip && \
|
|||
zip -r vgademo-$(VERSION).zip vga2 |
|||
Binary file not shown.
@ -1,619 +0,0 @@ |
|||
'' This object generates a 640x480 VGA signal which contains 80 columns x 30 |
|||
'' rows of 8x8 double scan characters. Each character can have a unique forground |
|||
'' and background color combination and each character can be inversed and highlit. |
|||
'' There are also two cursors which can be independently controlled (ie. mouse |
|||
'' and keyboard). A sync indicator signals each time the screen is refreshed |
|||
'' (you may ignore). |
|||
'' |
|||
'' You must provide buffers for the screen, cursors, and sync. Once started, |
|||
'' all interfacing is done via memory. To this object, all buffers are |
|||
'' read-only, with the exception of the sync indicator which gets written with |
|||
'' -1. You may freely write all buffers to affect screen appearance. Have fun! |
|||
'' |
|||
|
|||
CON |
|||
|
|||
' 640 x 480 @ 69Hz settings: 80 x 30 characters |
|||
|
|||
hp = 640 ' horizontal pixels |
|||
vp = 480 ' vertical pixels |
|||
hf = 24 ' horizontal front porch pixels |
|||
hs = 40 ' horizontal sync pixels |
|||
hb = 128 ' horizontal back porch pixels |
|||
vf = 20 ' vertical front porch lines |
|||
vs = 3 ' vertical sync lines |
|||
vb = 17 ' vertical back porch lines |
|||
hn = 1 ' horizontal normal sync state (0|1) |
|||
vn = 1 ' vertical normal sync state (0|1) |
|||
pr = 30 ' pixel rate in MHz at 80MHz system clock (5MHz granularity) |
|||
|
|||
' columns and rows |
|||
|
|||
cols = hp / 8 |
|||
rows = vp / 16 |
|||
|
|||
|
|||
VAR long cog[2] |
|||
|
|||
PUB start(BasePin, ScreenPtr, CursorPtr, SyncPtr) : okay | i, j |
|||
|
|||
'' Start VGA driver - starts two COGs |
|||
'' returns false if two COGs not available |
|||
'' |
|||
'' BasePin = VGA starting pin (0, 8, 16, 24, etc.) |
|||
'' |
|||
'' ScreenPtr = Pointer to 80x30 words containing Latin-1 codes and colors for |
|||
'' each of the 80x30 screen characters. The lower byte of the word |
|||
'' contains the Latin-1 code to display. The upper byte contains |
|||
'' the foreground colour in bits 11..8 and the background colour in |
|||
'' bits 15..12. |
|||
'' |
|||
'' screen word example: %00011111_01000001 = "A", white on blue |
|||
'' |
|||
'' CursorPtr = Pointer to 6 bytes which control the cursors: |
|||
'' |
|||
'' bytes 0,1,2: X, Y, and MODE of cursor 0 |
|||
'' bytes 3,4,5: X, Y, and MODE of cursor 1 |
|||
'' |
|||
'' X and Y are in terms of screen characters |
|||
'' (left-to-right, top-to-bottom) |
|||
'' |
|||
'' MODE uses three bottom bits: |
|||
'' |
|||
'' %x00 = cursor off |
|||
'' %x01 = cursor on |
|||
'' %x10 = cursor on, blink slow |
|||
'' %x11 = cursor on, blink fast |
|||
'' %0xx = cursor is solid block |
|||
'' %1xx = cursor is underscore |
|||
'' |
|||
'' cursor example: 127, 63, %010 = blinking block in lower-right |
|||
'' |
|||
'' SyncPtr = Pointer to long which gets written with -1 upon each screen |
|||
'' refresh. May be used to time writes/scrolls, so that chopiness |
|||
'' can be avoided. You must clear it each time if you want to see |
|||
'' it re-trigger. |
|||
|
|||
' if driver is already running, stop it |
|||
stop |
|||
|
|||
' implant pin settings |
|||
reg_vcfg := $200000FF + (BasePin & %111000) << 6 |
|||
i := $FF << (BasePin & %011000) |
|||
j := BasePin & %100000 == 0 |
|||
reg_dira := i & j |
|||
reg_dirb := i & !j |
|||
|
|||
' implant CNT value to sync COGs to |
|||
sync_cnt := cnt + $10000 |
|||
|
|||
' implant pointers |
|||
longmove(@screen_base, @ScreenPtr, 2) |
|||
font_base := @font |
|||
|
|||
' implant unique settings and launch first COG |
|||
vf_lines.byte := vf |
|||
vb_lines.byte := vb |
|||
font_part := 1 |
|||
cog[1] := cognew(@entry, SyncPtr) + 1 |
|||
|
|||
' allow time for first COG to launch |
|||
waitcnt($2000 + cnt) |
|||
|
|||
' differentiate settings and launch second COG |
|||
vf_lines.byte := vf+8 |
|||
vb_lines.byte := vb-8 |
|||
font_part := 0 |
|||
cog[0] := cognew(@entry, SyncPtr) + 1 |
|||
|
|||
' if both COGs launched, return true |
|||
if cog[0] and cog[1] |
|||
return true |
|||
|
|||
' else, stop any launched COG and return false |
|||
stop |
|||
|
|||
|
|||
PUB stop | i |
|||
|
|||
'' Stop VGA driver - frees two COGs |
|||
|
|||
repeat i from 0 to 1 |
|||
if cog[i] |
|||
cogstop(cog[i]~ - 1) |
|||
|
|||
|
|||
CON |
|||
hv_inactive = (hn << 1 + vn) * $0101 'H,V inactive states |
|||
|
|||
|
|||
DAT |
|||
|
|||
'***************************************************** |
|||
'* Assembly language VGA high-resolution text driver * |
|||
'***************************************************** |
|||
|
|||
' This program runs concurrently in two different COGs. |
|||
' |
|||
' Each COG's program has different values implanted for front-porch lines and |
|||
' back-porch lines which surround the vertical sync pulse lines. This allows |
|||
' timed interleaving of their active display signals during the visible portion |
|||
' of the field scan. Also, they are differentiated so that one COG displays |
|||
' even four-line groups while the other COG displays odd four-line groups. |
|||
' |
|||
' These COGs are launched in the PUB 'start' and are programmed to synchronize |
|||
' their PLL-driven video circuits so that they can alternately prepare sets of |
|||
' four scan lines and then display them. The COG-to-COG switchover is seemless |
|||
' due to two things: exact synchronization of the two video circuits and the |
|||
' fact that all COGs' driven output states get OR'd together, allowing one COG |
|||
' to output lows during its preparatory state while the other COG effectively |
|||
' drives the pins to create the visible and sync portions of its scan lines. |
|||
' During non-visible scan lines, both COGs output together in unison. |
|||
' |
|||
org 0 ' set origin to $000 for start of program |
|||
entry |
|||
' Initialization code and data - after execution, space gets reused as scanbuff |
|||
|
|||
' Init I/O registers and sync COGs' video circuits |
|||
|
|||
mov dira, reg_dira ' set pin directions |
|||
mov dirb, reg_dirb |
|||
movi frqa, #(pr / 5) << 2 ' set pixel rate |
|||
mov vcfg, reg_vcfg ' set video configuration |
|||
mov vscl, #1 ' set video to reload on every pixel |
|||
waitcnt sync_cnt, colormask ' wait for start value in cnt, add ~1ms |
|||
movi ctra, #%00001_110 ' COGs in sync! enable PLLs now - NCOs locked! |
|||
waitcnt sync_cnt, #0 ' wait ~1ms for PLLs to stabilize - PLLs locked! |
|||
mov vscl, #100 ' insure initial WAITVIDs lock cleanly |
|||
|
|||
' Main loop, display field - each COG alternately builds and displays four scan lines |
|||
|
|||
vsync mov x, #vs ' do vertical sync lines |
|||
call #blank_vsync |
|||
|
|||
vb_lines mov x, #vb ' do vertical back porch lines (# set at runtime) |
|||
call #blank_vsync |
|||
|
|||
mov screen_ptr, screen_base ' reset screen pointer to upper-left character |
|||
mov row, #0 ' reset row counter for cursor insertion |
|||
mov fours, #rows ' set number of 4-line builds for whole screen |
|||
|
|||
' Build four scan lines into scanbuff |
|||
|
|||
fourline mov font_ptr, font_part ' get address of appropriate font section |
|||
shl font_ptr, #7+2 |
|||
add font_ptr, font_base |
|||
|
|||
movd :pixa, #scanbuff-1 ' reset scanbuff address (pre-decremented) |
|||
movd :pixb, #scanbuff-1 ' reset scanbuff address (pre-decremented) |
|||
movd :cola, #colorbuff-1 ' reset colorbuff address (pre-decremented) |
|||
movd :colb, #colorbuff-1 |
|||
|
|||
mov y, #4 ' must build scanbuff in four sections because |
|||
mov vscl, vscl_line2x ' ..pixel counter is limited to twelve bits |
|||
|
|||
:halfrow waitvid underscore, #0 ' output lows to let other COG drive VGA pins |
|||
mov x, #cols/4 ' ..for 2 scan lines, ready for a quarter row |
|||
|
|||
:column rdword z, screen_ptr ' get character and colors from screen memory |
|||
mov bg, z |
|||
ror z, #7 |
|||
shr z, #32 - 9 wc |
|||
add z, font_ptr ' add font section address to point to 8*4 pixels |
|||
add :pixa, d0 ' increment scanbuff destination addresses |
|||
add :pixb, d0 ' increment scanbuff destination addresses |
|||
add screen_ptr, #2 ' increment screen memory address |
|||
cmp font_part, #1 wz |
|||
:pixa rdlong scanbuff, z ' read pixel long (8*4) into scanbuff |
|||
:pixb if_c_and_z or scanbuff, underline |
|||
|
|||
ror bg, #12 ' background color in bits 3..0 |
|||
mov fg, bg ' foreground color in bits 31..28 |
|||
shr fg, #28 ' bits 3..0 |
|||
add fg, #fg_clut ' + offset to foreground CLUT |
|||
movs :cola, fg |
|||
add :cola, d0 |
|||
add bg, #bg_clut ' + offset to background CLUT |
|||
movs :colb, bg |
|||
add :colb, d0 |
|||
:cola mov colorbuff, 0-0 |
|||
:colb or colorbuff, 0-0 |
|||
|
|||
djnz x, #:column ' another character in this half-row? |
|||
djnz y, #:halfrow ' loop to do 2nd half-row, time for 2nd WAITVID |
|||
|
|||
' Insert cursors into scanbuff |
|||
|
|||
mov z, #2 ' ready for two cursors |
|||
|
|||
:cursor rdbyte x, cursor_base ' x in range? |
|||
add cursor_base, #1 |
|||
cmp x, #cols wc |
|||
|
|||
rdbyte y, cursor_base ' y match? |
|||
add cursor_base, #1 |
|||
cmp y, row wz |
|||
|
|||
rdbyte y, cursor_base ' get cursor mode |
|||
add cursor_base, #1 |
|||
|
|||
if_nc_or_nz jmp #:nocursor ' if cursor not in scanbuff, no cursor |
|||
|
|||
add x, #scanbuff ' cursor in scanbuff, set scanbuff address |
|||
movd :xor, x |
|||
|
|||
test y, #%010 wc ' get mode bits into flags |
|||
test y, #%001 wz |
|||
if_nc_and_z jmp #:nocursor ' if cursor disabled, no cursor |
|||
|
|||
if_c_and_z test slowbit, cnt wc ' if blink mode, get blink state |
|||
if_c_and_nz test fastbit, cnt wc |
|||
|
|||
test y, #%100 wz ' get box or underscore cursor piece |
|||
if_z mov x, longmask |
|||
if_nz mov x, underscore |
|||
if_nz cmp font_part, #1 wz ' if underscore, must be last font section |
|||
|
|||
:xor if_nc_and_z xor scanbuff, x ' conditionally xor cursor into scanbuff |
|||
|
|||
:nocursor djnz z, #:cursor ' second cursor? |
|||
|
|||
sub cursor_base, #3*2 ' restore cursor base |
|||
|
|||
' Display four scan lines from scanbuff |
|||
|
|||
mov y, #4 ' ready for four scan lines |
|||
scanline |
|||
mov x, #2 wc ' clear carry and set sweep count |
|||
sweep |
|||
mov vscl, vscl_chr |
|||
waitvid colorbuff+ 0, scanbuff+ 0 |
|||
if_c ror scanbuff+ 0, #8 |
|||
waitvid colorbuff+ 1, scanbuff+ 1 |
|||
if_c ror scanbuff+ 1, #8 |
|||
waitvid colorbuff+ 2, scanbuff+ 2 |
|||
if_c ror scanbuff+ 2, #8 |
|||
waitvid colorbuff+ 3, scanbuff+ 3 |
|||
if_c ror scanbuff+ 3, #8 |
|||
waitvid colorbuff+ 4, scanbuff+ 4 |
|||
if_c ror scanbuff+ 4, #8 |
|||
waitvid colorbuff+ 5, scanbuff+ 5 |
|||
if_c ror scanbuff+ 5, #8 |
|||
waitvid colorbuff+ 6, scanbuff+ 6 |
|||
if_c ror scanbuff+ 6, #8 |
|||
waitvid colorbuff+ 7, scanbuff+ 7 |
|||
if_c ror scanbuff+ 7, #8 |
|||
|
|||
waitvid colorbuff+ 8, scanbuff+ 8 |
|||
if_c ror scanbuff+ 8, #8 |
|||
waitvid colorbuff+ 9, scanbuff+ 9 |
|||
if_c ror scanbuff+ 9, #8 |
|||
waitvid colorbuff+10, scanbuff+10 |
|||
if_c ror scanbuff+10, #8 |
|||
waitvid colorbuff+11, scanbuff+11 |
|||
if_c ror scanbuff+11, #8 |
|||
waitvid colorbuff+12, scanbuff+12 |
|||
if_c ror scanbuff+12, #8 |
|||
waitvid colorbuff+13, scanbuff+13 |
|||
if_c ror scanbuff+13, #8 |
|||
waitvid colorbuff+14, scanbuff+14 |
|||
if_c ror scanbuff+14, #8 |
|||
waitvid colorbuff+15, scanbuff+15 |
|||
if_c ror scanbuff+15, #8 |
|||
|
|||
waitvid colorbuff+16, scanbuff+16 |
|||
if_c ror scanbuff+16, #8 |
|||
waitvid colorbuff+17, scanbuff+17 |
|||
if_c ror scanbuff+17, #8 |
|||
waitvid colorbuff+18, scanbuff+18 |
|||
if_c ror scanbuff+18, #8 |
|||
waitvid colorbuff+19, scanbuff+19 |
|||
if_c ror scanbuff+19, #8 |
|||
waitvid colorbuff+20, scanbuff+20 |
|||
if_c ror scanbuff+20, #8 |
|||
waitvid colorbuff+21, scanbuff+21 |
|||
if_c ror scanbuff+21, #8 |
|||
waitvid colorbuff+22, scanbuff+22 |
|||
if_c ror scanbuff+22, #8 |
|||
waitvid colorbuff+23, scanbuff+23 |
|||
if_c ror scanbuff+23, #8 |
|||
|
|||
waitvid colorbuff+24, scanbuff+24 |
|||
if_c ror scanbuff+24, #8 |
|||
waitvid colorbuff+25, scanbuff+25 |
|||
if_c ror scanbuff+25, #8 |
|||
waitvid colorbuff+26, scanbuff+26 |
|||
if_c ror scanbuff+26, #8 |
|||
waitvid colorbuff+27, scanbuff+27 |
|||
if_c ror scanbuff+27, #8 |
|||
waitvid colorbuff+28, scanbuff+28 |
|||
if_c ror scanbuff+28, #8 |
|||
waitvid colorbuff+29, scanbuff+29 |
|||
if_c ror scanbuff+29, #8 |
|||
waitvid colorbuff+30, scanbuff+30 |
|||
if_c ror scanbuff+30, #8 |
|||
waitvid colorbuff+31, scanbuff+31 |
|||
if_c ror scanbuff+31, #8 |
|||
|
|||
waitvid colorbuff+32, scanbuff+32 |
|||
if_c ror scanbuff+32, #8 |
|||
waitvid colorbuff+33, scanbuff+33 |
|||
if_c ror scanbuff+33, #8 |
|||
waitvid colorbuff+34, scanbuff+34 |
|||
if_c ror scanbuff+34, #8 |
|||
waitvid colorbuff+35, scanbuff+35 |
|||
if_c ror scanbuff+35, #8 |
|||
waitvid colorbuff+36, scanbuff+36 |
|||
if_c ror scanbuff+36, #8 |
|||
waitvid colorbuff+37, scanbuff+37 |
|||
if_c ror scanbuff+37, #8 |
|||
waitvid colorbuff+38, scanbuff+38 |
|||
if_c ror scanbuff+38, #8 |
|||
waitvid colorbuff+39, scanbuff+39 |
|||
if_c ror scanbuff+39, #8 |
|||
|
|||
waitvid colorbuff+40, scanbuff+40 |
|||
if_c ror scanbuff+40, #8 |
|||
waitvid colorbuff+41, scanbuff+41 |
|||
if_c ror scanbuff+41, #8 |
|||
waitvid colorbuff+42, scanbuff+42 |
|||
if_c ror scanbuff+42, #8 |
|||
waitvid colorbuff+43, scanbuff+43 |
|||
if_c ror scanbuff+43, #8 |
|||
waitvid colorbuff+44, scanbuff+44 |
|||
if_c ror scanbuff+44, #8 |
|||
waitvid colorbuff+45, scanbuff+45 |
|||
if_c ror scanbuff+45, #8 |
|||
waitvid colorbuff+46, scanbuff+46 |
|||
if_c ror scanbuff+46, #8 |
|||
waitvid colorbuff+47, scanbuff+47 |
|||
if_c ror scanbuff+47, #8 |
|||
|
|||
waitvid colorbuff+48, scanbuff+48 |
|||
if_c ror scanbuff+48, #8 |
|||
waitvid colorbuff+49, scanbuff+49 |
|||
if_c ror scanbuff+49, #8 |
|||
waitvid colorbuff+50, scanbuff+50 |
|||
if_c ror scanbuff+50, #8 |
|||
waitvid colorbuff+51, scanbuff+51 |
|||
if_c ror scanbuff+51, #8 |
|||
waitvid colorbuff+52, scanbuff+52 |
|||
if_c ror scanbuff+52, #8 |
|||
waitvid colorbuff+53, scanbuff+53 |
|||
if_c ror scanbuff+53, #8 |
|||
waitvid colorbuff+54, scanbuff+54 |
|||
if_c ror scanbuff+54, #8 |
|||
waitvid colorbuff+55, scanbuff+55 |
|||
if_c ror scanbuff+55, #8 |
|||
|
|||
waitvid colorbuff+56, scanbuff+56 |
|||
if_c ror scanbuff+56, #8 |
|||
waitvid colorbuff+57, scanbuff+57 |
|||
if_c ror scanbuff+57, #8 |
|||
waitvid colorbuff+58, scanbuff+58 |
|||
if_c ror scanbuff+58, #8 |
|||
waitvid colorbuff+59, scanbuff+59 |
|||
if_c ror scanbuff+59, #8 |
|||
waitvid colorbuff+60, scanbuff+60 |
|||
if_c ror scanbuff+60, #8 |
|||
waitvid colorbuff+61, scanbuff+61 |
|||
if_c ror scanbuff+61, #8 |
|||
waitvid colorbuff+62, scanbuff+62 |
|||
if_c ror scanbuff+62, #8 |
|||
waitvid colorbuff+63, scanbuff+63 |
|||
if_c ror scanbuff+63, #8 |
|||
|
|||
waitvid colorbuff+64, scanbuff+64 |
|||
if_c ror scanbuff+64, #8 |
|||
waitvid colorbuff+65, scanbuff+65 |
|||
if_c ror scanbuff+65, #8 |
|||
waitvid colorbuff+66, scanbuff+66 |
|||
if_c ror scanbuff+66, #8 |
|||
waitvid colorbuff+67, scanbuff+67 |
|||
if_c ror scanbuff+67, #8 |
|||
waitvid colorbuff+68, scanbuff+68 |
|||
if_c ror scanbuff+68, #8 |
|||
waitvid colorbuff+69, scanbuff+69 |
|||
if_c ror scanbuff+69, #8 |
|||
waitvid colorbuff+70, scanbuff+70 |
|||
if_c ror scanbuff+70, #8 |
|||
waitvid colorbuff+71, scanbuff+71 |
|||
if_c ror scanbuff+71, #8 |
|||
|
|||
waitvid colorbuff+72, scanbuff+72 |
|||
if_c ror scanbuff+72, #8 |
|||
waitvid colorbuff+73, scanbuff+73 |
|||
if_c ror scanbuff+73, #8 |
|||
waitvid colorbuff+74, scanbuff+74 |
|||
if_c ror scanbuff+74, #8 |
|||
waitvid colorbuff+75, scanbuff+75 |
|||
if_c ror scanbuff+75, #8 |
|||
waitvid colorbuff+76, scanbuff+76 |
|||
if_c ror scanbuff+76, #8 |
|||
waitvid colorbuff+77, scanbuff+77 |
|||
if_c ror scanbuff+77, #8 |
|||
waitvid colorbuff+78, scanbuff+78 |
|||
if_c ror scanbuff+78, #8 |
|||
waitvid colorbuff+79, scanbuff+79 |
|||
|
|||
mov vscl, #hf ' do horizontal front porch pixels |
|||
waitvid hvsync, #0 ' #0 makes hsync inactive |
|||
mov vscl, #hs ' do horizontal sync pixels |
|||
waitvid hvsync, #1 ' #1 makes hsync active |
|||
mov vscl, #hb ' do horizontal back porch pixels |
|||
waitvid hvsync, #0 ' #0 makes hsync inactive |
|||
if_c ror scanbuff+79, #8 |
|||
test x, #2 wc ' set carry |
|||
djnz x, #sweep |
|||
djnz y, #scanline ' another scan line? |
|||
|
|||
' Next group of four scan lines |
|||
|
|||
add row, #1 ' if new row, increment row counter |
|||
djnz fours, #fourline ' another 4-line build/display? |
|||
|
|||
' Visible section done, do vertical sync front porch lines |
|||
|
|||
wrlong longmask,par ' write -1 to refresh indicator |
|||
|
|||
vf_lines mov x,#vf ' do vertical front porch lines (# set at runtime) |
|||
call #blank |
|||
|
|||
jmp #vsync ' new field, loop to vsync |
|||
|
|||
' Subroutine - do blank lines |
|||
|
|||
blank_vsync xor hvsync,#$101 ' flip vertical sync bits |
|||
|
|||
blank mov vscl, hx ' do blank pixels |
|||
waitvid hvsync, #0 |
|||
mov vscl, #hf ' do horizontal front porch pixels |
|||
waitvid hvsync, #0 |
|||
mov vscl, #hs ' do horizontal sync pixels |
|||
waitvid hvsync, #1 |
|||
mov vscl, #hb ' do horizontal back porch pixels |
|||
waitvid hvsync, #0 |
|||
djnz x, #blank ' another line? |
|||
blank_ret |
|||
blank_vsync_ret |
|||
ret |
|||
|
|||
' Data |
|||
|
|||
screen_base long 0 ' set at runtime (3 contiguous longs) |
|||
cursor_base long 0 ' set at runtime |
|||
|
|||
font_base long 0 ' set at runtime |
|||
font_part long 0 ' set at runtime |
|||
|
|||
hx long hp ' visible pixels per scan line |
|||
vscl_line2x long (hp + hf + hs + hb) * 2 ' total number of pixels per 2 scan lines |
|||
vscl_chr long 1 << 12 + 8 ' 1 clock per pixel and 8 pixels per set |
|||
colormask long $fcfc ' mask to isolate R,G,B bits from H,V |
|||
longmask long $ffffffff ' all bits set |
|||
slowbit long 1 << 25 ' cnt mask for slow cursor blink |
|||
fastbit long 1 << 24 ' cnt mask for fast cursor blink |
|||
underscore long $ffff0000 ' underscore cursor pattern |
|||
underline long $ff000000 |
|||
hv long hv_inactive ' -H,-V states |
|||
hvsync long hv_inactive ^ $200 ' +/-H,-V states |
|||
d0 long 1 << 9 |
|||
d0s0 long 1 << 9 + 1 |
|||
d1 long 1 << 10 |
|||
reg_dira long 0 ' set at runtime |
|||
reg_dirb long 0 ' set at runtime |
|||
reg_vcfg long 0 ' set at runtime |
|||
sync_cnt long 0 ' set at runtime |
|||
|
|||
bg_clut long %00000011_00000011 ' black |
|||
long %00000011_00001011 ' dark blue |
|||
long %00000011_00100011 ' dark green |
|||
long %00000011_00101011 ' dark cyan |
|||
long %00000011_10000011 ' dark red |
|||
long %00000011_10001011 ' dark magenta |
|||
long %00000011_10100011 ' brown |
|||
long %00000011_10101011 ' light gray |
|||
long %00000011_01010111 ' dark gray |
|||
long %00000011_00001111 ' light blue |
|||
long %00000011_00110011 ' light green |
|||
long %00000011_00111111 ' light cyan |
|||
long %00000011_11000011 ' light red |
|||
long %00000011_11001111 ' light magenta |
|||
long %00000011_11110011 ' light yellow |
|||
long %00000011_11111111 ' white |
|||
|
|||
fg_clut long %00000011_00000011 ' black |
|||
long %00000111_00000011 ' dark blue |
|||
long %00010011_00000011 ' dark green |
|||
long %00010111_00000011 ' dark cyan |
|||
long %01000011_00000011 ' dark red |
|||
long %01000111_00000011 ' dark magenta |
|||
long %01010011_00000011 ' brown |
|||
long %10101011_00000011 ' light gray |
|||
long %01010111_00000011 ' dark gray |
|||
long %00001011_00000011 ' blue |
|||
long %00100011_00000011 ' green |
|||
long %00101011_00000011 ' cyan |
|||
long %10000011_00000011 ' red |
|||
long %10001011_00000011 ' magenta |
|||
long %10100011_00000011 ' yellow |
|||
long %11111111_00000011 ' white |
|||
|
|||
' Uninitialized data |
|||
|
|||
screen_ptr res 1 |
|||
font_ptr res 1 |
|||
|
|||
x res 1 |
|||
y res 1 |
|||
z res 1 |
|||
fg res 1 |
|||
bg res 1 |
|||
|
|||
row res 1 |
|||
fours res 1 |
|||
|
|||
scanbuff res 80 |
|||
colorbuff res 80 |
|||
|
|||
fit $1f0 |
|||
|
|||
' 8 x 12 font - characters 0..127 |
|||
' |
|||
' Each long holds four scan lines of a single character. The longs are arranged into |
|||
' groups of 128 which represent all characters (0..127). There are four groups which |
|||
' each contain a vertical part of all characters. They are ordered top, middle, and |
|||
' bottom. |
|||
|
|||
font long |
|||
long $00000000,$0f0f0f0f,$f0f0f0f0,$ffffffff,$00000000,$0f0f0f0f,$f0f0f0f0,$ffffffff |
|||
long $00000000,$0f0f0f0f,$f0f0f0f0,$ffffffff,$00000000,$0f0f0f0f,$f0f0f0f0,$ffffffff |
|||
long $7e5a3c00,$7e3c1800,$7e7e2400,$7e3c1800,$f8000000,$1f000000,$f8181818,$1f181818 |
|||
long $18181818,$ff000000,$1f181818,$f8181818,$ff181818,$ff000000,$ff181818,$aa55aa55 |
|||
long $00000000,$18181800,$66666600,$66ff6600,$3c067c18,$18366600,$1c386c38,$18181800 |
|||
long $0c0c1830,$3030180c,$ff3c6600,$7e181800,$00000000,$7e000000,$00000000,$18306000 |
|||
long $76663c00,$181c1800,$30663c00,$18307e00,$3c383000,$3e067e00,$3e063c00,$30607e00 |
|||
long $3c663c00,$7c663c00,$18180000,$18180000,$0c183060,$007e0000,$30180c06,$30663c00 |
|||
long $76663c00,$663c1800,$3e663e00,$06663c00,$66361e00,$3e067e00,$3e067e00,$06067c00 |
|||
long $7e666600,$18187e00,$60606000,$1e366600,$06060600,$feeec600,$7e6e6600,$66663c00 |
|||
long $66663e00,$66663c00,$66663e00,$3c063c00,$18187e00,$66666600,$66666600,$d6c6c600 |
|||
long $3c666600,$3c666600,$18307e00,$0c0c0c3c,$0c060200,$3030303c,$c66c3810,$00000000 |
|||
long $30180c00,$603c0000,$3e060600,$063c0000,$7c606000,$663c0000,$7c187000,$667c0000 |
|||
long $3e060600,$1c001800,$60006000,$36060600,$18181c00,$fe660000,$663e0000,$663c0000 |
|||
long $663e0000,$667c0000,$663e0000,$067c0000,$187e1800,$66660000,$66660000,$d6c60000 |
|||
long $3c660000,$66660000,$307e0000,$0c181830,$18181800,$3018180c,$0000366c,$142a142a |
|||
|
|||
long $00000000,$00000000,$00000000,$00000000,$0f0f0f0f,$0f0f0f0f,$0f0f0f0f,$0f0f0f0f |
|||
long $f0f0f0f0,$f0f0f0f0,$f0f0f0f0,$f0f0f0f0,$ffffffff,$ffffffff,$ffffffff,$ffffffff |
|||
long $007e187e,$007e187e,$00183c7e,$00183c7e,$181818f8,$1818181f,$000000f8,$0000001f |
|||
long $18181818,$000000ff,$1818181f,$181818f8,$000000ff,$181818ff,$181818ff,$aa55aa55 |
|||
long $00000000,$00180018,$00000000,$0066ff66,$00183e60,$0062660c,$00dc66f6,$00000000 |
|||
long $30180c0c,$0c183030,$0000663c,$00001818,$0c181800,$00000000,$00181800,$0002060c |
|||
long $003c666e,$007e1818,$007e0c18,$003c6630,$00307e36,$003c6660,$003c6666,$000c0c18 |
|||
long $003c6666,$001c3060,$00181800,$0c181800,$00603018,$00007e00,$00060c18,$00180018 |
|||
long $007c0676,$00667e66,$003e6666,$003c6606,$001e3666,$007e0606,$00060606,$007c6676 |
|||
long $00666666,$007e1818,$003c6660,$0066361e,$007e0606,$00c6c6d6,$0066767e,$003c6666 |
|||
long $0006063e,$006c3666,$0066363e,$003c6060,$00181818,$007e6666,$00183c66,$00c6eefe |
|||
long $0066663c,$00181818,$007e060c,$3c0c0c0c,$00603018,$3c303030,$00000000,$ff000000 |
|||
long $00000000,$007c667c,$003e6666,$003c0606,$007c6666,$003c067e,$00181818,$3e607c66 |
|||
long $00666666,$003c1818,$3c606060,$0066361e,$003c1818,$00c6d6fe,$00666666,$003c6666 |
|||
long $06063e66,$60607c66,$00060606,$003e603c,$00701818,$007c6666,$00183c66,$006c7cfe |
|||
long $00663c18,$1e307c66,$007e0c18,$00301818,$00181818,$000c1818,$00000000,$002a142a |
|||
|
|||
|
|||
{{ |
|||
+------------------------------------------------------------------------------------------------------------------------------+ |
|||
| TERMS OF USE: Parallax Object Exchange 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. | |
|||
+------------------------------------------------------------------------------------------------------------------------------+ |
|||
}} |
|||
@ -1,602 +0,0 @@ |
|||
''*************************************** |
|||
''* VGA High-Res Text Driver v1.0 * |
|||
''* Author: Chip Gracey * |
|||
''* Copyright (c) 2006 Parallax, Inc. * |
|||
''* See end of file for terms of use. * |
|||
''*************************************** |
|||
'' |
|||
'' This object generates a 640x480 VGA signal which contains 80 columns x 30 |
|||
'' rows of 8x16 characters. Each character can have a unique forground/background |
|||
'' color combination and each character can be inversed and high-lighted. |
|||
'' There are also two cursors which can be independently controlled (ie. mouse |
|||
'' and keyboard). A sync indicator signals each time the screen is refreshed |
|||
'' (you may ignore). |
|||
'' |
|||
'' You must provide buffers for the screen, cursors, and sync. Once started, |
|||
'' all interfacing is done via memory. To this object, all buffers are |
|||
'' read-only, with the exception of the sync indicator which gets written with |
|||
'' -1. You may freely write all buffers to affect screen appearance. Have fun! |
|||
'' |
|||
|
|||
CON |
|||
|
|||
' 640 x 480 @ 69Hz settings: 80 x 30 characters |
|||
|
|||
hp = 640 ' horizontal pixels |
|||
vp = 480 ' vertical pixels |
|||
hf = 24 ' horizontal front porch pixels |
|||
hs = 40 ' horizontal sync pixels |
|||
hb = 128 ' horizontal back porch pixels |
|||
vf = 20 ' vertical front porch lines |
|||
vs = 3 ' vertical sync lines |
|||
vb = 17 ' vertical back porch lines |
|||
hn = 1 ' horizontal normal sync state (0|1) |
|||
vn = 1 ' vertical normal sync state (0|1) |
|||
pr = 30 ' pixel rate in MHz at 80MHz system clock (5MHz granularity) |
|||
|
|||
' columns and rows |
|||
|
|||
cols = hp / 8 |
|||
rows = vp / 16 |
|||
|
|||
|
|||
VAR long cog[2] |
|||
|
|||
PUB start(BasePin, ScreenPtr, CursorPtr, SyncPtr) : okay | i, j |
|||
|
|||
'' Start VGA driver - starts two COGs |
|||
'' returns false if two COGs not available |
|||
'' |
|||
'' BasePin = VGA starting pin (0, 8, 16, 24, etc.) |
|||
'' |
|||
'' ScreenPtr = Pointer to 80x30 words containing Latin-1 codes and colors for |
|||
'' each of the 80x30 screen characters. The lower byte of the word |
|||
'' contains the Latin-1 code to display. The upper byte contains |
|||
'' the foreground colour in bits 11..8 and the background colour in |
|||
'' bits 15..12. |
|||
'' |
|||
'' screen word example: %00011111_01000001 = "A", white on blue |
|||
'' |
|||
'' CursorPtr = Pointer to 6 bytes which control the cursors: |
|||
'' |
|||
'' bytes 0,1,2: X, Y, and MODE of cursor 0 |
|||
'' bytes 3,4,5: X, Y, and MODE of cursor 1 |
|||
'' |
|||
'' X and Y are in terms of screen characters |
|||
'' (left-to-right, top-to-bottom) |
|||
'' |
|||
'' MODE uses three bottom bits: |
|||
'' |
|||
'' %x00 = cursor off |
|||
'' %x01 = cursor on |
|||
'' %x10 = cursor on, blink slow |
|||
'' %x11 = cursor on, blink fast |
|||
'' %0xx = cursor is solid block |
|||
'' %1xx = cursor is underscore |
|||
'' |
|||
'' cursor example: 127, 63, %010 = blinking block in lower-right |
|||
'' |
|||
'' SyncPtr = Pointer to long which gets written with -1 upon each screen |
|||
'' refresh. May be used to time writes/scrolls, so that chopiness |
|||
'' can be avoided. You must clear it each time if you want to see |
|||
'' it re-trigger. |
|||
|
|||
' if driver is already running, stop it |
|||
stop |
|||
|
|||
' implant pin settings |
|||
reg_vcfg := $200000FF + (BasePin & %111000) << 6 |
|||
i := $FF << (BasePin & %011000) |
|||
j := BasePin & %100000 == 0 |
|||
reg_dira := i & j |
|||
reg_dirb := i & !j |
|||
|
|||
' implant CNT value to sync COGs to |
|||
sync_cnt := cnt + $10000 |
|||
|
|||
' implant pointers |
|||
longmove(@screen_base, @ScreenPtr, 2) |
|||
font_base := @font |
|||
|
|||
' implant unique settings and launch first COG |
|||
vf_lines.byte := vf |
|||
vb_lines.byte := vb |
|||
font_part := 1 |
|||
cog[1] := cognew(@d0, SyncPtr) + 1 |
|||
|
|||
' allow time for first COG to launch |
|||
waitcnt($2000 + cnt) |
|||
|
|||
' differentiate settings and launch second COG |
|||
vf_lines.byte := vf+4 |
|||
vb_lines.byte := vb-4 |
|||
font_part := 0 |
|||
cog[0] := cognew(@d0, SyncPtr) + 1 |
|||
|
|||
' if both COGs launched, return true |
|||
if cog[0] and cog[1] |
|||
return true |
|||
|
|||
' else, stop any launched COG and return false |
|||
stop |
|||
|
|||
|
|||
PUB stop | i |
|||
|
|||
'' Stop VGA driver - frees two COGs |
|||
|
|||
repeat i from 0 to 1 |
|||
if cog[i] |
|||
cogstop(cog[i]~ - 1) |
|||
|
|||
|
|||
CON |
|||
|
|||
#1, scanbuff[80], colorbuff[80], scancode[2*80-1+3], maincode 'enumerate COG RAM usage |
|||
|
|||
main_size = $1F0 - maincode 'size of main program |
|||
|
|||
hv_inactive = (hn << 1 + vn) * $0101 'H,V inactive states |
|||
|
|||
|
|||
DAT |
|||
|
|||
'***************************************************** |
|||
'* Assembly language VGA high-resolution text driver * |
|||
'***************************************************** |
|||
|
|||
' This program runs concurrently in two different COGs. |
|||
' |
|||
' Each COG's program has different values implanted for front-porch lines and |
|||
' back-porch lines which surround the vertical sync pulse lines. This allows |
|||
' timed interleaving of their active display signals during the visible portion |
|||
' of the field scan. Also, they are differentiated so that one COG displays |
|||
' even four-line groups while the other COG displays odd four-line groups. |
|||
' |
|||
' These COGs are launched in the PUB 'start' and are programmed to synchronize |
|||
' their PLL-driven video circuits so that they can alternately prepare sets of |
|||
' four scan lines and then display them. The COG-to-COG switchover is seemless |
|||
' due to two things: exact synchronization of the two video circuits and the |
|||
' fact that all COGs' driven output states get OR'd together, allowing one COG |
|||
' to output lows during its preparatory state while the other COG effectively |
|||
' drives the pins to create the visible and sync portions of its scan lines. |
|||
' During non-visible scan lines, both COGs output together in unison. |
|||
' |
|||
' COG RAM usage: $000 = d0 - used to inc destination fields for indirection |
|||
' $001-$050 = scanbuff - longs which hold 4 scan lines |
|||
' $051-$010 = colorbuff - longs which hold colors for 80 characters |
|||
' $0a1-$142 = scancode - stacked WAITVID/SHR for fast display |
|||
' $143-$1EF = maincode - main program loop which drives display |
|||
|
|||
org 0 ' set origin to $000 for start of program |
|||
|
|||
d0 long 1 << 9 ' d0 always resides here at $000, executes as NOP |
|||
|
|||
|
|||
' Initialization code and data - after execution, space gets reused as scanbuff |
|||
|
|||
' Move main program into maincode area |
|||
|
|||
:move mov $1EF, main_begin + main_size - 1 |
|||
sub :move,d0s0 ' (do reverse move to avoid overwrite) |
|||
djnz main_ctr,#:move |
|||
|
|||
' Build scanbuff display routine into scancode |
|||
|
|||
:waitvid mov scancode+0, i0 ' org scancode |
|||
:shr mov scancode+1, i1 ' waitvid colorbuff+0, scanbuff+0 |
|||
add :waitvid, d1 ' shr scanbuff+0,#8 |
|||
add :shr, d1 ' waitvid colorbuff+1, scanbuff+1 |
|||
add i0, d0s0 ' shr scanbuff+1,#8 |
|||
add i1, d0 ' ... |
|||
djnz scan_ctr, #:waitvid ' waitvid colorbuff+cols-1, scanbuff+cols-1 |
|||
|
|||
mov scancode+cols*2-1, i2 ' mov vscl,#hf |
|||
mov scancode+cols*2+0, i3 ' waitvid hvsync,#0 |
|||
mov scancode+cols*2+1, i4 ' jmp #scanret |
|||
|
|||
' Init I/O registers and sync COGs' video circuits |
|||
|
|||
mov dira, reg_dira ' set pin directions |
|||
mov dirb, reg_dirb |
|||
movi frqa, #(pr / 5) << 2 ' set pixel rate |
|||
mov vcfg, reg_vcfg ' set video configuration |
|||
mov vscl, #1 ' set video to reload on every pixel |
|||
waitcnt sync_cnt, colormask ' wait for start value in cnt, add ~1ms |
|||
movi ctra, #%00001_110 ' COGs in sync! enable PLLs now - NCOs locked! |
|||
waitcnt sync_cnt, #0 ' wait ~1ms for PLLs to stabilize - PLLs locked! |
|||
mov vscl, #100 ' insure initial WAITVIDs lock cleanly |
|||
|
|||
' Jump to main loop |
|||
|
|||
jmp #vsync ' jump to vsync - WAITVIDs will now be locked! |
|||
|
|||
' Data |
|||
|
|||
d0s0 long 1 << 9 + 1 |
|||
d1 long 1 << 10 |
|||
main_ctr long main_size |
|||
scan_ctr long cols |
|||
|
|||
i0 waitvid colorbuff+0, scanbuff+0 |
|||
i1 shr scanbuff+0, #8 |
|||
i2 mov vscl, #hf |
|||
i3 waitvid hvsync, #0 |
|||
i4 jmp #scanret |
|||
|
|||
reg_dira long 0 ' set at runtime |
|||
reg_dirb long 0 ' set at runtime |
|||
reg_vcfg long 0 ' set at runtime |
|||
sync_cnt long 0 ' set at runtime |
|||
|
|||
' Directives |
|||
|
|||
fit scancode ' make sure initialization code and data fit |
|||
main_begin org maincode ' main code follows (gets moved into maincode) |
|||
|
|||
|
|||
' Main loop, display field - each COG alternately builds and displays four scan lines |
|||
|
|||
vsync mov x, #vs ' do vertical sync lines |
|||
call #blank_vsync |
|||
|
|||
vb_lines mov x, #vb ' do vertical back porch lines (# set at runtime) |
|||
call #blank_vsync |
|||
|
|||
mov screen_ptr, screen_base ' reset screen pointer to upper-left character |
|||
mov row, #0 ' reset row counter for cursor insertion |
|||
mov fours, #rows * 4 / 2 ' set number of 4-line builds for whole screen |
|||
|
|||
' Build four scan lines into scanbuff |
|||
|
|||
fourline mov font_ptr, font_part ' get address of appropriate font section |
|||
shl font_ptr, #8+2 |
|||
add font_ptr, font_base |
|||
|
|||
movd :pixa, #scanbuff-1 ' reset scanbuff address (pre-decremented) |
|||
movd :cola, #colorbuff-1 ' reset colorbuff address (pre-decremented) |
|||
movd :colb, #colorbuff-1 |
|||
|
|||
mov y, #2 ' must build scanbuff in two sections because |
|||
mov vscl, vscl_line2x ' ..pixel counter is limited to twelve bits |
|||
|
|||
:halfrow waitvid underscore, #0 ' output lows to let other COG drive VGA pins |
|||
mov x, #cols/2 ' ..for 2 scan lines, ready for half a row |
|||
|
|||
:column rdword z, screen_ptr ' get character and colors from screen memory |
|||
mov bg, z |
|||
and z, #$ff ' mask character code |
|||
shl z, #2 ' * 4 |
|||
add z, font_ptr ' add font section address to point to 8*4 pixels |
|||
add :pixa, d0 ' increment scanbuff destination addresses |
|||
add screen_ptr, #2 ' increment screen memory address |
|||
:pixa rdlong scanbuff, z ' read pixel long (8*4) into scanbuff |
|||
|
|||
ror bg, #12 ' background color in bits 3..0 |
|||
mov fg, bg ' foreground color in bits 31..28 |
|||
shr fg, #28 ' bits 3..0 |
|||
add fg, #fg_clut ' + offset to foreground CLUT |
|||
movs :cola, fg |
|||
add :cola, d0 |
|||
add bg, #bg_clut ' + offset to background CLUT |
|||
movs :colb, bg |
|||
add :colb, d0 |
|||
:cola mov colorbuff, 0-0 |
|||
:colb or colorbuff, 0-0 |
|||
|
|||
djnz x, #:column ' another character in this half-row? |
|||
|
|||
djnz y, #:halfrow ' loop to do 2nd half-row, time for 2nd WAITVID |
|||
|
|||
sub screen_ptr, #2*cols ' back up to start of same row in screen memory |
|||
|
|||
' Insert cursors into scanbuff |
|||
|
|||
mov z, #2 ' ready for two cursors |
|||
|
|||
:cursor rdbyte x, cursor_base ' x in range? |
|||
add cursor_base, #1 |
|||
cmp x, #cols wc |
|||
|
|||
rdbyte y, cursor_base ' y match? |
|||
add cursor_base, #1 |
|||
cmp y, row wz |
|||
|
|||
rdbyte y, cursor_base ' get cursor mode |
|||
add cursor_base, #1 |
|||
|
|||
if_nc_or_nz jmp #:nocursor ' if cursor not in scanbuff, no cursor |
|||
|
|||
add x, #scanbuff ' cursor in scanbuff, set scanbuff address |
|||
movd :xor, x |
|||
|
|||
test y, #%010 wc ' get mode bits into flags |
|||
test y, #%001 wz |
|||
if_nc_and_z jmp #:nocursor ' if cursor disabled, no cursor |
|||
|
|||
if_c_and_z test slowbit, cnt wc ' if blink mode, get blink state |
|||
if_c_and_nz test fastbit, cnt wc |
|||
|
|||
test y, #%100 wz ' get box or underscore cursor piece |
|||
if_z mov x, longmask |
|||
if_nz mov x, underscore |
|||
if_nz cmp font_part, #3 wz ' if underscore, must be last font section |
|||
|
|||
:xor if_nc_and_z xor scanbuff, x ' conditionally xor cursor into scanbuff |
|||
|
|||
:nocursor djnz z, #:cursor ' second cursor? |
|||
|
|||
sub cursor_base, #3*2 ' restore cursor base |
|||
|
|||
' Display four scan lines from scanbuff |
|||
|
|||
mov y, #4 ' ready for four scan lines |
|||
|
|||
scanline mov vscl, vscl_chr ' set pixel rate for characters |
|||
jmp #scancode ' jump to scanbuff display routine in scancode |
|||
scanret mov vscl, #hs ' do horizontal sync pixels |
|||
waitvid hvsync, #1 ' #1 makes hsync active |
|||
mov vscl, #hb ' do horizontal back porch pixels |
|||
waitvid hvsync, #0 ' #0 makes hsync inactive |
|||
shr scanbuff+cols-1, #8 ' shift last column's pixels right by 8 |
|||
djnz y, #scanline ' another scan line? |
|||
|
|||
' Next group of four scan lines |
|||
|
|||
add font_part, #2 ' if font_part + 2 => 4, subtract 4 (new row) |
|||
cmpsub font_part, #4 wc ' c=0 for same row, c=1 for new row |
|||
if_c add screen_ptr, #2*cols ' if new row, advance screen pointer |
|||
if_c add row, #1 ' if new row, increment row counter |
|||
djnz fours, #fourline ' another 4-line build/display? |
|||
|
|||
' Visible section done, do vertical sync front porch lines |
|||
|
|||
wrlong longmask,par ' write -1 to refresh indicator |
|||
|
|||
vf_lines mov x,#vf ' do vertical front porch lines (# set at runtime) |
|||
call #blank |
|||
|
|||
jmp #vsync ' new field, loop to vsync |
|||
|
|||
' Subroutine - do blank lines |
|||
|
|||
blank_vsync xor hvsync,#$101 ' flip vertical sync bits |
|||
|
|||
blank mov vscl, hx ' do blank pixels |
|||
waitvid hvsync, #0 |
|||
mov vscl, #hf ' do horizontal front porch pixels |
|||
waitvid hvsync, #0 |
|||
mov vscl, #hs ' do horizontal sync pixels |
|||
waitvid hvsync, #1 |
|||
mov vscl, #hb ' do horizontal back porch pixels |
|||
waitvid hvsync, #0 |
|||
djnz x,#blank ' another line? |
|||
blank_ret |
|||
blank_vsync_ret |
|||
ret |
|||
|
|||
' Data |
|||
|
|||
screen_base long 0 ' set at runtime (3 contiguous longs) |
|||
cursor_base long 0 ' set at runtime |
|||
|
|||
font_base long 0 ' set at runtime |
|||
font_part long 0 ' set at runtime |
|||
|
|||
hx long hp ' visible pixels per scan line |
|||
vscl_line long hp + hf + hs + hb ' total number of pixels per scan line |
|||
vscl_line2x long (hp + hf + hs + hb) * 2 ' total number of pixels per 2 scan lines |
|||
vscl_chr long 1 << 12 + 8 ' 1 clock per pixel and 8 pixels per set |
|||
colormask long $FCFC ' mask to isolate R,G,B bits from H,V |
|||
longmask long $FFFFFFFF ' all bits set |
|||
slowbit long 1 << 25 ' cnt mask for slow cursor blink |
|||
fastbit long 1 << 24 ' cnt mask for fast cursor blink |
|||
underscore long $FFFF0000 ' underscore cursor pattern |
|||
hv long hv_inactive ' -H,-V states |
|||
hvsync long hv_inactive ^ $200 ' +/-H,-V states |
|||
|
|||
bg_clut long %00000011_00000011 ' black |
|||
long %00000011_00001011 ' dark blue |
|||
long %00000011_00100011 ' dark green |
|||
long %00000011_00101011 ' dark cyan |
|||
long %00000011_10000011 ' dark red |
|||
long %00000011_10001011 ' dark magenta |
|||
long %00000011_10100011 ' brown |
|||
long %00000011_10101011 ' light gray |
|||
long %00000011_01010111 ' dark gray |
|||
long %00000011_00001111 ' light blue |
|||
long %00000011_00110011 ' light green |
|||
long %00000011_00111111 ' light cyan |
|||
long %00000011_11000011 ' light red |
|||
long %00000011_11001111 ' light magenta |
|||
long %00000011_11110011 ' light yellow |
|||
long %00000011_11111111 ' white |
|||
|
|||
fg_clut long %00000011_00000011 ' black |
|||
long %00000111_00000011 ' dark blue |
|||
long %00010011_00000011 ' dark green |
|||
long %00010111_00000011 ' dark cyan |
|||
long %01000011_00000011 ' dark red |
|||
long %01000111_00000011 ' dark magenta |
|||
long %01010011_00000011 ' brown |
|||
long %10101011_00000011 ' light gray |
|||
long %01010111_00000011 ' dark gray |
|||
long %00001011_00000011 ' blue |
|||
long %00100011_00000011 ' green |
|||
long %00101011_00000011 ' cyan |
|||
long %10000011_00000011 ' red |
|||
long %10001011_00000011 ' magenta |
|||
long %10100011_00000011 ' yellow |
|||
long %11111111_00000011 ' white |
|||
|
|||
' Uninitialized data |
|||
|
|||
screen_ptr res 1 |
|||
font_ptr res 1 |
|||
|
|||
x res 1 |
|||
y res 1 |
|||
z res 1 |
|||
fg res 1 |
|||
bg res 1 |
|||
|
|||
row res 1 |
|||
fours res 1 |
|||
|
|||
|
|||
fit $1f0 |
|||
|
|||
' 8 x 12 font - characters 0..127 |
|||
' |
|||
' Each long holds four scan lines of a single character. The longs are arranged into |
|||
' groups of 128 which represent all characters (0..127). There are four groups which |
|||
' each contain a vertical part of all characters. They are ordered top, middle, and |
|||
' bottom. |
|||
|
|||
font long |
|||
long $0082ba00,$00000000,$2a552a00,$36360000,$061e0000,$061c0000,$06060000,$3c000000 |
|||
long $00000000,$6e660000,$66660000,$18181818,$00000000,$00000000,$18181818,$18181818 |
|||
long $0000ffff,$00000000,$00000000,$00000000,$00000000,$18181818,$18181818,$18181818 |
|||
long $00000000,$18181818,$60000000,$06000000,$00000000,$00000000,$38000000,$00000000 |
|||
long $00000000,$18000000,$36000000,$24000000,$18000000,$4e000000,$1c000000,$18000000 |
|||
long $30000000,$0c000000,$00000000,$00000000,$00000000,$00000000,$00000000,$60000000 |
|||
long $18000000,$18000000,$3c000000,$7e000000,$60000000,$7e000000,$3c000000,$7e000000 |
|||
long $3c000000,$3c000000,$00000000,$00000000,$60000000,$00000000,$06000000,$3c000000 |
|||
long $3c000000,$3c000000,$3e000000,$3c000000,$3e000000,$7e000000,$7e000000,$3c000000 |
|||
long $66000000,$7e000000,$60000000,$46000000,$06000000,$42000000,$66000000,$3c000000 |
|||
long $3e000000,$3c000000,$3e000000,$3c000000,$7e000000,$66000000,$66000000,$66000000 |
|||
long $42000000,$66000000,$7e000000,$3c000000,$06000000,$3c000000,$18000000,$00000000 |
|||
long $180c0000,$00000000,$06000000,$00000000,$60000000,$00000000,$38000000,$00000000 |
|||
long $06000000,$18000000,$60000000,$06000000,$1c000000,$00000000,$00000000,$00000000 |
|||
long $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000 |
|||
long $00000000,$00000000,$00000000,$38000000,$18000000,$1c000000,$4c000000,$aa55aa55 |
|||
long $00000000,$00000000,$2a552a00,$36360000,$061e0000,$061c0000,$06060000,$3c000000 |
|||
long $00000000,$6e660000,$66660000,$24242424,$00000000,$00000000,$24242424,$24242424 |
|||
long $00ff00ff,$ff000000,$00000000,$00000000,$00000000,$24242424,$24242424,$24242424 |
|||
long $00000000,$24242424,$60000000,$06000000,$00000000,$00000000,$38000000,$00000000 |
|||
long $00000000,$18000000,$36000000,$24000000,$18000000,$4e000000,$1c000000,$18000000 |
|||
long $30000000,$0c000000,$00000000,$00000000,$00000000,$00000000,$00000000,$60000000 |
|||
long $18000000,$18000000,$3c000000,$7e000000,$60000000,$7e000000,$3c000000,$7e000000 |
|||
long $3c000000,$3c000000,$00000000,$00000000,$60000000,$00000000,$06000000,$3c000000 |
|||
long $3c000000,$3c000000,$3e000000,$3c000000,$3e000000,$7e000000,$7e000000,$3c000000 |
|||
long $66000000,$7e000000,$60000000,$46000000,$06000000,$42000000,$66000000,$3c000000 |
|||
long $3e000000,$3c000000,$3e000000,$3c000000,$7e000000,$66000000,$66000000,$66000000 |
|||
long $42000000,$66000000,$7e000000,$3c000000,$06000000,$3c000000,$18000000,$00000000 |
|||
long $180c0000,$00000000,$06000000,$00000000,$60000000,$00000000,$38000000,$00000000 |
|||
long $06000000,$18000000,$60000000,$06000000,$1c000000,$00000000,$00000000,$00000000 |
|||
long $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000 |
|||
long $00000000,$00000000,$00000000,$38000000,$18000000,$1c000000,$4c000000,$aa55aa55 |
|||
long $82008282,$3c180000,$2a552a55,$0036363e,$0006060e,$001c0606,$001e0606,$003c6666 |
|||
long $187e1818,$0066767e,$00183c24,$1f181818,$1f000000,$f8000000,$f8181818,$ff181818 |
|||
long $00000000,$0000ffff,$00000000,$00000000,$00000000,$f8181818,$1f181818,$ff181818 |
|||
long $ff000000,$18181818,$0c060c30,$3060300c,$667e0000,$187e3030,$3e0c0c6c,$18180000 |
|||
long $00000000,$18181818,$00003636,$247e7e24,$3c1a5a3c,$18302e6a,$1c363636,$00181818 |
|||
long $0c0c1818,$30301818,$7e182400,$7e181800,$00000000,$00000000,$00000000,$18303060 |
|||
long $66666624,$18181a1c,$38606666,$3c183060,$666c7870,$663e0606,$3e060666,$30306060 |
|||
long $3c666666,$7c666666,$183c1800,$183c1800,$060c1830,$007e0000,$6030180c,$38606666 |
|||
long $6a7a6262,$7e666666,$3e666666,$06060666,$66666666,$3e060606,$3e060606,$76060666 |
|||
long $7e666666,$18181818,$60606060,$0e1e3666,$06060606,$667e7e66,$7e6e6e66,$66666666 |
|||
long $3e666666,$66666666,$3e666666,$3c060666,$18181818,$66666666,$24246666,$66666666 |
|||
long $183c2466,$183c3c66,$18306060,$0c0c0c0c,$180c0c06,$30303030,$0042663c,$00000000 |
|||
long $00000030,$603c0000,$663e0606,$663c0000,$667c6060,$663c0000,$1e0c0c6c,$665c0000 |
|||
long $663e0606,$181c0018,$60600060,$36660606,$18181818,$fe6a0000,$663e0000,$663c0000 |
|||
long $663e0000,$667c0000,$663e0000,$663c0000,$0c3e0c0c,$66660000,$66660000,$66660000 |
|||
long $66660000,$66660000,$607e0000,$0c180c0c,$18181818,$30183030,$0000327e,$aa55aa55 |
|||
long $00000000,$3c180000,$2a552a55,$0036363e,$0006060e,$001c0606,$001e0606,$003c6666 |
|||
long $187e1818,$0066767e,$00183c24,$20272424,$203f0000,$04fc0000,$04e42424,$00e72424 |
|||
long $00000000,$0000ff00,$ff000000,$00000000,$00000000,$04e42424,$20272424,$00e72424 |
|||
long $00ff0000,$24242424,$0c060c30,$3060300c,$667e0000,$187e3030,$3e0c0c6c,$18180000 |
|||
long $00000000,$18181818,$00003636,$247e7e24,$3c1a5a3c,$18302e6a,$1c363636,$00181818 |
|||
long $0c0c1818,$30301818,$7e182400,$7e181800,$00000000,$00000000,$00000000,$18303060 |
|||
long $66666624,$18181a1c,$38606666,$3c183060,$666c7870,$663e0606,$3e060666,$30306060 |
|||
long $3c666666,$7c666666,$183c1800,$183c1800,$060c1830,$007e0000,$6030180c,$38606666 |
|||
long $76766666,$7e666666,$3e666666,$06060666,$66666666,$3e060606,$3e060606,$76060666 |
|||
long $7e666666,$18181818,$60606060,$0e1e3666,$06060606,$667e7e66,$7e6e6e66,$66666666 |
|||
long $3e666666,$66666666,$3e666666,$3c060666,$18181818,$66666666,$24246666,$66666666 |
|||
long $183c2466,$183c3c66,$18306060,$0c0c0c0c,$180c0c06,$30303030,$0042663c,$00000000 |
|||
long $00000030,$603c0000,$663e0606,$663c0000,$667c6060,$663c0000,$1e0c0c6c,$665c0000 |
|||
long $663e0606,$181c0018,$60600060,$36660606,$18181818,$fe6a0000,$663e0000,$663c0000 |
|||
long $663e0000,$667c0000,$663e0000,$663c0000,$0c3e0c0c,$66660000,$66660000,$66660000 |
|||
long $66660000,$66660000,$607e0000,$0c180c0c,$18181818,$30183030,$0000327e,$aa55aa55 |
|||
long $82820082,$00183c7e,$2a552a55,$30303078,$18381878,$58385838,$18381878,$00000000 |
|||
long $007e0018,$18181818,$30303078,$0000001f,$1818181f,$181818f8,$000000f8,$181818ff |
|||
long $00000000,$00000000,$0000ffff,$ff000000,$00000000,$181818f8,$1818181f,$000000ff |
|||
long $181818ff,$18181818,$7e006030,$7e00060c,$66666666,$0c0c7e18,$3a6c0c0c,$00000000 |
|||
long $00000000,$18180018,$00000000,$24247e7e,$183c5a58,$7256740c,$5c367656,$00000000 |
|||
long $3018180c,$0c181830,$0024187e,$0018187e,$18383800,$0000007e,$3c180000,$06060c0c |
|||
long $18246666,$7e181818,$7e06060c,$3c666060,$60607e66,$3c666060,$3c666666,$0c0c1818 |
|||
long $3c666666,$3c666060,$3c180000,$18383800,$6030180c,$00007e00,$060c1830,$18180018 |
|||
long $3c62027a,$66666666,$3e666666,$3c660606,$3e666666,$7e060606,$06060606,$7c666666 |
|||
long $66666666,$7e181818,$3c666060,$4666361e,$7e060606,$66666666,$66667676,$3c666666 |
|||
long $06060606,$3c766e66,$4666361e,$3c666060,$18181818,$3c666666,$1818183c,$42667e7e |
|||
long $4266243c,$18181818,$7e06060c,$3c0c0c0c,$60603030,$3c303030,$00000000,$fe000000 |
|||
long $00000000,$7c66667c,$3e666666,$3c660606,$7c666666,$3c66067e,$0c0c0c0c,$3c063c66 |
|||
long $66666666,$7e181818,$60606060,$66361e1e,$7e181818,$c6c6d6d6,$66666666,$3c666666 |
|||
long $063e6666,$607c6666,$06060606,$3c66300c,$386c0c0c,$7c666666,$183c3c66,$247e7e66 |
|||
long $66663c3c,$607c6666,$7e060c30,$380c0c18,$18181818,$1c303018,$00000000,$aa55aa55 |
|||
long $00000000,$00183c7e,$2a552a55,$30303078,$18381878,$58385838,$18381878,$00000000 |
|||
long $007e0018,$18181818,$30303078,$00003f20,$24242720,$2424e404,$0000fc04,$2424e700 |
|||
long $00000000,$00000000,$0000ff00,$00ff0000,$00000000,$2424e404,$24242720,$0000ff00 |
|||
long $2424e700,$24242424,$7e006030,$7e00060c,$66666666,$0c0c7e18,$3a6c0c0c,$00000000 |
|||
long $00000000,$18180018,$00000000,$24247e7e,$183c5a58,$7256740c,$5c367656,$00000000 |
|||
long $3018180c,$0c181830,$0024187e,$0018187e,$18383800,$0000007e,$3c180000,$06060c0c |
|||
long $18246666,$7e181818,$7e06060c,$3c666060,$60607e66,$3c666060,$3c666666,$0c0c1818 |
|||
long $3c666666,$3c666060,$3c180000,$18383800,$6030180c,$00007e00,$060c1830,$18180018 |
|||
long $3c660676,$66666666,$3e666666,$3c660606,$3e666666,$7e060606,$06060606,$7c666666 |
|||
long $66666666,$7e181818,$3c666060,$4666361e,$7e060606,$66666666,$66667676,$3c666666 |
|||
long $06060606,$3c766e66,$4666361e,$3c666060,$18181818,$3c666666,$1818183c,$42667e7e |
|||
long $4266243c,$18181818,$7e06060c,$3c0c0c0c,$60603030,$3c303030,$00000000,$fe000000 |
|||
long $00000000,$7c66667c,$3e666666,$3c660606,$7c666666,$3c66067e,$0c0c0c0c,$3c063c66 |
|||
long $66666666,$7e181818,$60606060,$66361e1e,$7e181818,$c6c6d6d6,$66666666,$3c666666 |
|||
long $063e6666,$607c6666,$06060606,$3c66300c,$386c0c0c,$7c666666,$183c3c66,$247e7e66 |
|||
long $66663c3c,$607c6666,$7e060c30,$380c0c18,$18181818,$1c303018,$00000000,$aa55aa55 |
|||
long $00ba8200,$00000000,$00002a55,$00000030,$00000018,$00000058,$00000018,$00000000 |
|||
long $00000000,$00000078,$00000030,$00000000,$18181818,$18181818,$00000000,$18181818 |
|||
long $00000000,$00000000,$00000000,$000000ff,$ffff0000,$18181818,$18181818,$00000000 |
|||
long $18181818,$18181818,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000 |
|||
long $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000 |
|||
long $00000000,$00000000,$00000000,$00000000,$0000000c,$00000000,$00000018,$00000000 |
|||
long $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000 |
|||
long $00000000,$00000000,$00000018,$0000000c,$00000000,$00000000,$00000000,$00000000 |
|||
long $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000 |
|||
long $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000 |
|||
long $00000000,$00000060,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000 |
|||
long $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$000000fe |
|||
long $00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000,$00003c66 |
|||
long $00000000,$00000000,$00003c66,$00000000,$00000000,$00000000,$00000000,$00000000 |
|||
long $00000606,$00006060,$00000000,$00000000,$00000000,$00000000,$00000000,$00000000 |
|||
long $00000000,$00003c66,$00000000,$00000000,$00000000,$00000000,$00000000,$aa55aa55 |
|||
long $ff000000,$ff000000,$ff002a55,$ff000030,$ff000018,$ff000058,$ff000018,$ff000000 |
|||
long $ff000000,$ff000078,$ff000030,$00000000,$24242424,$24242424,$00000000,$24242424 |
|||
long $00000000,$00000000,$00000000,$000000ff,$ff00ff00,$24242424,$24242424,$00000000 |
|||
long $24242424,$24242424,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000 |
|||
long $ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000 |
|||
long $ff000000,$ff000000,$ff000000,$ff000000,$ff00000c,$ff000000,$ff000018,$ff000000 |
|||
long $ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000 |
|||
long $ff000000,$ff000000,$ff000018,$ff00000c,$ff000000,$ff000000,$ff000000,$ff000000 |
|||
long $ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000 |
|||
long $ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000 |
|||
long $ff000000,$ff000060,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000 |
|||
long $ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff0000fe |
|||
long $ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff003c66 |
|||
long $ff000000,$ff000000,$ff003c66,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000 |
|||
long $ff000606,$ff006060,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000 |
|||
long $ff000000,$ff003c66,$ff000000,$ff000000,$ff000000,$ff000000,$ff000000,$ff55aa55 |
|||
|
|||
|
|||
{{ |
|||
+------------------------------------------------------------------------------------------------------------------------------+ |
|||
| TERMS OF USE: Parallax Object Exchange 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. | |
|||
+------------------------------------------------------------------------------------------------------------------------------+ |
|||
}} |
|||
Binary file not shown.
File diff suppressed because it is too large
@ -1,102 +0,0 @@ |
|||
CON |
|||
_xinfreq = 5_000_000 ' Quartz is 5MHz |
|||
_clkmode = xtal1 + pll16x ' System clock is 80MHz |
|||
|
|||
#define DracBladeProp |
|||
|
|||
CHAR_W = 80 |
|||
CHAR_H = 30 |
|||
|
|||
OBJ |
|||
' vga : "vga8x8d" |
|||
vga : "vgacolour" |
|||
vt100 : "vt100" |
|||
|
|||
VAR |
|||
long params[6] |
|||
long seed |
|||
|
|||
PUB main |
|||
vga.start(16, @screen, @cursor, @sync) |
|||
params[0] := @command |
|||
params[1] := @screen |
|||
params[2] := @cursor |
|||
params[3] := @sync |
|||
params[4] := CHAR_W |
|||
params[5] := CHAR_H |
|||
|
|||
vt100.start(@params) |
|||
|
|||
seed := cnt |
|||
|
|||
str(string(27,"[2;34m",27,"[2J",27,"[H","Hello World!",13,10)) |
|||
str(string(27,"[7m","Inverse on",13,10)) |
|||
str(string(27,"[27m","Inverse off",13,10)) |
|||
str(string(27,"[1m","Highlite on",13,10)) |
|||
str(string(27,"[2m","Highlite off",13,10)) |
|||
str(string(27,"[4m","Underline on ",27,"[1m + highlite ",27,"[2m",27,"[7m + inverse ",27,"[0m all off + default color.",13,10)) |
|||
str(string(27,"[40m","BGD 0")) |
|||
str(string(27,"[41m","BGD 1")) |
|||
str(string(27,"[42m","BGD 2")) |
|||
str(string(27,"[43m","BGD 3")) |
|||
str(string(27,"[44m","BGD 4")) |
|||
str(string(27,"[45m","BGD 5")) |
|||
str(string(27,"[46m","BGD 6")) |
|||
str(string(27,"[47m","BGD 7",13,10)) |
|||
|
|||
str(string(27,"[41m")) |
|||
|
|||
str(string(27,"[30m","FGD 0")) |
|||
str(string(27,"[31m","FGD 1")) |
|||
str(string(27,"[32m","FGD 2")) |
|||
str(string(27,"[33m","FGD 3")) |
|||
str(string(27,"[34m","FGD 4")) |
|||
str(string(27,"[35m","FGD 5")) |
|||
str(string(27,"[36m","FGD 6")) |
|||
str(string(27,"[37m","FGD 7",13,10)) |
|||
str(string(27,"[1;40m")) |
|||
str(string(27,"[30m","FGD 0")) |
|||
str(string(27,"[31m","FGD 1")) |
|||
str(string(27,"[32m","FGD 2")) |
|||
str(string(27,"[33m","FGD 3")) |
|||
str(string(27,"[34m","FGD 4")) |
|||
str(string(27,"[35m","FGD 5")) |
|||
str(string(27,"[36m","FGD 6")) |
|||
str(string(27,"[37m","FGD 7",13,10)) |
|||
str(string(27,"[2m","The quick brown fox jumps over the lazy dog.", 13, 10)) |
|||
|
|||
str(string("Setting a scroll range below here.",13,10)) |
|||
str(string(27,"[24H","This part of the screen remains ",27,"[4mstatic",27,"[24m, since it is below the scrolling region.")) |
|||
str(string(27,"[12;23r",27,"[41m")) |
|||
repeat |
|||
chr(27) |
|||
chr("[") |
|||
chr("3") |
|||
chr("0" + rand & 7) |
|||
chr("m") |
|||
chr(27) |
|||
chr("[") |
|||
chr("4") |
|||
chr("0" + rand & 7) |
|||
chr("m") |
|||
str(string("Four score and seven years ago our ",27,"[1mfathers",27,"[2m brought forth, upon this continent, a new ",27,"[1mnation",27,"[2m, conceived in Liberty, and dedicated to the proposition that all men are created equal. ")) |
|||
waitcnt(clkfreq/4 + cnt) |
|||
|
|||
|
|||
PUB chr(ch) |
|||
command := $100 | ch |
|||
repeat while command |
|||
|
|||
PUB str(strptr) | i |
|||
repeat i from 0 to strsize(strptr) |
|||
chr(byte[strptr][i]) |
|||
|
|||
PUB rand |
|||
seed := seed * 1103515245 + 12345 + CNT / 7777 |
|||
return seed |
|||
|
|||
DAT |
|||
command long 0 |
|||
screen word $0720[CHAR_W*CHAR_H] |
|||
cursor byte 0,0,%110,0,0,0,0,0 |
|||
sync long 0 |
|||
File diff suppressed because it is too large
@ -0,0 +1,535 @@ |
|||
'' AnsiTerm.spin |
|||
'' |
|||
'' MODIFIED BY WAYNE WARTHEN FOR ANSI COLOR CHARACTER SUPPORT |
|||
'' |
|||
'' based on... |
|||
'' |
|||
'' VGA_1024.spin |
|||
'' |
|||
'' MODIFIED BY VINCE BRIEL FOR POCKETERM FEATURES |
|||
'' MODIIFED BY JEFF LEDGER / AKA OLDBITCOLLECTOR |
|||
'' |
|||
|
|||
CON |
|||
cols = 80 ' screen columns |
|||
rows = 40 ' screen rows |
|||
chars = rows * cols ' screen characters |
|||
termRows = 25 ' rows in terminal area |
|||
termChars = termRows * cols ' characters in terminal area |
|||
termLastRow = termChars - cols ' buffer pos of first char in last term row |
|||
statArea = termChars ' starting position of status area |
|||
statRows = rows - TermRows ' status area rows |
|||
blank = $20 |
|||
|
|||
OBJ |
|||
vga : "vgacolour" |
|||
'vga : "vga8x8d" |
|||
|
|||
VAR |
|||
word screen[chars] ' screen character buffer |
|||
word tmpl[cols] ' temporary line buffer |
|||
byte cursor[6] ' cursor info array (see CursorPtr description above) |
|||
long sync, loc, xloc, yloc ' sync used by VGA routine, others are local screen pointers |
|||
byte state ' Current state of state machine |
|||
word pos ' Current Position on the screen |
|||
word regionTop, regionBot ' Scroll region top/bottom |
|||
long arg0 ' First argument of escape sequence |
|||
long arg1 ' Second argument of escape sequence |
|||
byte lastc ' Last displayed char |
|||
long vgaBasePin |
|||
word curAttr ' active attribute value |
|||
word bold, underscore, blink, reverse, fg, bg |
|||
|
|||
|
|||
DAT |
|||
{ |
|||
color ansi rgb |
|||
----- ---- --- |
|||
black 0 0 |
|||
red 1 4 |
|||
green 2 2 |
|||
yellow 3 6 |
|||
blue 4 1 |
|||
magenta 5 5 |
|||
cyan 6 3 |
|||
white 7 7 |
|||
} |
|||
cmap WORD 0,4,2,6,1,5,3,7 ' Map ANSI color codes to VGA driver RGB |
|||
|
|||
PUB start(BasePin) | i, char |
|||
vgaBasePin := BasePin |
|||
|
|||
cursor[2] := %110 ' init cursor to underscore with slow blink |
|||
xloc := cursor[0] := 0 |
|||
yloc := cursor[1] := 0 |
|||
loc := xloc + yloc * cols |
|||
|
|||
pos := 0 |
|||
regionTop := 0 |
|||
regionBot := termChars |
|||
state := 0 |
|||
bold := 0 |
|||
underscore := 0 |
|||
blink := 0 |
|||
reverse := 0 |
|||
fg := 0 |
|||
bg := 0 |
|||
setMode(0) ' reset attributes |
|||
|
|||
PUB vidOn |
|||
if (!vga.start(vgaBasePin, @screen, @cursor, @sync)) |
|||
return false |
|||
|
|||
PUB vidOff |
|||
vga.stop |
|||
|
|||
PUB cls |
|||
wordfill(@screen, (curAttr | blank), chars) |
|||
|
|||
PUB dec(value) | i |
|||
|
|||
'' Print a decimal number |
|||
|
|||
if value < 0 |
|||
-value |
|||
outc("-") |
|||
|
|||
i := 1_000_000_000 |
|||
|
|||
repeat 10 |
|||
if value => i |
|||
outc(value/i + "0") |
|||
value //= i |
|||
result~~ |
|||
elseif result or i == 1 |
|||
outc("0") |
|||
i /= 10 |
|||
|
|||
PUB bin(value, digits) |
|||
|
|||
'' Print a binary number, specify number of digits |
|||
|
|||
repeat while digits > 32 |
|||
outc("0") |
|||
digits-- |
|||
|
|||
value <<= 32 - digits |
|||
|
|||
repeat digits |
|||
outc((value <-= 1) & 1 + "0") |
|||
|
|||
|
|||
PUB hex(value, digits) |
|||
|
|||
'' Print a hexadecimal number, specify number of digits |
|||
|
|||
repeat while digits > 8 |
|||
outc("0") |
|||
digits-- |
|||
|
|||
value <<= (8 - digits) << 2 |
|||
|
|||
repeat digits |
|||
outc(lookupz((value <-= 4) & $f : "0".."9", "A".."F")) |
|||
|
|||
|
|||
PUB str(string_ptr) |
|||
|
|||
'' Print a zero terminated string |
|||
|
|||
repeat strsize(string_ptr) |
|||
outc(byte[string_ptr++]) |
|||
|
|||
PUB statInfo |
|||
result := (statRows << 8) | cols |
|||
|
|||
PUB statStr(row, col, attr, strVal) | nxtPos |
|||
nxtPos := statArea + (row * cols) + col |
|||
repeat strsize(strVal) |
|||
screen[nxtPos++] := (attr | byte[strVal++]) |
|||
|
|||
PUB statFill(row, col, attr, charVal, count) |
|||
wordfill(@screen + ((statArea + (row * cols) + col) * 2), (attr | charVal), count) |
|||
|
|||
PRI clsTerm |
|||
wordfill (@screen, (curAttr | blank), termChars) |
|||
|
|||
PRI outc(c) |
|||
|
|||
screen[pos++] := (curAttr | c) |
|||
lastc := c |
|||
|
|||
if pos == regionBot |
|||
scrollUp |
|||
pos -= cols |
|||
elseif pos == termChars |
|||
pos := termLastRow |
|||
|
|||
PRI setMode(n) |
|||
if (n == 0) |
|||
bold := 0 |
|||
underscore := 0 |
|||
blink := 0 |
|||
reverse := 0 |
|||
fg := 7 |
|||
bg := 0 |
|||
elseif (n == 1) |
|||
bold := 1 |
|||
elseif (n == 4) |
|||
underscore := 1 |
|||
elseif (n == 5) |
|||
blink := 1 |
|||
elseif (n == 7) |
|||
reverse := 1 |
|||
elseif ((n => 30) & (n =< 37)) |
|||
fg := cmap[(n - 30)] |
|||
elseif ((n => 40) & (n =< 47)) |
|||
bg := cmap[(n - 40)] |
|||
|
|||
if (reverse == 0) |
|||
curAttr := ((fg << 8) | (bg << 12)) |
|||
else |
|||
curAttr := ((fg << 12) | (bg << 8)) |
|||
|
|||
curAttr |= (bold << 11) | (underscore << 7) | (blink << 15) |
|||
|
|||
PRI clEOL(position) | count |
|||
count := cols - (position // cols) |
|||
wordfill(@screen + (position * 2), (curAttr | blank), count) |
|||
|
|||
PRI clBOL(position) | count |
|||
count := position // cols |
|||
wordfill(@screen + ((position - count) * 2), (curAttr | blank), count) |
|||
|
|||
PRI delLine(position) | src, count |
|||
position -= position // cols |
|||
|
|||
src := position + cols |
|||
|
|||
count := termChars - src |
|||
|
|||
if count > 0 |
|||
wordmove(@screen + (position * 2), @screen + (src * 2), count) |
|||
|
|||
wordfill(@screen + (termLastRow * 2), (curAttr | blank), cols) |
|||
|
|||
PRI clEOS(position) |
|||
cleol(position) |
|||
position += cols - (position // cols) |
|||
repeat while position < termChars |
|||
wordfill(@screen + (position * 2), (curAttr | blank), cols) |
|||
pos += cols |
|||
|
|||
PRI setCursorPos(position) |
|||
cursor[0] := position // cols |
|||
cursor[1] := position / cols |
|||
|
|||
PRI insLine(position) | base, nxt |
|||
base := position - (position // cols) |
|||
position := termLastRow |
|||
repeat while position > base |
|||
nxt := position - cols |
|||
wordmove(@screen + (position * 2), @screen + (nxt * 2), cols) |
|||
position := nxt |
|||
clEOL(base) |
|||
|
|||
PRI insChar(position) | count |
|||
count := (cols - (position // cols)) - 1 |
|||
wordmove(@tmpl, @screen + (position * 2), count) |
|||
screen[position] := (curAttr | blank) |
|||
wordmove(@screen + ((position + 1) * 2), @tmpl, count) |
|||
|
|||
PRI delChar(position) | count |
|||
count := (cols - (position // cols)) - 1 |
|||
wordmove(@screen + (position * 2), @screen + ((position + 1) * 2), count) |
|||
screen[position + count] := (curAttr | blank) |
|||
|
|||
PRI inRegion : answer |
|||
answer := (pos => regionTop) AND (pos < regionBot) |
|||
|
|||
PRI scrollUp |
|||
delLine(regionTop) |
|||
if regionBot < termChars |
|||
insLine(regionBot) |
|||
|
|||
PRI scrollDown |
|||
if regionBot < termChars |
|||
delLine(regionBot) |
|||
insLine(regionTop) |
|||
|
|||
PRI ansi(c) | x, defVal |
|||
|
|||
state := 0 |
|||
|
|||
if (c <> "r") AND (c <> "J") AND (c <> "m") AND (c <> "K") |
|||
if arg0 == -1 |
|||
arg0 := 1 |
|||
if arg1 == -1 |
|||
arg1 := 1 |
|||
|
|||
case c |
|||
"@": |
|||
repeat while arg0-- > 0 |
|||
insChar(pos) |
|||
|
|||
"b": |
|||
repeat while arg0-- > 0 |
|||
outc(lastc) |
|||
|
|||
"d": |
|||
if (arg0 < 1) OR (arg0 > rows) |
|||
arg0 := rows |
|||
pos := ((arg0 - 1) * cols) + (pos // cols) |
|||
|
|||
"m": |
|||
if (arg0 == -1) |
|||
setMode(0) |
|||
else |
|||
setMode(arg0) |
|||
if arg1 <> -1 |
|||
setMode(arg1) |
|||
|
|||
"r": |
|||
if arg0 < 1 |
|||
arg0 := 1 |
|||
elseif arg0 > cols |
|||
arg0 := cols |
|||
if arg1 < 1 |
|||
arg1 := 1 |
|||
elseif arg1 > cols |
|||
arg1 := cols |
|||
if arg1 < arg0 |
|||
arg1 := arg0 |
|||
|
|||
regionTop := (arg0 - 1) * cols |
|||
regionBot := arg1 * cols |
|||
pos := 0 |
|||
|
|||
"A": |
|||
repeat while arg0-- > 0 |
|||
pos -= cols |
|||
if pos < 0 |
|||
pos += cols |
|||
return |
|||
|
|||
"B": |
|||
repeat while arg0-- > 0 |
|||
pos += cols |
|||
if pos => termChars |
|||
pos -= cols |
|||
return |
|||
|
|||
"C": |
|||
repeat while arg0-- > 0 |
|||
pos += 1 |
|||
if pos => termChars |
|||
pos -= 1 |
|||
return |
|||
|
|||
"D": |
|||
repeat while arg0-- > 0 |
|||
pos -= 1 |
|||
if pos < 0 |
|||
pos := 0 |
|||
return |
|||
|
|||
"G": |
|||
if (arg0 < 1) OR (arg0 > cols) |
|||
arg0 := cols |
|||
pos := (pos - (pos // cols)) + (arg0 - 1) |
|||
|
|||
"H", "f": |
|||
if arg0 =< 0 |
|||
arg0 := 1 |
|||
if arg1 =< 0 |
|||
arg1 := 1 |
|||
pos := (cols * (arg0 - 1)) + (arg1 - 1) |
|||
if pos < 0 |
|||
pos := 0 |
|||
if pos => termChars |
|||
pos := termChars - 1 |
|||
|
|||
"J": |
|||
if arg0 == 1 |
|||
clBOL(pos) |
|||
x := pos - cols |
|||
x -= x // cols |
|||
repeat while x => 0 |
|||
clEOL(x) |
|||
x -= cols |
|||
return |
|||
|
|||
if arg0 == 2 |
|||
pos := 0 |
|||
|
|||
clEOL(pos) |
|||
x := pos + cols |
|||
x -= (x // cols) |
|||
repeat while x < termChars |
|||
clEOL(x) |
|||
x += cols |
|||
|
|||
"K": |
|||
if arg0 == -1 |
|||
clEOL(pos) |
|||
elseif arg0 == 1 |
|||
clBOL(pos) |
|||
else |
|||
clEOL(pos - (pos // cols)) |
|||
|
|||
"L": |
|||
if inRegion |
|||
repeat while arg0-- > 0 |
|||
if regionBot < termChars |
|||
delLine(regionBot) |
|||
insLine(pos) |
|||
|
|||
"M": |
|||
if inRegion |
|||
repeat while arg0-- > 0 |
|||
delLine(pos) |
|||
if regionBot < termChars |
|||
insLine(regionBot) |
|||
|
|||
"P": |
|||
repeat while arg0-- |
|||
delChar(pos) |
|||
|
|||
PUB processChar(c) |
|||
|
|||
case state |
|||
|
|||
0: ' Default state (no escape sequence in process) |
|||
if c > 127 |
|||
c := $20 |
|||
|
|||
if c => $20 |
|||
outc(c) |
|||
setCursorPos(pos) |
|||
return |
|||
|
|||
if c == $1B |
|||
state := 1 |
|||
return |
|||
|
|||
if c == $0D |
|||
pos := pos - (pos // cols) |
|||
setCursorPos(pos) |
|||
return |
|||
|
|||
if c == $0A |
|||
if inRegion |
|||
pos += cols |
|||
if pos => regionBot |
|||
scrollUp |
|||
pos -= cols |
|||
else |
|||
pos += cols |
|||
if pos => termChars |
|||
pos -= cols |
|||
setCursorPos(pos) |
|||
return |
|||
|
|||
if c == 9 |
|||
pos += (8 - (pos // 8)) |
|||
|
|||
if pos => termChars |
|||
pos := termLastRow |
|||
delLine(0) |
|||
|
|||
setCursorPos(pos) |
|||
return |
|||
|
|||
if c == 8 |
|||
if pos > 0 |
|||
pos -= 1 |
|||
setCursorPos(pos) |
|||
return |
|||
|
|||
1: ' Process char following escape |
|||
case c |
|||
"[": |
|||
arg0 := arg1 := -1 |
|||
state := 2 |
|||
return |
|||
|
|||
"P": |
|||
pos += cols |
|||
if pos => termChars |
|||
pos -= cols |
|||
|
|||
"K": |
|||
if pos > 0 |
|||
pos -= 1 |
|||
|
|||
"H": |
|||
pos -= cols |
|||
if pos < 0 |
|||
pos += cols |
|||
|
|||
"D": |
|||
if inRegion |
|||
scrollUp |
|||
|
|||
"M": |
|||
if inRegion |
|||
scrollDown |
|||
|
|||
"G": |
|||
pos := 0 |
|||
|
|||
"(": |
|||
state := 5 |
|||
return |
|||
|
|||
state := 0 |
|||
return |
|||
|
|||
2: ' Parse first argument (arg0) of escape sequence |
|||
if (c => "0") AND (c =< "9") |
|||
if arg0 == -1 |
|||
arg0 := c - "0" |
|||
else |
|||
arg0 := (arg0 * 10) + (c - "0") |
|||
return |
|||
|
|||
if c == ";" |
|||
state := 3 |
|||
return |
|||
|
|||
ansi(c) |
|||
setCursorPos(pos) |
|||
return |
|||
|
|||
3: ' Parse second argument (arg1) of escape sequence |
|||
if (c => "0") AND (c =< "9") |
|||
if arg1 == -1 |
|||
arg1 := c - "0" |
|||
else |
|||
arg1 := (arg1 * 10) + (c - "0") |
|||
return |
|||
|
|||
if c == ";" |
|||
state := 4 |
|||
return |
|||
|
|||
ansi(c) |
|||
setCursorPos(pos) |
|||
return |
|||
|
|||
4: ' Parse remaining arguments (ignored) |
|||
if (c => "0") AND (c =< "9") |
|||
return |
|||
|
|||
if c == ";" |
|||
return |
|||
|
|||
ansi(c) |
|||
setCursorPos(pos) |
|||
return |
|||
|
|||
5: ' Set character set (not implemented) |
|||
state := 0 |
|||
return |
|||
|
|||
return |
|||
@ -1 +1,100 @@ |
|||
{{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// E555 Speaker Engine
//
// Author: Kwabena W. Agyeman
// Updated: 7/27/2010
// Designed For: P8X32A
// Version: 1.1
//
// Copyright (c) 2010 Kwabena W. Agyeman
// See end of file for terms of use.
//
// Update History:
//
// v1.0 - Original release - 8/26/2009.
// v1.1 - Added support for variable pin assignments - 7/27/2010.
//
// For each included copy of this object only one spin interpreter should access it at a time.
//
// Nyamekye,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Speaker Circuit:
//
// SpeakerPinNumber --- Speaker Driver (Active High).
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}}
PUB speakerFrequency(newFrequency, speakerPinNumber) '' 10 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Changes the speaker frequency using the SPIN interpreter's counter modules.
'' //
'' // NewFrequency - The new frequency. Between 0 Hz and 80MHz @ 80MHz. -1 to reset the pin and counter modules.
'' // SpeakerPinNumber - Pin to use to drive the speaker circuit. Between 0 and 31.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
speakerSetup((newFrequency <> -1), speakerPinNumber)
newFrequency := ((newFrequency <# clkfreq) #> 0)
result := 1
repeat 32
newFrequency <<= 1
result <-= 1
if(newFrequency => clkfreq)
newFrequency -= clkfreq
result += 1
frqa := result~
phsb := 0
PUB speakerVolume(newVolume, speakerPinNumber) '' 10 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Changes the speaker volume using the SPIN interpreter's counter modules.
'' //
'' // NewVolume - The new volume. Between 0% and 100%. -1 to reset the pin and counter modules.
'' // SpeakerPinNumber - Pin to use to drive the speaker circuit. Between 0 and 31.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
speakerSetup((newVolume <> -1), speakerPinNumber)
frqb := (((100 - ((newVolume <# 100) #> 0)) * constant(posx / 50)) | $7)
PRI speakerSetup(activeOrInactive, speakerPinNumber) ' 5 Stack Longs
speakerPinNumber := ((speakerPinNumber <# 31) #> 0)
dira[speakerPinNumber] := activeOrInactive
outa[speakerPinNumber] := false
ctra := ((constant(%0_0100 << 26) + speakerPinNumber) & activeOrInactive)
ctrb := ((constant(%0_0110 << 26) + speakerPinNumber) & activeOrInactive)
{{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}} |
|||
{{ |
|||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|||
// E555 Speaker Engine |
|||
// |
|||
// Author: Kwabena W. Agyeman |
|||
// Updated: 7/27/2010 |
|||
// Designed For: P8X32A |
|||
// Version: 1.1 |
|||
// |
|||
// Copyright (c) 2010 Kwabena W. Agyeman |
|||
// See end of file for terms of use. |
|||
// |
|||
// Update History: |
|||
// |
|||
// v1.0 - Original release - 8/26/2009. |
|||
// v1.1 - Added support for variable pin assignments - 7/27/2010. |
|||
// |
|||
// For each included copy of this object only one spin interpreter should access it at a time. |
|||
// |
|||
// Nyamekye, |
|||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|||
|
|||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|||
// Speaker Circuit: |
|||
// |
|||
// SpeakerPinNumber --- Speaker Driver (Active High). |
|||
// |
|||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|||
}} |
|||
|
|||
PUB speakerFrequency(newFrequency, speakerPinNumber) '' 10 Stack Longs |
|||
|
|||
'' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|||
'' // Changes the speaker frequency using the SPIN interpreter's counter modules. |
|||
'' // |
|||
'' // NewFrequency - The new frequency. Between 0 Hz and 80MHz @ 80MHz. -1 to reset the pin and counter modules. |
|||
'' // SpeakerPinNumber - Pin to use to drive the speaker circuit. Between 0 and 31. |
|||
'' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|||
|
|||
speakerSetup((newFrequency <> -1), speakerPinNumber) |
|||
|
|||
newFrequency := ((newFrequency <# clkfreq) #> 0) |
|||
|
|||
result := 1 |
|||
|
|||
repeat 32 |
|||
newFrequency <<= 1 |
|||
result <-= 1 |
|||
if(newFrequency => clkfreq) |
|||
newFrequency -= clkfreq |
|||
result += 1 |
|||
|
|||
frqa := result~ |
|||
|
|||
phsb := 0 |
|||
|
|||
PUB speakerVolume(newVolume, speakerPinNumber) '' 10 Stack Longs |
|||
|
|||
'' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|||
'' // Changes the speaker volume using the SPIN interpreter's counter modules. |
|||
'' // |
|||
'' // NewVolume - The new volume. Between 0% and 100%. -1 to reset the pin and counter modules. |
|||
'' // SpeakerPinNumber - Pin to use to drive the speaker circuit. Between 0 and 31. |
|||
'' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|||
|
|||
speakerSetup((newVolume <> -1), speakerPinNumber) |
|||
|
|||
frqb := (((100 - ((newVolume <# 100) #> 0)) * constant(posx / 50)) | $7) |
|||
|
|||
PRI speakerSetup(activeOrInactive, speakerPinNumber) ' 5 Stack Longs |
|||
|
|||
speakerPinNumber := ((speakerPinNumber <# 31) #> 0) |
|||
|
|||
dira[speakerPinNumber] := activeOrInactive |
|||
|
|||
outa[speakerPinNumber] := false |
|||
|
|||
ctra := ((constant(%0_0100 << 26) + speakerPinNumber) & activeOrInactive) |
|||
|
|||
ctrb := ((constant(%0_0110 << 26) + speakerPinNumber) & activeOrInactive) |
|||
|
|||
{{ |
|||
|
|||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|||
// 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. |
|||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|||
}} |
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
File diff suppressed because it is too large
Loading…
Reference in new issue