aboutsummaryrefslogtreecommitdiff
path: root/examples/system/timer
diff options
context:
space:
mode:
authorspicyjpeg <thatspicyjpeg@gmail.com>2023-07-03 08:13:23 +0200
committerspicyjpeg <thatspicyjpeg@gmail.com>2023-07-03 08:13:23 +0200
commit06e65bea3a778b2dae5af77a7935ae3868ddd4d3 (patch)
tree3af954ebead7540c9478d0a026ca2e59f3cf7b64 /examples/system/timer
parent472cf1c254ea5be5aff8a6c7067cbed2d467d85b (diff)
downloadpsn00bsdk-06e65bea3a778b2dae5af77a7935ae3868ddd4d3.tar.gz
Fix setjmp.h, FntSort(), examples, rewrite system/timer
Diffstat (limited to 'examples/system/timer')
-rw-r--r--examples/system/timer/main.c255
1 files changed, 124 insertions, 131 deletions
diff --git a/examples/system/timer/main.c b/examples/system/timer/main.c
index eb62712..c424e84 100644
--- a/examples/system/timer/main.c
+++ b/examples/system/timer/main.c
@@ -1,156 +1,149 @@
-#include <sys/types.h>
-#include <stdio.h>
+/*
+ * PSn00bSDK hardware timer example
+ * (C) 2023 spicyjpeg - MPL licensed
+ */
+
+#include <stdint.h>
#include <psxgpu.h>
-#include <psxapi.h>
#include <psxetc.h>
+#include <psxapi.h>
#include <hwregs_c.h>
-/* OT and Packet Buffer sizes */
-#define OT_LEN 256
-#define PACKET_LEN 1024
+/* Display/GPU context utilities */
-/* Screen resolution */
-#define SCREEN_XRES 320
-#define SCREEN_YRES 240
+#define SCREEN_XRES 320
+#define SCREEN_YRES 240
-/* Screen center position */
-#define CENTERX SCREEN_XRES>>1
-#define CENTERY SCREEN_YRES>>1
+#define BGCOLOR_R 48
+#define BGCOLOR_G 24
+#define BGCOLOR_B 0
+typedef struct {
+ DISPENV disp;
+ DRAWENV draw;
+} Framebuffer;
-/* Double buffer structure */
typedef struct {
- DISPENV disp; /* Display environment */
- DRAWENV draw; /* Drawing environment */
-} DB;
+ Framebuffer db[2];
+ int db_active;
+} RenderContext;
+
+void init_context(RenderContext *ctx) {
+ Framebuffer *db;
+
+ ResetGraph(0);
+ ctx->db_active = 0;
+
+ db = &(ctx->db[0]);
+ SetDefDispEnv(&(db->disp), 0, 0, SCREEN_XRES, SCREEN_YRES);
+ SetDefDrawEnv(&(db->draw), SCREEN_XRES, 0, SCREEN_XRES, SCREEN_YRES);
+ setRGB0(&(db->draw), BGCOLOR_R, BGCOLOR_G, BGCOLOR_B);
+ db->draw.isbg = 1;
+ db->draw.dtd = 1;
+
+ db = &(ctx->db[1]);
+ SetDefDispEnv(&(db->disp), SCREEN_XRES, 0, SCREEN_XRES, SCREEN_YRES);
+ SetDefDrawEnv(&(db->draw), 0, 0, SCREEN_XRES, SCREEN_YRES);
+ setRGB0(&(db->draw), BGCOLOR_R, BGCOLOR_G, BGCOLOR_B);
+ db->draw.isbg = 1;
+ db->draw.dtd = 1;
+
+ PutDrawEnv(&(db->draw));
+ //PutDispEnv(&(db->disp));
+
+ // Create a text stream at the top of the screen.
+ FntLoad(960, 0);
+ FntOpen(8, 16, 304, 208, 2, 512);
+}
+
+void display(RenderContext *ctx) {
+ Framebuffer *db;
+
+ DrawSync(0);
+ VSync(0);
+ ctx->db_active ^= 1;
-/* Double buffer variables */
-DB db[2];
-int db_active = 0;
+ db = &(ctx->db[ctx->db_active]);
+ PutDrawEnv(&(db->draw));
+ PutDispEnv(&(db->disp));
+ SetDispMask(1);
+}
+
+/* Interrupt handlers */
+typedef struct {
+ int irq_count, last_irq_count, irqs_per_sec;
+} TimerState;
-/* Function declarations */
-void init();
-void display();
+static volatile TimerState timer_state[3];
+static void timer0_handler(void) {
+ timer_state[0].irq_count++;
+}
-volatile int timer_calls = 0;
+static void timer1_handler(void) {
+ timer_state[1].irq_count++;
+}
-void timer_func()
-{
- timer_calls++;
+static void timer2_handler(void) {
+ timer_state[2].irq_count++;
}
-volatile int vsync_count = 0;
-volatile int tick_count = 0;
-volatile int tick_value = 0;
-
-void vsync_func()
-{
- vsync_count++;
- if( vsync_count > 60 )
- {
- tick_value = timer_calls-tick_count;
- tick_count = timer_calls;
- vsync_count = 0;
+static void vblank_handler(void) {
+ int refresh_rate = (GetVideoMode() == MODE_PAL) ? 50 : 60;
+
+ // Only update once per second (every 50 or 60 vblanks).
+ if (VSync(-1) % refresh_rate)
+ return;
+
+ for (int i = 0; i < 3; i++) {
+ TimerState *state = &timer_state[i];
+
+ int count = state->irq_count;
+ state->irqs_per_sec = count - state->last_irq_count;
+ state->last_irq_count = count;
}
}
-/* Main function */
-int main() {
-
- int counter;
-
- /* Init graphics and GTE */
- init();
-
-
+/* Main */
+
+static RenderContext ctx;
+
+int main(int argc, const char* argv[]) {
+ init_context(&ctx);
+
+ // Set up the timers and register callbacks for their interrupts.
+ TIMER_CTRL(0) = 0x0160; // Dotclock input, repeated IRQ on overflow
+ TIMER_CTRL(1) = 0x0160; // Hblank input, repeated IRQ on overflow
+ TIMER_CTRL(2) = 0x0260; // CLK/8 input, repeated IRQ on overflow
+
+ __builtin_memset(timer_state, 0, sizeof(timer_state));
+
EnterCriticalSection();
- //SetRCnt(RCntCNT2, 0xF040, RCntMdINTR);
-
- // NTSC clock base
- counter = 4304000/560;
-
- // PAL clock base
- //counter = 5163000/560;
-
- SetRCnt(RCntCNT2, counter, RCntMdINTR);
- TIMER_CTRL(2) = 0x1E58;
- InterruptCallback(6, timer_func);
- StartRCnt(RCntCNT2);
- ChangeClearRCnt(2, 0);
+ InterruptCallback(IRQ_TIMER0, &timer0_handler);
+ InterruptCallback(IRQ_TIMER1, &timer1_handler);
+ InterruptCallback(IRQ_TIMER2, &timer2_handler);
+ VSyncCallback(&vblank_handler);
ExitCriticalSection();
-
- VSyncCallback(vsync_func);
-
- /* Main loop */
- while( 1 ) {
-
- FntPrint(-1, "TIMER COUNT=%d\n", timer_calls);
- FntPrint(-1, "TICKS/SEC=%d\n", tick_value);
-
- /* Swap buffers and draw text */
- display();
-
+
+ while (1) {
+ FntPrint(-1, "HARDWARE TIMER EXAMPLE\n\n");
+
+ for (int i = 0; i < 3; i++) {
+ TimerState *state = &timer_state[i];
+
+ FntPrint(-1, "TIMER %d:\n", i);
+ FntPrint(-1, " VALUE: %d\n", TIMER_VALUE(i));
+ FntPrint(-1, " IRQS: %d\n", state->irq_count);
+ FntPrint(-1, " IRQS/S: %d\n\n", state->irqs_per_sec);
+ }
+
+ FntPrint(-1, "VBLANK COUNTER:\n");
+ FntPrint(-1, " VALUE: %d\n\n", VSync(-1));
+
+ FntFlush(-1);
+ display(&ctx);
}
-
- return 0;
-
-}
-void init() {
-
- /* Reset the GPU, also installs a VSync event handler */
- ResetGraph( 0 );
- //SetVideoMode(MODE_PAL);
-
- /* Set display and draw environment areas */
- /* (display and draw areas must be separate, otherwise hello flicker) */
- SetDefDispEnv( &db[0].disp, 0, 0, SCREEN_XRES, SCREEN_YRES );
- SetDefDrawEnv( &db[0].draw, SCREEN_XRES, 0, SCREEN_XRES, SCREEN_YRES );
-
- /* Enable draw area clear and dither processing */
- setRGB0( &db[0].draw, 63, 0, 127 );
- db[0].draw.isbg = 1;
- db[0].draw.dtd = 1;
-
-
- /* Define the second set of display/draw environments */
- SetDefDispEnv( &db[1].disp, SCREEN_XRES, 0, SCREEN_XRES, SCREEN_YRES );
- SetDefDrawEnv( &db[1].draw, 0, 0, SCREEN_XRES, SCREEN_YRES );
-
- //db[0].disp.screen.y = 24;
- //db[1].disp.screen.y = 24;
-
- setRGB0( &db[1].draw, 63, 0, 127 );
- db[1].draw.isbg = 1;
- db[1].draw.dtd = 1;
-
-
- /* Apply the drawing environment of the first double buffer */
- PutDrawEnv( &db[0].draw );
-
- FntLoad(960, 0);
- FntOpen(0, 8, 320, 216, 0, 100);
-
+ return 0;
}
-
-void display() {
-
- FntFlush(-1);
-
- /* Wait for GPU to finish drawing and vertical retrace */
- DrawSync( 0 );
- VSync( 0 );
-
- /* Swap buffers */
- db_active ^= 1;
-
- /* Apply display/drawing environments */
- PutDrawEnv( &db[db_active].draw );
- PutDispEnv( &db[db_active].disp );
-
- /* Enable display */
- SetDispMask( 1 );
-
-} \ No newline at end of file