Skip to content

Commit

Permalink
Apple2 first cut
Browse files Browse the repository at this point in the history
  • Loading branch information
keirf committed Mar 14, 2024
1 parent ca7144b commit 6b9850f
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 0 deletions.
1 change: 1 addition & 0 deletions Rules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ FLAGS += -Wstrict-prototypes -Wredundant-decls -Wnested-externs
FLAGS += -fno-common -fno-exceptions -fno-strict-aliasing
FLAGS += -mlittle-endian -mthumb -mfloat-abi=soft
FLAGS += -Wno-unused-value -ffunction-sections
FLAGS += -DAPPLE2=1

## STM32F105
ifeq ($(mcu),stm32f105)
Expand Down
2 changes: 2 additions & 0 deletions src/gotek/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,10 +219,12 @@ void board_init(void)

if (mcu_package == MCU_QFN32) {

#if !defined(APPLE2)
/* The sole QFN32 board is a KC30 Rev 1 design. */
has_kc30_header = 1;

pa_skip &= ~(1<<10); /* PA10 is not used as serial rx */
#endif
pb_skip |= 1<<1; /* PB1 is a floppy input (WGATE) */

} else {
Expand Down
99 changes: 99 additions & 0 deletions src/gotek/floppy.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,15 @@

/* Input pins: DIR=PB0, STEP=PA1, SELA=PA0, SELB=PA3, WGATE=PB9, SIDE=PB4,
* MOTOR=PA15/PB15 */
#if defined(APPLE2)
#define pin_pha0 6 /* PA6 */
#define pin_pha1 15 /* PA15 */
#define pin_pha2 0 /* PB0 */
#define pin_pha3 1 /* PA1 */
#else
#define pin_dir 0 /* PB0 */
#define pin_step 1 /* PA1 */
#endif
#define pin_sel0 0 /* PA0 */
#define pin_sel1 3 /* PA3 */
static uint8_t pin_wgate = 9; /* PB9 */
Expand Down Expand Up @@ -51,7 +58,12 @@ void IRQ_6(void) __attribute__((alias("IRQ_SELA_changed"))); /* EXTI0 */
void IRQ_7(void) __attribute__((alias("IRQ_WGATE_rotary"))); /* EXTI1 */
void IRQ_10(void) __attribute__((alias("IRQ_SIDE_changed"))); /* EXTI4 */
void IRQ_23(void) __attribute__((alias("IRQ_WGATE_rotary"))); /* EXTI9_5 */
#if defined(APPLE2)
static struct timer step_timer;
static void POLL_step(void *unused);
#else
void IRQ_28(void) __attribute__((alias("IRQ_STEP_changed"))); /* TMR2 */
#endif
void IRQ_40(void) __attribute__((alias("IRQ_MOTOR_CHGRST_rotary"))); /* EXTI15_10 */
#define MOTOR_CHGRST_IRQ 40
static const struct exti_irq exti_irqs[] = {
Expand Down Expand Up @@ -80,6 +92,7 @@ static volatile uint32_t *p_dma_rd_active;

bool_t floppy_ribbon_is_reversed(void)
{
#if !defined(APPLE2)
time_t t_start = time_now();

/* If ribbon is reversed then most/all inputs are grounded.
Expand All @@ -91,6 +104,7 @@ bool_t floppy_ribbon_is_reversed(void)
if (time_since(t_start) > time_ms(1000))
return TRUE;
}
#endif

return FALSE;
}
Expand All @@ -111,7 +125,9 @@ static void board_floppy_init(void)
gpio->crl = (gpio->crl & ~(0xfu<<((pin)<<2))) \
| (((mode)&0xfu)<<((pin)<<2))

#if !defined(APPLE2)
gpio_configure_pin(gpioa, pin_step, GPI_bus);
#endif
gpio_configure_pin(gpio_data, pin_wdata, GPI_bus);
gpio_configure_pin(gpio_data, pin_rdata, GPO_bus);

Expand All @@ -122,8 +138,10 @@ static void board_floppy_init(void)
| (((mode)&0x3u)<<((pin)<<1));
#define afio syscfg

#if !defined(APPLE2)
gpio_set_af(gpioa, pin_step, 1);
gpio_configure_pin(gpioa, pin_step, AFI(PUPD_none));
#endif

gpio_set_af(gpio_data, pin_wdata, 1);
gpio_configure_pin(gpio_data, pin_wdata, AFI(PUPD_none));
Expand All @@ -149,7 +167,16 @@ static void board_floppy_init(void)
pin_wgate = 1; /* PB1 */
}

#if defined(APPLE2)
gpio_configure_pin(gpioa, pin_pha0, GPI_bus);
gpio_configure_pin(gpioa, pin_pha1, GPI_bus);
gpio_configure_pin(gpiob, pin_pha2, GPI_bus);
gpio_configure_pin(gpioa, pin_pha3, GPI_bus);
timer_init(&step_timer, POLL_step, NULL);
timer_set(&step_timer, time_now());
#else
gpio_configure_pin(gpiob, pin_dir, GPI_bus);
#endif
gpio_configure_pin(gpioa, pin_sel0, GPI_bus);
gpio_configure_pin(gpiob, pin_wgate, GPI_bus);
gpio_configure_pin(gpiob, pin_side, GPI_bus);
Expand Down Expand Up @@ -275,6 +302,76 @@ static void update_SELA_irq(bool_t amiga_hd_id)
#undef OFF
}

#if defined(APPLE2)

static void POLL_step(void *unused)
{
static unsigned int _pha;

struct drive *drv = &drive;
uint16_t idr_a, idr_b;
unsigned int pha;

/* Latch inputs. */
idr_a = gpioa->idr;
idr_b = gpiob->idr;

/* Bail if drive not selected. */
if (idr_a & m(pin_sel0)) {
_pha = 0;
goto out;
}

/* Debounce the phase signals. */
pha = _pha;
_pha = ((idr_a >> pin_pha0) & 1)
| ((idr_a >> (pin_pha1-1)) & 2)
| ((idr_b << (2-pin_pha2)) & 4)
| ((idr_a << (3-pin_pha3)) & 8);
pha &= _pha;

/* Do nothing while we're mid-step. */
if (drv->step.state & STEP_active)
goto out;

/* Rotate the phase bitmap so that the current phase is at bit 0. Note
* that the current phase is directly related to the current cylinder. */
pha = ((pha | (pha << 4)) >> (drv->cyl & 3)) & 0xf;

/* Conditions to action a head step:
* (1) Only one phase is asserted;
* (2) That phase is adjacent to the current phase;
* (3) We haven't hit a cylinder hard limit. */
switch (pha) {
case m(1): /* Phase +1 only */
if (drv->cyl == ff_cfg.max_cyl)
goto out;
drv->step.inward = TRUE;
break;
case m(3): /* Phase -1 only */
if (drv->cyl == 0)
goto out;
drv->step.inward = FALSE;
break;
default:
goto out;
}

/* Action a head step. */
if (dma_rd != NULL)
rdata_stop();
if (dma_wr != NULL)
wdata_stop();
drv->step.start = time_now();
drv->step.state = STEP_started;
IRQx_set_pending(FLOPPY_SOFTIRQ);

out:
timer_set(&step_timer, step_timer.deadline + time_ms(1));
}

#else

static bool_t drive_is_writing(void)
{
if (!dma_wr)
Expand Down Expand Up @@ -335,6 +432,8 @@ static void IRQ_STEP_changed(void)
IRQx_set_pending(FLOPPY_SOFTIRQ);
}

#endif

static void IRQ_SIDE_changed(void)
{
stk_time_t t = stk_now();
Expand Down

0 comments on commit 6b9850f

Please sign in to comment.