Skip to content

Commit

Permalink
apple2: initial support
Browse files Browse the repository at this point in the history
  • Loading branch information
keirf committed Nov 17, 2024
1 parent fab54f9 commit a32be60
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 3 deletions.
16 changes: 16 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,23 @@ export ROOT := $(CURDIR)
prod-%: FORCE
$(MAKE) target mcu=$* target=bootloader level=prod
$(MAKE) target mcu=$* target=floppy level=prod
$(MAKE) target mcu=$* target=apple2 level=prod
$(MAKE) target mcu=$* target=quickdisk level=prod
$(MAKE) target mcu=$* target=bl_update level=prod
$(MAKE) target mcu=$* target=io_test level=prod

debug-%: FORCE
$(MAKE) target mcu=$* target=bootloader level=debug
$(MAKE) target mcu=$* target=floppy level=debug
$(MAKE) target mcu=$* target=apple2 level=debug
$(MAKE) target mcu=$* target=quickdisk level=debug
$(MAKE) target mcu=$* target=bl_update level=debug
$(MAKE) target mcu=$* target=io_test level=debug

logfile-%: FORCE
$(MAKE) target mcu=$* target=bootloader level=logfile
$(MAKE) target mcu=$* target=floppy level=logfile
$(MAKE) target mcu=$* target=apple2 level=logfile
$(MAKE) target mcu=$* target=quickdisk level=logfile

all-%: FORCE prod-% debug-% logfile-% ;
Expand Down Expand Up @@ -65,6 +68,12 @@ _legacy_dist: FORCE
$(PYTHON) $(ROOT)/scripts/mk_update.py old \
$(t)/alt/logfile/$(PROJ)-logfile-$(VER).upd \
out/$(mcu)/logfile/floppy/target.bin & \
$(PYTHON) $(ROOT)/scripts/mk_update.py old \
$(t)/alt/apple2/$(PROJ)-apple2-$(VER).upd \
out/$(mcu)/$(level)/apple2/target.bin & \
$(PYTHON) $(ROOT)/scripts/mk_update.py old \
$(t)/alt/apple2/logfile/$(PROJ)-apple2-logfile-$(VER).upd \
out/$(mcu)/logfile/apple2/target.bin & \
$(PYTHON) $(ROOT)/scripts/mk_update.py old \
$(t)/alt/quickdisk/$(PROJ)-quickdisk-$(VER).upd \
out/$(mcu)/$(level)/quickdisk/target.bin & \
Expand All @@ -89,6 +98,12 @@ _dist: FORCE
$(PYTHON) $(ROOT)/scripts/mk_update.py new \
$(t)/alt/logfile/$(PROJ)-logfile-$(VER).upd \
out/$(mcu)/logfile/floppy/target.bin $(mcu) & \
$(PYTHON) $(ROOT)/scripts/mk_update.py new \
$(t)/alt/apple2/$(PROJ)-apple2-$(VER).upd \
out/$(mcu)/$(level)/apple2/target.bin $(mcu) & \
$(PYTHON) $(ROOT)/scripts/mk_update.py new \
$(t)/alt/apple2/logfile/$(PROJ)-apple2-logfile-$(VER).upd \
out/$(mcu)/logfile/apple2/target.bin $(mcu) & \
$(PYTHON) $(ROOT)/scripts/mk_update.py new \
$(t)/alt/quickdisk/$(PROJ)-quickdisk-$(VER).upd \
out/$(mcu)/$(level)/quickdisk/target.bin $(mcu) & \
Expand All @@ -106,6 +121,7 @@ dist: FORCE all
mkdir -p $(t)/alt/bootloader
mkdir -p $(t)/alt/logfile
mkdir -p $(t)/alt/io-test
mkdir -p $(t)/alt/apple2/logfile
mkdir -p $(t)/alt/quickdisk/logfile
$(MAKE) _legacy_dist mcu=stm32f105 level=$(level) t=$(t)
$(MAKE) _dist mcu=stm32f105 n=at415-st105 level=$(level) t=$(t)
Expand Down
5 changes: 5 additions & 0 deletions Rules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ ifeq ($(logfile),y)
FLAGS += -DLOGFILE=1
endif

ifeq ($(apple2),y)
floppy := y
FLAGS += -DAPPLE2=1
endif

ifeq ($(quickdisk),y)
FLAGS += -DQUICKDISK=1
endif
Expand Down
6 changes: 6 additions & 0 deletions inc/floppy.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
#define is_quickdisk FALSE
#endif

#if defined(APPLE2)
#define WDATA_TOGGLE TRUE
#else
#define WDATA_TOGGLE FALSE
#endif

#define FINTF_SHUGART 0
#define FINTF_IBMPC 1
#define FINTF_IBMPC_HDOUT 2
Expand Down
7 changes: 6 additions & 1 deletion src/floppy.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,12 @@ static void drive_change_output(
switch (outp) {
case outp_index: pin = pin_08; break;
case outp_trk0: pin = pin_26; break;
case outp_wrprot: pin = pin_28; break;
case outp_wrprot:
pin = pin_28;
#if defined(APPLE2)
assert ^= 1;
#endif
break;
default:
_drive_change_output(drv, outp, assert);
return;
Expand Down
6 changes: 5 additions & 1 deletion src/floppy_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,11 @@ static void timer_dma_init(void)
tim_rdata->ccmr1 = (TIM_CCMR1_CC2S(TIM_CCS_OUTPUT) |
TIM_CCMR1_OC2M(TIM_OCM_PWM1));
tim_rdata->ccer = TIM_CCER_CC2E | ((O_TRUE==0) ? TIM_CCER_CC2P : 0);
#if defined(APPLE2)
tim_rdata->ccr2 = sampleclk_ns(1000);
#else
tim_rdata->ccr2 = sampleclk_ns(400);
#endif
tim_rdata->dier = TIM_DIER_UDE;
tim_rdata->cr2 = 0;

Expand Down Expand Up @@ -290,7 +294,7 @@ static void timer_dma_init(void)
tim_wdata->psc = (SYSCLK_MHZ/SAMPLECLK_MHZ) - 1;
tim_wdata->arr = 0xffff;
tim_wdata->ccmr1 = TIM_CCMR1_CC1S(TIM_CCS_INPUT_TI1);
tim_wdata->dier = TIM_DIER_CC1DE;
tim_wdata->dier = TIM_DIER_CC1DE | (WDATA_TOGGLE ? TIM_DIER_CC1IE : 0);
tim_wdata->cr2 = 0;

/* DMA setup: From the WDATA Timer's CCRx into a circular buffer. */
Expand Down
18 changes: 18 additions & 0 deletions src/gotek/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ unsigned int board_get_buttons(void)
if (mcu_package == MCU_LQFP64)
x &= _rbit32(gpioc->idr) >> 23;
x = ~x & 7;

#if defined(APPLE2)
/* Apple 2: QFN32 select pin PA10 is reassigned as stepper phase #0. */
if (mcu_package == MCU_QFN32)
return x;
#endif
if (has_kc30_header) {
/* KC30 Select pin, Artery models only:
* PF6/PH2 = Select; except QFN32: PA10 = Select. */
Expand All @@ -91,6 +97,7 @@ unsigned int board_get_buttons(void)
: kc30_sel_gpio->idr >> (kc30_sel_pin-2));
x |= ~kc30 & 4;
}

return x;
}

Expand Down Expand Up @@ -281,6 +288,17 @@ void board_init(void)

}

#if defined(APPLE2)
#if defined(NDEBUG)
/* Normal build: Two phases use UART RX/TX. */
pa_skip |= m(9) | m(10);
#else
/* Debug build: Move the two UART phases to the KC30 header. */
pa_skip |= m(6) | m(15);
has_kc30_header = 0;
#endif
#endif

gpio_pull_up_pins(gpioa, ~pa_skip);
gpio_pull_up_pins(gpiob, ~pb_skip);
}
Expand Down
127 changes: 126 additions & 1 deletion src/gotek/floppy.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,20 @@

/* Input pins: DIR=PB0, STEP=PA1, SELA=PA0, SELB=PA3, WGATE=PB9, SIDE=PB4,
* MOTOR=PA15/PB15 */
#if defined(APPLE2)
#if defined(NDEBUG)
#define pin_pha0 10 /* PA10 - (aka UART RX (PCB silk J4)) */
#define pin_pha1 9 /* PA9 - (aka UART TX) */
#else
#define pin_pha0 6 /* PA6 - (aka SFRKC30 Rotary DAT (PCB silk J8)) */
#define pin_pha1 15 /* PA15 - (aka SRFKC30 Rotary CLK) */
#endif
#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 @@ -46,17 +58,32 @@ DEFINE_IRQ(dma_wdata_irq, "IRQ_wdata_dma");
#define dma_rdata_irq DMA1_CH3_IRQ
DEFINE_IRQ(dma_rdata_irq, "IRQ_rdata_dma");

/* Head step handling. */
#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

/* EXTI IRQs. */
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 */
void IRQ_28(void) __attribute__((alias("IRQ_STEP_changed"))); /* TMR2 */
void IRQ_40(void) __attribute__((alias("IRQ_MOTOR_CHGRST_rotary"))); /* EXTI15_10 */
#if WDATA_TOGGLE
void IRQ_27(void) __attribute__((alias("IRQ_wdata_capture"))); /* TMR1_CC */
#endif
#define MOTOR_CHGRST_IRQ 40
static const struct exti_irq exti_irqs[] = {
#if WDATA_TOGGLE
/* WDATA */ { 27, FLOPPY_IRQ_WGATE_PRI, 0 },
#endif
/* SELA */ { 6, FLOPPY_IRQ_SEL_PRI, 0 },
#if !defined(APPLE2)
/* STEP */ { 28, FLOPPY_IRQ_STEP_PRI, m(2) /* dummy */ },
#endif
/* WGATE */ { 7, FLOPPY_IRQ_WGATE_PRI, 0 },
/* SIDE */ { 10, TIMER_IRQ_PRI, 0 },
/* WGATE */ { 23, FLOPPY_IRQ_WGATE_PRI, 0 },
Expand All @@ -80,6 +107,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 +119,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 +140,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 +153,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 +182,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 +317,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 +447,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 Expand Up @@ -431,6 +545,17 @@ static void IRQ_CHGRST(struct drive *drv)
}
}

#if WDATA_TOGGLE
static void IRQ_wdata_capture(void)
{
/* Clear WDATA-captured flag. */
(void)tim_wdata->ccr1;

/* Toggle polarity to capture the next edge. */
tim_wdata->ccer ^= TIM_CCER_CC1P;
}
#endif

static void IRQ_MOTOR_CHGRST_rotary(void)
{
struct drive *drv = &drive;
Expand Down

0 comments on commit a32be60

Please sign in to comment.