-
-
Save tkurbad/1bdedc8757e1fb1730230057b1ea061a to your computer and use it in GitHub Desktop.
FF_OSD videoswitch patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/attic/pins.md b/attic/pins.md | |
index f821324..50acfc5 100644 | |
--- a/attic/pins.md | |
+++ b/attic/pins.md | |
@@ -10,9 +10,9 @@ | |
| 7 | | Disp.Out.SPI1 | Y | I2C SDA | | |
| 8 | Y | CSYNC/HSYNC | Y | User Out (U0) | | |
| 9 | Y | Serial Tx | Y | User Out (U1) | | |
-|10 | Y | Serial Rx | Y | User Out (U2) | | |
-|11 | Y | | Y | Atari KB | | |
-|12 | Y | | Y | | | |
+|10 | Y | Serial Rx | Y | I2C2 SCL | | |
+|11 | Y | Atari KB | Y | I2C2 SDA | | |
+|12 | Y | Amiga CTS | Y | User Out (U2) | | |
|13 | Y | **NA** (SWDIO)| Y | SPI2.SCK | | |
|14 | Y | **NA** (SWCLK)| Y | VSYNC | | |
|15 | Y | Disp.Enable | Y | Disp.Out. (RGB) | | |
diff --git a/inc/config.h b/inc/config.h | |
index 2b3d275..7dfcb72 100644 | |
--- a/inc/config.h | |
+++ b/inc/config.h | |
@@ -49,6 +49,10 @@ extern struct packed config { | |
uint16_t display_2Y; | |
+#define OM_MASTER 0 | |
+#define OM_SLAVE 1 | |
+ uint16_t op_mode; | |
+ | |
/* Mask of user-assigned pins configured in open-drain mode. */ | |
uint8_t user_pin_opendrain; | |
/* Mask of user-assigned pins configured in push-pull mode. */ | |
@@ -65,9 +69,19 @@ extern struct packed config { | |
uint16_t flags; | |
/* HKF_momentary: Pins are driven the opposite way on key release. */ | |
#define HKF_momentary 1 | |
+/* HKF_videoswitch: This hotkey controls the video input switch. */ | |
+/* NB: config.videoswitch = TRUE must be set for this to have any effect. */ | |
+#define HKF_videoswitch 2 | |
char str[30]; | |
} hotkey[10]; | |
+ /* Enable video output switching using A12 as input and one of the user- | |
+ * assigned pins as output. | |
+ * To make use of this feature, the corresponding hotkey has to be flagged | |
+ * HKF_videoswitch. | |
+ */ | |
+ uint16_t videoswitch; | |
+ | |
uint16_t crc16_ccitt; | |
} config; | |
diff --git a/inc/decls.h b/inc/decls.h | |
index 1de7cc6..3050515 100644 | |
--- a/inc/decls.h | |
+++ b/inc/decls.h | |
@@ -24,6 +24,7 @@ | |
#include "cancellation.h" | |
#include "time.h" | |
#include "timer.h" | |
+#include "userpin.h" | |
/* | |
* Local variables: | |
diff --git a/inc/userpin.h b/inc/userpin.h | |
new file mode 100644 | |
index 0000000..b9f3026 | |
--- /dev/null | |
+++ b/inc/userpin.h | |
@@ -0,0 +1,36 @@ | |
+/* | |
+ * userpin.h | |
+ * | |
+ * User pin definitions for FlashFloppy OSD. | |
+ * | |
+ * This is free and unencumbered software released into the public domain. | |
+ * See the file COPYING for more details, or visit <http://unlicense.org>. | |
+ */ | |
+ | |
+/* Amiga CTS Input (A12): For use with automatic video output switch. */ | |
+#define gpio_amicts gpioa | |
+#define pin_amicts 12 | |
+ | |
+/* User outputs are PB8, PB9, PB12. */ | |
+#define gpio_user gpiob | |
+#define pin_u0 8 | |
+#define pin_u2 12 | |
+ | |
+/* Video input switch. */ | |
+enum vs_state { VS_AUTO=0, VS_AMIGA, VS_RTG }; | |
+extern uint8_t videoswitch_state; | |
+ | |
+/* User pin function prototypes. */ | |
+void user_pin_init(void); | |
+void videoswitch_next(uint8_t pin_num); | |
+void videoswitch_update(void); | |
+ | |
+/* | |
+ * Local variables: | |
+ * mode: C | |
+ * c-file-style: "Linux" | |
+ * c-basic-offset: 4 | |
+ * tab-width: 4 | |
+ * indent-tabs-mode: nil | |
+ * End: | |
+ */ | |
diff --git a/src/Makefile b/src/Makefile | |
index 1f0f5c5..20bfd66 100644 | |
--- a/src/Makefile | |
+++ b/src/Makefile | |
@@ -9,6 +9,7 @@ OBJS += string.o | |
OBJS += stm32f10x.o | |
OBJS += time.o | |
OBJS += timer.o | |
+OBJS += userpin.o | |
OBJS += util.o | |
OBJS += vectors.o | |
diff --git a/src/config.c b/src/config.c | |
index 89dde01..3164cf3 100644 | |
--- a/src/config.c | |
+++ b/src/config.c | |
@@ -38,6 +38,8 @@ static void config_printk(const struct config *conf) | |
printk(" Display Output: %s\n", | |
config.display_spi ? "PA7/SPI1" : "PB15/SPI2"); | |
printk(" Display Enable: %s\n", dispen_pretty[config.dispctl_mode] ); | |
+ printk(" Operating Mode: %s\n", | |
+ config.op_mode ? "Slave" : "Master"); | |
printk(" H.Off: %u\n", conf->h_off); | |
printk(" V.Off: %u\n", conf->v_off); | |
printk(" Rows: %u\n", conf->rows); | |
@@ -107,6 +109,7 @@ static enum { | |
C_disp2Y, | |
C_spibus, | |
C_dispen, | |
+ C_opmode, | |
C_h_off, | |
C_v_off, | |
/* LCD */ | |
@@ -316,6 +319,15 @@ void config_process(uint8_t b, bool_t autosync_changed) | |
if (b) | |
cnf_prt(1, "%s", dispen_pretty[config.dispctl_mode] ); | |
break; | |
+ case C_opmode: | |
+ if (changed) | |
+ cnf_prt(0, "Operating Mode:"); | |
+ if (b & (B_LEFT|B_RIGHT)) { | |
+ config.op_mode ^= 1; | |
+ } | |
+ if (b) | |
+ cnf_prt(1, "%s", config.op_mode ? "Slave" : "Master"); | |
+ break; | |
case C_h_off: | |
if (changed) | |
cnf_prt(0, "H.Off (1-199):"); | |
diff --git a/src/default_config.c b/src/default_config.c | |
index 8366237..c2fa7d0 100644 | |
--- a/src/default_config.c | |
+++ b/src/default_config.c | |
@@ -76,6 +76,42 @@ const static struct config dfl_config = { | |
} | |
#endif | |
+#if 1 | |
+ /* An example configuration for switching ROMs and video input. | |
+ * F1-F4: Switch between ROMs #1-#4 via binary value at pins U1,U0. | |
+ * F10: Toggle U2 between (mirror A12 - high - low) | |
+ */ | |
+ | |
+ .videoswitch = TRUE, | |
+ | |
+ /* U0 and U1 are configured open drain and need external pullups. | |
+ * U2 is handled by the videoswitch configuration flag. */ | |
+ .user_pin_opendrain = U(1) | U(0), | |
+ .user_pin_pushpull = 0, | |
+ | |
+ /* ROM #1 */ | |
+ .user_pin_high = 0, | |
+ | |
+ .hotkey = { | |
+ /* F1-F4: ROM switching. */ | |
+ [F(1)] = { .str = "ROM #1", | |
+ .pin_mod = U(1) | U(0), }, | |
+ [F(2)] = { .str = "ROM #2", | |
+ .pin_mod = U(1) | U(0), | |
+ .pin_high = U(0), }, | |
+ [F(3)] = { .str = "ROM #3", | |
+ .pin_mod = U(1) | U(0), | |
+ .pin_high = U(1) , }, | |
+ [F(4)] = { .str = "ROM #4", | |
+ .pin_mod = U(1) | U(0), | |
+ .pin_high = U(1) | U(0), }, | |
+ /* F10: Switch video source */ | |
+ [F(10)] = { .str = "Video input source", | |
+ .pin_mod = U(2), | |
+ .flags = HKF_videoswitch, }, | |
+ } | |
+#endif | |
+ | |
#undef F | |
#undef U | |
diff --git a/src/main.c b/src/main.c | |
index 11327a6..3c3fe4b 100644 | |
--- a/src/main.c | |
+++ b/src/main.c | |
@@ -33,6 +33,10 @@ | |
* B6: CLK | |
* B7: DAT | |
* | |
+ * I2C2 Interface (to slave OSD): | |
+ * B10: CLK2 | |
+ * B11: DAT2 | |
+ * | |
* Display: | |
* A7: Display output SPI1 | |
* A8: CSYNC or HSYNC | |
@@ -44,10 +48,13 @@ | |
* B3: KBDAT | |
* B4: KBCLK | |
* | |
+ * Amiga signals: | |
+ * A12: CTS | |
+ * | |
* User outputs: | |
* B8: U0 | |
* B9: U1 | |
- * B10: U2 | |
+ * B12: U2 | |
*/ | |
/* CSYNC/HSYNC (A8): EXTI IRQ trigger and TIM1 Ch.1 trigger. */ | |
@@ -110,9 +117,6 @@ void IRQ_28(void) __attribute__((alias("IRQ_osd_pre_start"))); | |
#define gpio_dispen gpioa | |
#define pin_dispen 15 | |
-/* User outputs are PB8 upwards. */ | |
-#define gpio_user gpiob | |
-#define pin_u0 8 | |
/* List of interrupts used by the display-sync and -output system. */ | |
const static uint8_t irqs[] = { | |
@@ -612,6 +616,10 @@ static uint8_t keys; | |
static bool_t osd_on = TRUE; | |
+/* Pretty print video input switch states. */ | |
+const static char *vs_state_pretty[] = { | |
+ "Auto", "Amiga", "RTG" }; | |
+ | |
static void update_amiga_keys(void) | |
{ | |
int i; | |
@@ -662,6 +670,17 @@ static void update_amiga_keys(void) | |
} | |
continue; | |
} | |
+ /* Video input switch hotkey? */ | |
+ if ((config.videoswitch) && (hk->flags & HKF_videoswitch)) { | |
+ videoswitch_next(hk->pin_mod); | |
+ snprintf((char *)notify.text[0], sizeof(notify.text[0]), | |
+ "%s %s", hk->str, vs_state_pretty[videoswitch_state]); | |
+ notify.cols = strlen((char *)notify.text[0]); | |
+ notify.rows = 1; | |
+ notify.on = TRUE; | |
+ notify_time = time_now(); | |
+ continue; | |
+ } | |
/* Hotkey is now pressed: Perform configured action. */ | |
gpio_user->bsrr = ((uint32_t)r << 16) | s; | |
if (*(p = hk->str)) { | |
@@ -897,15 +916,7 @@ int main(void) | |
running_polarity = SYNC_HIGH; | |
/* Set user pin output modes and initial logic levels. */ | |
- for (i = 0; i < 3; i++) { | |
- bool_t level = (config.user_pin_high >> i) & 1; | |
- if (config.user_pin_opendrain & (1u<<i)) | |
- gpio_configure_pin(gpio_user, pin_u0+i, | |
- GPO_opendrain(_2MHz, level)); | |
- if (config.user_pin_pushpull & (1u<<i)) | |
- gpio_configure_pin(gpio_user, pin_u0+i, | |
- GPO_pushpull(_2MHz, level)); | |
- } | |
+ user_pin_init(); | |
/* Display DMA setup: From memory into the Display Timer's CCRx. */ | |
if (startup_display_spi == DISP_SPI1) | |
@@ -1158,6 +1169,9 @@ int main(void) | |
} | |
i2c_process(); | |
+ | |
+ if (config.videoswitch) | |
+ videoswitch_update(); | |
} | |
return 0; | |
diff --git a/src/userpin.c b/src/userpin.c | |
new file mode 100644 | |
index 0000000..f3933fa | |
--- /dev/null | |
+++ b/src/userpin.c | |
@@ -0,0 +1,101 @@ | |
+/* | |
+ * userpin.c | |
+ * | |
+ * User pin functions for FlashFloppy OSD. | |
+ * | |
+ * This is free and unencumbered software released into the public domain. | |
+ * See the file COPYING for more details, or visit <http://unlicense.org>. | |
+ */ | |
+ | |
+uint8_t videoswitch_state = VS_AUTO; | |
+static uint8_t videoswitch_pin = 0; | |
+ | |
+void user_pin_init() | |
+{ | |
+ int i; | |
+ | |
+ /* Video input switching enabled and correctly configured? */ | |
+ if (config.videoswitch) { | |
+ gpio_configure_pin(gpio_amicts, pin_amicts, GPI_pull_up); | |
+ | |
+ for (i = 0; i < ARRAY_SIZE(config.hotkey); i++) { | |
+ struct config_hotkey *hk = &config.hotkey[i]; | |
+ if ((hk->pin_mod) && (hk->flags & HKF_videoswitch)) | |
+ videoswitch_pin |= hk->pin_mod; | |
+ } | |
+ } | |
+ | |
+ for (i = 0; i < 3; i++) { | |
+ uint8_t pin_ux = (i<2 ? pin_u0+i : pin_u2); | |
+ bool_t level = (config.user_pin_high >> i) & 1; | |
+ | |
+ if (videoswitch_pin & (1u<<i)) { | |
+ gpio_configure_pin(gpio_user, pin_ux, | |
+ GPO_opendrain(_2MHz, | |
+ gpio_read_pin(gpio_amicts, pin_amicts))); | |
+ continue; | |
+ } | |
+ if (config.user_pin_opendrain & (1u<<i)) | |
+ gpio_configure_pin(gpio_user, pin_ux, | |
+ GPO_opendrain(_2MHz, level)); | |
+ if (config.user_pin_pushpull & (1u<<i)) | |
+ gpio_configure_pin(gpio_user, pin_ux, | |
+ GPO_pushpull(_2MHz, level)); | |
+ } | |
+} | |
+ | |
+/* State machine for video switching. Switch output is active low. */ | |
+void videoswitch_next(uint8_t pin_num) | |
+{ | |
+ uint8_t pin_ux = (pin_num<2 ? pin_u0+pin_num : pin_u2); | |
+ | |
+ switch (videoswitch_state) { | |
+ case VS_AUTO: | |
+ /* Switch in "auto" position. Advance to state 1. */ | |
+ videoswitch_state = VS_AMIGA; | |
+ gpio_write_pin(gpio_user, pin_ux, 1); | |
+ break; | |
+ case VS_AMIGA: | |
+ /* Switch in "off" position. Advance to state 2. */ | |
+ videoswitch_state = VS_RTG; | |
+ gpio_write_pin(gpio_user, pin_ux, 0); | |
+ break; | |
+ default: | |
+ /* Switch in "on" position. Reset to state 0. */ | |
+ /* NB: pin_ux output level will be set by next | |
+ * videoswitch_update(). */ | |
+ videoswitch_state = VS_AUTO; | |
+ } | |
+} | |
+ | |
+/* Update videoswitch output for state 0. */ | |
+void videoswitch_update() | |
+{ | |
+ int i; | |
+ | |
+ /* Video input switch is not in AUTO state. */ | |
+ if (videoswitch_state) { | |
+ return; | |
+ } | |
+ | |
+ for (i = 0; i < 3; i++) { | |
+ if (videoswitch_pin & (1u<<i)) { | |
+ /* For videoswitch state 0 mirror Amiga CTS input on videoswitch | |
+ * output pins. | |
+ */ | |
+ uint8_t pin_ux = (i<2 ? pin_u0+i : pin_u2); | |
+ gpio_write_pin(gpio_user, pin_ux, | |
+ gpio_read_pin(gpio_amicts, pin_amicts)); | |
+ } | |
+ } | |
+} | |
+ | |
+/* | |
+ * Local variables: | |
+ * mode: C | |
+ * c-file-style: "Linux" | |
+ * c-basic-offset: 4 | |
+ * tab-width: 4 | |
+ * indent-tabs-mode: nil | |
+ * End: | |
+ */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment