Browse Source

Finalize v2.9.1 Prerelease 0

Added character attributes on propeller-based consoles.
pull/9/head
Wayne Warthen 8 years ago
parent
commit
091d171f02
  1. 1
      Doc/ChangeLog.txt
  2. 2
      ReadMe.txt
  3. 2
      Source/CBIOS/ver.inc
  4. 2
      Source/HBIOS/ver.inc
  5. BIN
      Source/Hardware/Experimental/PropIO2_test/PropIO2.eeprom
  6. 2
      Source/Hardware/Experimental/PropIO2_test/Spin/Build.cmd
  7. 1
      Source/Hardware/Experimental/PropIO2_test/Spin/E555_SPKEngine.spin
  8. BIN
      Source/Hardware/Experimental/PropIO2_test/Spin/Keyboard.spin
  9. BIN
      Source/Hardware/Experimental/PropIO2_test/Spin/Parallax Serial Terminal.spin
  10. 6939
      Source/Hardware/Experimental/PropIO2_test/Spin/PropIO2.list
  11. BIN
      Source/Hardware/Experimental/PropIO2_test/Spin/PropIO2.spin
  12. 920
      Source/Hardware/Experimental/PropIO2_test/Spin/safe_spi.spin
  13. 1198
      Source/Hardware/Experimental/PropIO2_test/Spin/vt100.spin
  14. 1
      Source/Hardware/Experimental/vga2/Build.cmd
  15. 17
      Source/Hardware/Experimental/vga2/Makefile
  16. BIN
      Source/Hardware/Experimental/vga2/bstc.exe
  17. 619
      Source/Hardware/Experimental/vga2/vga8x8d.spin
  18. 602
      Source/Hardware/Experimental/vga2/vgacolour.spin
  19. BIN
      Source/Hardware/Experimental/vga2/vgademo.eeprom
  20. 3019
      Source/Hardware/Experimental/vga2/vgademo.list
  21. 102
      Source/Hardware/Experimental/vga2/vgademo.spin
  22. 1198
      Source/Hardware/Experimental/vga2/vt100.spin
  23. 535
      Source/Hardware/Prop/Spin/AnsiTerm.spin
  24. 101
      Source/Hardware/Prop/Spin/E555_SPKEngine.spin
  25. BIN
      Source/Hardware/Prop/Spin/FullDuplexSerial.spin
  26. BIN
      Source/Hardware/Prop/Spin/FullDuplexSerialNull.spin
  27. BIN
      Source/Hardware/Prop/Spin/Keyboard.spin
  28. BIN
      Source/Hardware/Prop/Spin/ParPortProp.spin
  29. BIN
      Source/Hardware/Prop/Spin/Parallax Serial Terminal Null.spin
  30. BIN
      Source/Hardware/Prop/Spin/Parallax Serial Terminal.spin
  31. BIN
      Source/Hardware/Prop/Spin/PropIO.spin
  32. BIN
      Source/Hardware/Prop/Spin/PropIO2.spin
  33. 2
      Source/Hardware/Prop/Spin/VGA_1024.spin
  34. BIN
      Source/Hardware/Prop/Spin/VGA_HiRes_Text.spin
  35. 0
      Source/Hardware/Prop/Spin/vga8x8d.spin
  36. 0
      Source/Hardware/Prop/Spin/vgacolour.spin

1
Doc/ChangeLog.txt

@ -3,6 +3,7 @@ Version 2.9.1
- E?B: Added support for RC2014 RTC
- WBW: Converted PTXPLAY to TUNE (now plays PT2/PT3/MYM sounds files)
- WBW: Updated Win32DiskImager to v1.0
- WBW: Implemented character attributes on Propeller based consoles
Version 2.9.0
-------------

2
ReadMe.txt

@ -7,7 +7,7 @@
***********************************************************************
Wayne Warthen (wwarthen@gmail.com)
Version 2.9.1 (developmental), 2018-01-26
Version 2.9.1-pre.0, 2018-03-11
https://www.retrobrewcomputers.org/
RomWBW is a ROM-based implementation of CP/M-80 2.2 and Z-System for

2
Source/CBIOS/ver.inc

@ -2,4 +2,4 @@
#DEFINE RMN 9
#DEFINE RUP 1
#DEFINE RTP 0
#DEFINE BIOSVER "2.9.1-dev.0"
#DEFINE BIOSVER "2.9.1-pre.0"

2
Source/HBIOS/ver.inc

@ -2,4 +2,4 @@
#DEFINE RMN 9
#DEFINE RUP 1
#DEFINE RTP 0
#DEFINE BIOSVER "2.9.1-dev.0"
#DEFINE BIOSVER "2.9.1-pre.0"

BIN
Source/Hardware/Experimental/PropIO2_test/PropIO2.eeprom

Binary file not shown.

2
Source/Hardware/Experimental/PropIO2_test/Spin/Build.cmd

@ -1,2 +0,0 @@
rem ..\..\..\Tools\bst\bstc -Ox -ls -e -p0 -dCOM5: PropIO2.spin
..\..\..\Tools\bst\bstc -Ox -ls -e PropIO2.spin

1
Source/Hardware/Experimental/PropIO2_test/Spin/E555_SPKEngine.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. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }}

BIN
Source/Hardware/Experimental/PropIO2_test/Spin/Keyboard.spin

Binary file not shown.

BIN
Source/Hardware/Experimental/PropIO2_test/Spin/Parallax Serial Terminal.spin

Binary file not shown.

6939
Source/Hardware/Experimental/PropIO2_test/Spin/PropIO2.list

File diff suppressed because it is too large

BIN
Source/Hardware/Experimental/PropIO2_test/Spin/PropIO2.spin

Binary file not shown.

920
Source/Hardware/Experimental/PropIO2_test/Spin/safe_spi.spin

@ -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.
}}

1198
Source/Hardware/Experimental/PropIO2_test/Spin/vt100.spin

File diff suppressed because it is too large

1
Source/Hardware/Experimental/vga2/Build.cmd

@ -1 +0,0 @@
bstc -Ox -ls -e -p0 -dCOM5: vgademo.spin

17
Source/Hardware/Experimental/vga2/Makefile

@ -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

BIN
Source/Hardware/Experimental/vga2/bstc.exe

Binary file not shown.

619
Source/Hardware/Experimental/vga2/vga8x8d.spin

@ -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. |
+------------------------------------------------------------------------------------------------------------------------------+
}}

602
Source/Hardware/Experimental/vga2/vgacolour.spin

@ -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. |
+------------------------------------------------------------------------------------------------------------------------------+
}}

BIN
Source/Hardware/Experimental/vga2/vgademo.eeprom

Binary file not shown.

3019
Source/Hardware/Experimental/vga2/vgademo.list

File diff suppressed because it is too large

102
Source/Hardware/Experimental/vga2/vgademo.spin

@ -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

1198
Source/Hardware/Experimental/vga2/vt100.spin

File diff suppressed because it is too large

535
Source/Hardware/Prop/Spin/AnsiTerm.spin

@ -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

101
Source/Hardware/Prop/Spin/E555_SPKEngine.spin

@ -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.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}}

BIN
Source/Hardware/Prop/Spin/FullDuplexSerial.spin

Binary file not shown.

BIN
Source/Hardware/Prop/Spin/FullDuplexSerialNull.spin

Binary file not shown.

BIN
Source/Hardware/Prop/Spin/Keyboard.spin

Binary file not shown.

BIN
Source/Hardware/Prop/Spin/ParPortProp.spin

Binary file not shown.

BIN
Source/Hardware/Prop/Spin/Parallax Serial Terminal Null.spin

Binary file not shown.

BIN
Source/Hardware/Prop/Spin/Parallax Serial Terminal.spin

Binary file not shown.

BIN
Source/Hardware/Prop/Spin/PropIO.spin

Binary file not shown.

BIN
Source/Hardware/Prop/Spin/PropIO2.spin

Binary file not shown.

2
Source/Hardware/Prop/Spin/VGA_1024.spin

@ -73,7 +73,7 @@ PUB vidon
if (!vga.start(vgabasepin, @screen, @colors, @cursor, @sync))
return false
waitcnt(clkfreq * 1 + cnt) 'wait 1 second for cogs to start
'waitcnt(clkfreq * 1 + cnt) 'wait 1 second for cogs to start
PUB vidoff

BIN
Source/Hardware/Prop/Spin/VGA_HiRes_Text.spin

Binary file not shown.

0
Source/Hardware/Experimental/PropIO2_test/Spin/vga8x8d.spin → Source/Hardware/Prop/Spin/vga8x8d.spin

0
Source/Hardware/Experimental/PropIO2_test/Spin/vgacolour.spin → Source/Hardware/Prop/Spin/vgacolour.spin

Loading…
Cancel
Save