Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added waitVSYNCStart and getVSYNCActive functions #131

Merged
merged 4 commits into from
Aug 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions cpctelera/src/video/cpct_getVSYNCActive.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
;;-----------------------------LICENSE NOTICE------------------------------------
;; This file is part of CPCtelera: An Amstrad CPC Game Engine
;; Copyright (C) 2014-2021 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR)
;;
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU Lesser General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU Lesser General Public License for more details.
;;
;; You should have received a copy of the GNU Lesser General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;-------------------------------------------------------------------------------
.module cpct_video

.include /videomode.s/

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Function: cpct_getVSYNCActive
;;
;; Checks if the vertical synchronization signal (VSYNC) is active or not and returns.
;;
;; C Definition:
;; <u8> <cpct_getVSYNCActive> ()
;;
;; Assembly call:
;; > call cpct_getVSYNCActive_asm
;;
;; Return Value:
;; (1B L) - 0 if VSYNC not active, 1 if VSYNC is active.
;;
;; Details:
;; This function gets the VSYNC signal from the CRTC. It will return 0 if VSYNC is not active,
;; and 1 if it is active.
;;
;; This function can be used within an interrupt handler as a method to know which interrupt has
;; occurred and can be used for synchronising interrupts.
;;
;; To detect VSYNC signal status, function reads a byte from PPI Port B. That byte contains
;; this information:
;; (start code)
;; BIT NAME DESCRIPTION
;; ----------------------------------------------------------------
;; 7 CAS.IN Cassette data input
;; 6 RN.BUSY Parallel/Printer port signal, "0"=ready,"1"= Not Ready
;; 5 /EXP Expansion Port /EXP pin
;; 4 LK4 Screen Refresh Rate ("1"=50Hz, "0"=60Hz)
;; 3 LK3 3bit Distributor ID. Usually set to 4=Awa,
;; 2 LK2 5=Schneider, or 7=Amstrad, see LK-selectable
;; 1 LK1 Brand Names for details.
;; 0 CRTC Vertical Sync ("1"=VSYNC active, "0"=inactive)
;; (end)
;; So, checking the bit 0 of a byte coming from PPI Port B tells us if
;; VSYNC is active or not.
;;
;; Destroyed Register values:
;; AF, BC
;;
;; Required memory:
;; 8 bytes
;;
;; Time Measures:
;; (start code)
;; Case | microSecs (us) | CPU Cycles
;; ----------------------------------------
;; Any | 12 | 48
;; (end code)
;;
;; Credits:
;; This function was coded based on code by Kevin Thacker.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_cpct_getVSYNCActive:: ;; C entry point
cpct_getVSYNCActive_asm:: ;; Assembly entry point
ld b, #PPI_PORT_B ;; [2] B = F5h ==> B has the address of PPI Port B, where we get information from VSYNC
in a,(c) ;; [4] A = Status register got from PPI port B
and #1 ;; [2] Leave only bit 0 (VSYNC status)
ld l,a ;; [1] L=0 if VSYNC is not active, L=1 if VSYNC is active

ret ;; [3] Return to caller

4 changes: 2 additions & 2 deletions cpctelera/src/video/cpct_waitVSYNC.s
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
;; 50Hz drawing display.
;;
;; To detect VSYNC signal status, function reads bytes from PPI Port B.
;; Every byte read the port has this information:
;; Every byte read from the port has this information:
;; (start code)
;; BIT NAME DESCRIPTION
;; ----------------------------------------------------------------
Expand All @@ -51,7 +51,7 @@
;; 1 LK1 Brand Names for details.
;; 0 CRTC Vertical Sync ("1"=VSYNC active, "0"=inactive)
;; (end)
;; So, checking the bit 0 of a byte comming from PPI Port B tells us if
;; So, checking the bit 0 of a byte coming from PPI Port B tells us if
;; VSYNC is active or not.
;; This function is optimized for size (instead of speed) as it is a wait loop
;; and does not make sense making it faster. It will stop when VSYNC is detected
Expand Down
101 changes: 101 additions & 0 deletions cpctelera/src/video/cpct_waitVSYNCStart.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
;;-----------------------------LICENSE NOTICE------------------------------------
;; This file is part of CPCtelera: An Amstrad CPC Game Engine
;; Copyright (C) 2014-2021 ronaldo / Fremos / Cheesetea / ByteRealms (@FranGallegoBR)
;;
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU Lesser General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU Lesser General Public License for more details.
;;
;; You should have received a copy of the GNU Lesser General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;-------------------------------------------------------------------------------
.module cpct_video

.include /videomode.s/

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Function: cpct_waitVSYNCStart
;;
;; Waits until the start of the vertical synchronization signal (VSYNC) and returns.
;;
;; C Definition:
;; void <cpct_waitVSYNCStart> ()
;;
;; Assembly call:
;; > call cpct_waitVSYNCStart_asm
;;
;; Details:
;; This function implements a wait loop that will return only when the start
;; of the VSYNC signal from the CRTC is detected. This signal means that the monitor
;; has finished drawing the last frame and it is returning to the top left of the screen
;; to start drawing the next one. This is useful to synchronize routines with the
;; 50Hz drawing display.
;;
;; To detect VSYNC signal status, function reads bytes from PPI Port B.
;; Every byte read from the port has this information:
;; (start code)
;; BIT NAME DESCRIPTION
;; ----------------------------------------------------------------
;; 7 CAS.IN Cassette data input
;; 6 RN.BUSY Parallel/Printer port signal, "0"=ready,"1"= Not Ready
;; 5 /EXP Expansion Port /EXP pin
;; 4 LK4 Screen Refresh Rate ("1"=50Hz, "0"=60Hz)
;; 3 LK3 3bit Distributor ID. Usually set to 4=Awa,
;; 2 LK2 5=Schneider, or 7=Amstrad, see LK-selectable
;; 1 LK1 Brand Names for details.
;; 0 CRTC Vertical Sync ("1"=VSYNC active, "0"=inactive)
;; (end)
;; So, checking the bit 0 of a byte coming from PPI Port B tells us if VSYNC
;; is active or not. That signal is active during a small period of time, but
;; for synchronization purposes it is normally very important to detect exactly
;; when VSYNC signal starts. In order to achieve this, this function first waits
;; for VSYNC being inactive, and then waits for VSYNC being active. That ensures
;; that the function will return at the start of the VSYNC signal.
;;
;; This function is optimized for size (instead of speed) as it is an active
;; wait, and does not make sense making it faster. It will stop when VSYNC start is
;; detected no matter how fast the code is.
;;
;; Destroyed Register values:
;; AF, BC
;;
;; Required memory:
;; 13 bytes
;;
;; Time Measures:
;; (start code)
;; Case | microSecs (us) | CPU Cycles
;; -------------------------------------
;; Best | 19 | 76
;; -------------------------------------
;; Worst | 19984 | 79936
;; -------------------------------------
;; (end code)
;;
;; NOTE:
;; As this function is an active wait, it does not actually mind
;; at all the time needed to process. It will vary depending on
;; how much time has passed since the last VSYNC start.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_cpct_waitVSYNCStart:: ;; C entry point
cpct_waitVSYNCStart_asm:: ;; Assembly entry point
ld b, #PPI_PORT_B ;; [2] B = F5h ==> B has the address of PPI Port B, where we get information from VSYNC

wait_for_vs_inactive:
in a,(c) ;; [4] A = Status register got from PPI port B
rra ;; [1] Move bit 0 of A to Carry (bit 0 contains VSYNC status)
jr c, wait_for_vs_inactive ;; [2/3] Carry means VSYNC is active, so loop While Carry

wait_for_vs_active:
in a,(c) ;; [4] A = Status register got from PPI port B
rra ;; [1] Move bit 0 of A to Carry (bit 0 contains VSYNC status)
jr nc, wait_for_vs_active ;; [2/3] No Carry means No VSYNC, so loop While No Carry

ret ;; [3] Start of VSYNC, Return
8 changes: 5 additions & 3 deletions cpctelera/src/video/videomode.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@
// Setting Video Mode
extern void cpct_setVideoMode (u8 videoMode) __z88dk_fastcall;

// Waiting for VSYNC
extern void cpct_waitVSYNC ();
extern u16 cpct_count2VSYNC ();
// VSYNC functions
extern void cpct_waitVSYNC ();
extern void cpct_waitVSYNCStart ();
extern u8 cpct_getVSYNCActive ();
extern u16 cpct_count2VSYNC ();

// Palette functions
extern void cpct_fw2hw (void *fw_colour_array, u16 size) __z88dk_callee;
Expand Down