Skip to content

Instantly share code, notes, and snippets.

@tkurbad
Last active December 19, 2021 21:14
Show Gist options
  • Save tkurbad/1bdedc8757e1fb1730230057b1ea061a to your computer and use it in GitHub Desktop.
Save tkurbad/1bdedc8757e1fb1730230057b1ea061a to your computer and use it in GitHub Desktop.
FF_OSD videoswitch patch
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