Developments for the tranZPUter SW, core library and initials tools
This commit is contained in:
@@ -36,13 +36,13 @@
|
||||
#########################################################################################################
|
||||
|
||||
ifeq ($(__K64F__),1)
|
||||
TOOLSPATH = $(CURDIR)/../../tools
|
||||
COMPILERPATH = $(TOOLSPATH)/arm/bin
|
||||
BASE = $(abspath $(COMPILERPATH))/arm-none-eabi
|
||||
TOOLSPATH = $(CURDIR)/../../tools
|
||||
COMPILERPATH = $(TOOLSPATH)/arm/bin
|
||||
BASE = $(abspath $(COMPILERPATH))/arm-none-eabi
|
||||
else
|
||||
TOOLSPATH = /opt/zpu
|
||||
COMPILERPATH = $(TOOLSPATH)/bin
|
||||
BASE = zpu-elf
|
||||
TOOLSPATH = /opt/zpu
|
||||
COMPILERPATH = $(TOOLSPATH)/bin
|
||||
BASE = zpu-elf
|
||||
endif
|
||||
CC = $(BASE)-gcc
|
||||
CXX = $(BASE)-g++
|
||||
@@ -60,8 +60,15 @@ BUFFER_SUBDIRS:= bdump bedit bread bwrite bfill blen
|
||||
MEM_SUBDIRS := mclear mcopy mdiff mdump meb meh mew mperf msrch mtest
|
||||
HW_SUBDIRS := hr ht tcpu
|
||||
TST_SUBDIRS := dhry coremark
|
||||
MISC_SUBDIRS := help time test tbasic mbasic kilo ed
|
||||
SUBDIRS := $(FS_SUBDIRS) $(DISK_SUBDIRS) $(BUFFER_SUBDIRS) $(MEM_SUBDIRS) $(HW_SUBDIRS) $(TST_SUBDIRS) $(MISC_SUBDIRS)
|
||||
MISC_SUBDIRS := help time
|
||||
APP_SUBDIRS := tbasic mbasic kilo ed
|
||||
ifeq ($(__K64F__),1)
|
||||
TZPU_SUBDIRS:= tzpu tzload
|
||||
else
|
||||
TZPU_SUBDIRS:=
|
||||
endif
|
||||
|
||||
SUBDIRS := $(FS_SUBDIRS) $(DISK_SUBDIRS) $(BUFFER_SUBDIRS) $(MEM_SUBDIRS) $(HW_SUBDIRS) $(TST_SUBDIRS) $(MISC_SUBDIRS) $(APP_SUBDIRS) $(TZPU_SUBDIRS)
|
||||
BASEDIR = ../..
|
||||
TARGETS := all clean install
|
||||
|
||||
|
||||
579
apps/common/analog.c
Normal file
579
apps/common/analog.c
Normal file
@@ -0,0 +1,579 @@
|
||||
/* Teensyduino Core Library
|
||||
* http://www.pjrc.com/teensy/
|
||||
* Copyright (c) 2017 PJRC.COM, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* 1. The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* 2. If the Software is incorporated into a build system that allows
|
||||
* selection among a list of target devices, then similar target
|
||||
* devices manufactured by PJRC.COM must be included in the list of
|
||||
* target devices and selectable in the same manner.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "core_pins.h"
|
||||
//#include "HardwareSerial.h"
|
||||
|
||||
static uint8_t calibrating;
|
||||
static uint8_t analog_right_shift = 0;
|
||||
static uint8_t analog_config_bits = 10;
|
||||
static uint8_t analog_num_average = 4;
|
||||
static uint8_t analog_reference_internal = 0;
|
||||
|
||||
// the alternate clock is connected to OSCERCLK (16 MHz).
|
||||
// datasheet says ADC clock should be 2 to 12 MHz for 16 bit mode
|
||||
// datasheet says ADC clock should be 1 to 18 MHz for 8-12 bit mode
|
||||
#if F_BUS == 128000000
|
||||
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(3) + ADC_CFG1_ADICLK(1) // 8 MHz
|
||||
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 16 MHz
|
||||
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 16 MHz
|
||||
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 16 MHz
|
||||
#elif F_BUS == 120000000
|
||||
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(3) + ADC_CFG1_ADICLK(1) // 7.5 MHz
|
||||
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 15 MHz
|
||||
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 15 MHz
|
||||
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 15 MHz
|
||||
#elif F_BUS == 108000000
|
||||
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(3) + ADC_CFG1_ADICLK(1) // 7 MHz
|
||||
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 14 MHz
|
||||
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 14 MHz
|
||||
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 14 MHz
|
||||
#elif F_BUS == 96000000
|
||||
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 12 MHz
|
||||
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 12 MHz
|
||||
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 12 MHz
|
||||
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 24 MHz
|
||||
#elif F_BUS == 90000000
|
||||
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 11.25 MHz
|
||||
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 11.25 MHz
|
||||
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 11.25 MHz
|
||||
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 22.5 MHz
|
||||
#elif F_BUS == 80000000
|
||||
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 10 MHz
|
||||
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 10 MHz
|
||||
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 10 MHz
|
||||
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 20 MHz
|
||||
#elif F_BUS == 72000000
|
||||
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 9 MHz
|
||||
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 18 MHz
|
||||
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 18 MHz
|
||||
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 18 MHz
|
||||
#elif F_BUS == 64000000
|
||||
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 8 MHz
|
||||
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 16 MHz
|
||||
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 16 MHz
|
||||
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 16 MHz
|
||||
#elif F_BUS == 60000000
|
||||
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 7.5 MHz
|
||||
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 15 MHz
|
||||
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 15 MHz
|
||||
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 15 MHz
|
||||
#elif F_BUS == 56000000 || F_BUS == 54000000
|
||||
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 7 MHz
|
||||
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 14 MHz
|
||||
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 14 MHz
|
||||
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 14 MHz
|
||||
#elif F_BUS == 48000000
|
||||
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 12 MHz
|
||||
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 12 MHz
|
||||
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 12 MHz
|
||||
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1) // 24 MHz
|
||||
#elif F_BUS == 40000000
|
||||
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 10 MHz
|
||||
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 10 MHz
|
||||
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 10 MHz
|
||||
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1) // 20 MHz
|
||||
#elif F_BUS == 36000000
|
||||
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 9 MHz
|
||||
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1) // 18 MHz
|
||||
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1) // 18 MHz
|
||||
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1) // 18 MHz
|
||||
#elif F_BUS == 24000000
|
||||
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(0) // 12 MHz
|
||||
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(0) // 12 MHz
|
||||
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(0) // 12 MHz
|
||||
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 24 MHz
|
||||
#elif F_BUS == 16000000
|
||||
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz
|
||||
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz
|
||||
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz
|
||||
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 16 MHz
|
||||
#elif F_BUS == 8000000
|
||||
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz
|
||||
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz
|
||||
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz
|
||||
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz
|
||||
#elif F_BUS == 4000000
|
||||
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 4 MHz
|
||||
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 4 MHz
|
||||
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 4 MHz
|
||||
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 4 MHz
|
||||
#elif F_BUS == 2000000
|
||||
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 2 MHz
|
||||
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 2 MHz
|
||||
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 2 MHz
|
||||
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 2 MHz
|
||||
#else
|
||||
#error "F_BUS must be 128, 120, 108, 96, 90, 80, 72, 64, 60, 56, 54, 48, 40, 36, 24, 4 or 2 MHz"
|
||||
#endif
|
||||
|
||||
void analog_init(void)
|
||||
{
|
||||
uint32_t num;
|
||||
|
||||
#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
VREF_TRM = 0x60;
|
||||
VREF_SC = 0xE1; // enable 1.2 volt ref
|
||||
#endif
|
||||
|
||||
if (analog_config_bits == 8) {
|
||||
ADC0_CFG1 = ADC_CFG1_8BIT + ADC_CFG1_MODE(0);
|
||||
ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
ADC1_CFG1 = ADC_CFG1_8BIT + ADC_CFG1_MODE(0);
|
||||
ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
|
||||
#endif
|
||||
} else if (analog_config_bits == 10) {
|
||||
ADC0_CFG1 = ADC_CFG1_10BIT + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP;
|
||||
ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
ADC1_CFG1 = ADC_CFG1_10BIT + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP;
|
||||
ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
|
||||
#endif
|
||||
} else if (analog_config_bits == 12) {
|
||||
ADC0_CFG1 = ADC_CFG1_12BIT + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP;
|
||||
ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
ADC1_CFG1 = ADC_CFG1_12BIT + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP;
|
||||
ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
|
||||
#endif
|
||||
} else {
|
||||
ADC0_CFG1 = ADC_CFG1_16BIT + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP;
|
||||
ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
ADC1_CFG1 = ADC_CFG1_16BIT + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP;
|
||||
ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__MK20DX128__)
|
||||
if (analog_reference_internal) {
|
||||
ADC0_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref
|
||||
} else {
|
||||
ADC0_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref
|
||||
}
|
||||
#elif defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
if (analog_reference_internal) {
|
||||
ADC0_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref
|
||||
ADC1_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref
|
||||
} else {
|
||||
ADC0_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref
|
||||
ADC1_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref
|
||||
}
|
||||
#elif defined(__MKL26Z64__)
|
||||
if (analog_reference_internal) {
|
||||
ADC0_SC2 = ADC_SC2_REFSEL(0); // external AREF
|
||||
} else {
|
||||
ADC0_SC2 = ADC_SC2_REFSEL(1); // vcc
|
||||
}
|
||||
#endif
|
||||
|
||||
num = analog_num_average;
|
||||
if (num <= 1) {
|
||||
ADC0_SC3 = ADC_SC3_CAL; // begin cal
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
ADC1_SC3 = ADC_SC3_CAL; // begin cal
|
||||
#endif
|
||||
} else if (num <= 4) {
|
||||
ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0);
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0);
|
||||
#endif
|
||||
} else if (num <= 8) {
|
||||
ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1);
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1);
|
||||
#endif
|
||||
} else if (num <= 16) {
|
||||
ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2);
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2);
|
||||
#endif
|
||||
} else {
|
||||
ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3);
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3);
|
||||
#endif
|
||||
}
|
||||
calibrating = 1;
|
||||
}
|
||||
|
||||
static void wait_for_cal(void)
|
||||
{
|
||||
uint16_t sum;
|
||||
|
||||
//serial_print("wait_for_cal\n");
|
||||
#if defined(HAS_KINETIS_ADC0) && defined(HAS_KINETIS_ADC1)
|
||||
while ((ADC0_SC3 & ADC_SC3_CAL) || (ADC1_SC3 & ADC_SC3_CAL)) {
|
||||
// wait
|
||||
}
|
||||
#elif defined(HAS_KINETIS_ADC0)
|
||||
while (ADC0_SC3 & ADC_SC3_CAL) {
|
||||
// wait
|
||||
}
|
||||
#endif
|
||||
__disable_irq();
|
||||
if (calibrating) {
|
||||
//serial_print("\n");
|
||||
sum = ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 + ADC0_CLP2 + ADC0_CLP1 + ADC0_CLP0;
|
||||
sum = (sum / 2) | 0x8000;
|
||||
ADC0_PG = sum;
|
||||
//serial_print("ADC0_PG = ");
|
||||
//serial_phex16(sum);
|
||||
//serial_print("\n");
|
||||
sum = ADC0_CLMS + ADC0_CLM4 + ADC0_CLM3 + ADC0_CLM2 + ADC0_CLM1 + ADC0_CLM0;
|
||||
sum = (sum / 2) | 0x8000;
|
||||
ADC0_MG = sum;
|
||||
//serial_print("ADC0_MG = ");
|
||||
//serial_phex16(sum);
|
||||
//serial_print("\n");
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
sum = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0;
|
||||
sum = (sum / 2) | 0x8000;
|
||||
ADC1_PG = sum;
|
||||
sum = ADC1_CLMS + ADC1_CLM4 + ADC1_CLM3 + ADC1_CLM2 + ADC1_CLM1 + ADC1_CLM0;
|
||||
sum = (sum / 2) | 0x8000;
|
||||
ADC1_MG = sum;
|
||||
#endif
|
||||
calibrating = 0;
|
||||
}
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
// ADCx_SC2[REFSEL] bit selects the voltage reference sources for ADC.
|
||||
// VREFH/VREFL - connected as the primary reference option
|
||||
// 1.2 V VREF_OUT - connected as the VALT reference option
|
||||
|
||||
#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
#define DEFAULT 0
|
||||
#define INTERNAL 2
|
||||
#define INTERNAL1V2 2
|
||||
#define INTERNAL1V1 2
|
||||
#define EXTERNAL 0
|
||||
|
||||
#elif defined(__MKL26Z64__)
|
||||
#define DEFAULT 0
|
||||
#define INTERNAL 0
|
||||
#define EXTERNAL 1
|
||||
#endif
|
||||
|
||||
void analogReference(uint8_t type)
|
||||
{
|
||||
if (type) {
|
||||
// internal reference requested
|
||||
if (!analog_reference_internal) {
|
||||
analog_reference_internal = 1;
|
||||
if (calibrating) {
|
||||
ADC0_SC3 = 0; // cancel cal
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
ADC1_SC3 = 0; // cancel cal
|
||||
#endif
|
||||
}
|
||||
analog_init();
|
||||
}
|
||||
} else {
|
||||
// vcc or external reference requested
|
||||
if (analog_reference_internal) {
|
||||
analog_reference_internal = 0;
|
||||
if (calibrating) {
|
||||
ADC0_SC3 = 0; // cancel cal
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
ADC1_SC3 = 0; // cancel cal
|
||||
#endif
|
||||
}
|
||||
analog_init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void analogReadRes(unsigned int bits)
|
||||
{
|
||||
unsigned int config;
|
||||
|
||||
if (bits >= 13) {
|
||||
if (bits > 16) bits = 16;
|
||||
config = 16;
|
||||
} else if (bits >= 11) {
|
||||
config = 12;
|
||||
} else if (bits >= 9) {
|
||||
config = 10;
|
||||
} else {
|
||||
config = 8;
|
||||
}
|
||||
analog_right_shift = config - bits;
|
||||
if (config != analog_config_bits) {
|
||||
analog_config_bits = config;
|
||||
if (calibrating) {
|
||||
ADC0_SC3 = 0; // cancel cal
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
ADC1_SC3 = 0;
|
||||
#endif
|
||||
}
|
||||
analog_init();
|
||||
}
|
||||
}
|
||||
|
||||
void analogReadAveraging(unsigned int num)
|
||||
{
|
||||
|
||||
if (calibrating) wait_for_cal();
|
||||
if (num <= 1) {
|
||||
num = 0;
|
||||
ADC0_SC3 = 0;
|
||||
} else if (num <= 4) {
|
||||
num = 4;
|
||||
ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(0);
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(0);
|
||||
#endif
|
||||
} else if (num <= 8) {
|
||||
num = 8;
|
||||
ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(1);
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(1);
|
||||
#endif
|
||||
} else if (num <= 16) {
|
||||
num = 16;
|
||||
ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(2);
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(2);
|
||||
#endif
|
||||
} else {
|
||||
num = 32;
|
||||
ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(3);
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(3);
|
||||
#endif
|
||||
}
|
||||
analog_num_average = num;
|
||||
}
|
||||
|
||||
// The SC1A register is used for both software and hardware trigger modes of operation.
|
||||
|
||||
#if defined(__MK20DX128__)
|
||||
static const uint8_t pin2sc1a[] = {
|
||||
5, 14, 8, 9, 13, 12, 6, 7, 15, 4, 0, 19, 3, 21, // 0-13 -> A0-A13
|
||||
5, 14, 8, 9, 13, 12, 6, 7, 15, 4, // 14-23 are A0-A9
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 24-33 are digital only
|
||||
0, 19, 3, 21, // 34-37 are A10-A13
|
||||
26, // 38 is temp sensor
|
||||
22, // 39 is vref
|
||||
23 // 40 is unused analog pin
|
||||
};
|
||||
#elif defined(__MK20DX256__)
|
||||
static const uint8_t pin2sc1a[] = {
|
||||
5, 14, 8, 9, 13, 12, 6, 7, 15, 4, 0, 19, 3, 19+128, // 0-13 -> A0-A13
|
||||
5, 14, 8, 9, 13, 12, 6, 7, 15, 4, // 14-23 are A0-A9
|
||||
255, 255, // 24-25 are digital only
|
||||
5+192, 5+128, 4+128, 6+128, 7+128, 4+192, // 26-31 are A15-A20
|
||||
255, 255, // 32-33 are digital only
|
||||
0, 19, 3, 19+128, // 34-37 are A10-A13
|
||||
26, // 38 is temp sensor,
|
||||
18+128, // 39 is vref
|
||||
23 // 40 is A14
|
||||
};
|
||||
#elif defined(__MKL26Z64__)
|
||||
static const uint8_t pin2sc1a[] = {
|
||||
5, 14, 8, 9, 13, 12, 6, 7, 15, 11, 0, 4+64, 23, // 0-12 -> A0-A12
|
||||
255, // 13 is digital only (no A13 alias)
|
||||
5, 14, 8, 9, 13, 12, 6, 7, 15, 11, 0, 4+64, 23, // 14-26 are A0-A12
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 27-37 unused
|
||||
26, // 38=temperature
|
||||
27 // 39=bandgap ref (PMC_REGSC |= PMC_REGSC_BGBE)
|
||||
};
|
||||
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
static const uint8_t pin2sc1a[] = {
|
||||
5, 14, 8, 9, 13, 12, 6, 7, 15, 4, 3, 19+128, 14+128, 15+128, // 0-13 -> A0-A13
|
||||
5, 14, 8, 9, 13, 12, 6, 7, 15, 4, // 14-23 are A0-A9
|
||||
255, 255, 255, 255, 255, 255, 255, // 24-30 are digital only
|
||||
14+128, 15+128, 17, 18, 4+128, 5+128, 6+128, 7+128, 17+128, // 31-39 are A12-A20
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, // 40-48 are digital only
|
||||
10+128, 11+128, // 49-50 are A23-A24
|
||||
255, 255, 255, 255, 255, 255, 255, // 51-57 are digital only
|
||||
255, 255, 255, 255, 255, 255, // 58-63 (sd card pins) are digital only
|
||||
3, 19+128, // 64-65 are A10-A11
|
||||
23, 23+128,// 66-67 are A21-A22 (DAC pins)
|
||||
1, 1+128, // 68-69 are A25-A26 (unused USB host port on Teensy 3.5)
|
||||
26, // 70 is Temperature Sensor
|
||||
18+128 // 71 is Vref
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// TODO: perhaps this should store the NVIC priority, so it works recursively?
|
||||
static volatile uint8_t analogReadBusyADC0 = 0;
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
static volatile uint8_t analogReadBusyADC1 = 0;
|
||||
#endif
|
||||
|
||||
int analogRead(uint8_t pin)
|
||||
{
|
||||
int result;
|
||||
uint8_t channel;
|
||||
|
||||
//serial_phex(pin);
|
||||
//serial_print(" ");
|
||||
|
||||
if (pin >= sizeof(pin2sc1a)) return 0;
|
||||
channel = pin2sc1a[pin];
|
||||
if (channel == 255) return 0;
|
||||
|
||||
if (calibrating) wait_for_cal();
|
||||
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
if (channel & 0x80) goto beginADC1;
|
||||
#endif
|
||||
|
||||
__disable_irq();
|
||||
startADC0:
|
||||
//serial_print("startADC0\n");
|
||||
#if defined(__MKL26Z64__)
|
||||
if (channel & 0x40) {
|
||||
ADC0_CFG2 &= ~ADC_CFG2_MUXSEL;
|
||||
channel &= 0x3F;
|
||||
} else {
|
||||
ADC0_CFG2 |= ADC_CFG2_MUXSEL;
|
||||
}
|
||||
#endif
|
||||
ADC0_SC1A = channel;
|
||||
analogReadBusyADC0 = 1;
|
||||
__enable_irq();
|
||||
while (1) {
|
||||
__disable_irq();
|
||||
if ((ADC0_SC1A & ADC_SC1_COCO)) {
|
||||
result = ADC0_RA;
|
||||
analogReadBusyADC0 = 0;
|
||||
__enable_irq();
|
||||
result >>= analog_right_shift;
|
||||
return result;
|
||||
}
|
||||
// detect if analogRead was used from an interrupt
|
||||
// if so, our analogRead got canceled, so it must
|
||||
// be restarted.
|
||||
if (!analogReadBusyADC0) goto startADC0;
|
||||
__enable_irq();
|
||||
yield();
|
||||
}
|
||||
|
||||
#ifdef HAS_KINETIS_ADC1
|
||||
beginADC1:
|
||||
__disable_irq();
|
||||
startADC1:
|
||||
//serial_print("startADC1\n");
|
||||
// ADC1_CFG2[MUXSEL] bit selects between ADCx_SEn channels a and b.
|
||||
if (channel & 0x40) {
|
||||
ADC1_CFG2 &= ~ADC_CFG2_MUXSEL;
|
||||
} else {
|
||||
ADC1_CFG2 |= ADC_CFG2_MUXSEL;
|
||||
}
|
||||
ADC1_SC1A = channel & 0x3F;
|
||||
analogReadBusyADC1 = 1;
|
||||
__enable_irq();
|
||||
while (1) {
|
||||
__disable_irq();
|
||||
if ((ADC1_SC1A & ADC_SC1_COCO)) {
|
||||
result = ADC1_RA;
|
||||
analogReadBusyADC1 = 0;
|
||||
__enable_irq();
|
||||
result >>= analog_right_shift;
|
||||
return result;
|
||||
}
|
||||
// detect if analogRead was used from an interrupt
|
||||
// if so, our analogRead got canceled, so it must
|
||||
// be restarted.
|
||||
if (!analogReadBusyADC1) goto startADC1;
|
||||
__enable_irq();
|
||||
yield();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef int16_t __attribute__((__may_alias__)) aliased_int16_t;
|
||||
|
||||
void analogWriteDAC0(int val)
|
||||
{
|
||||
#if defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
SIM_SCGC2 |= SIM_SCGC2_DAC0;
|
||||
if (analog_reference_internal) {
|
||||
DAC0_C0 = DAC_C0_DACEN; // 1.2V ref is DACREF_1
|
||||
} else {
|
||||
DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2
|
||||
}
|
||||
__asm__ ("usat %[value], #12, %[value]\n\t" : [value] "+r" (val)); // 0 <= val <= 4095
|
||||
|
||||
*(volatile aliased_int16_t *)&(DAC0_DAT0L) = val;
|
||||
#elif defined(__MKL26Z64__)
|
||||
SIM_SCGC6 |= SIM_SCGC6_DAC0;
|
||||
if (analog_reference_internal == 0) {
|
||||
// use 3.3V VDDA power as the reference (this is the default)
|
||||
DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS | DAC_C0_DACSWTRG; // 3.3V VDDA
|
||||
} else {
|
||||
// use whatever voltage is on the AREF pin
|
||||
DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACSWTRG; // 3.3V VDDA
|
||||
}
|
||||
if (val < 0) val = 0;
|
||||
else if (val > 4095) val = 4095;
|
||||
|
||||
*(volatile aliased_int16_t *)&(DAC0_DAT0L) = val;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
void analogWriteDAC1(int val)
|
||||
{
|
||||
SIM_SCGC2 |= SIM_SCGC2_DAC1;
|
||||
if (analog_reference_internal) {
|
||||
DAC1_C0 = DAC_C0_DACEN; // 1.2V ref is DACREF_1
|
||||
} else {
|
||||
DAC1_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2
|
||||
}
|
||||
__asm__ ("usat %[value], #12, %[value]\n\t" : [value] "+r" (val)); // 0 <= val <= 4095
|
||||
|
||||
*(volatile aliased_int16_t *)&(DAC1_DAT0L) = val;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1363
apps/common/pins_teensy.c
Normal file
1363
apps/common/pins_teensy.c
Normal file
File diff suppressed because it is too large
Load Diff
1165
apps/common/tranzputer.c
Normal file
1165
apps/common/tranzputer.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -89,7 +89,11 @@ uint32_t app(uint32_t param1, uint32_t param2)
|
||||
char *fileName;
|
||||
uint32_t retCode = 0xffffffff;
|
||||
FRESULT fr = 1;
|
||||
printf("0=%08lx, 1=%08lx, 2=%08lx, _IOB=%08lx\n", __iob[0], __iob[1], __iob[2], (uint32_t)__iob);
|
||||
|
||||
#if defined __ZPU__
|
||||
printf("0=%08lx, 1=%08lx, 2=%08lx, _IOB=%08lx\n", __iob[0], __iob[1], __iob[2], (uint32_t)__iob);
|
||||
#endif
|
||||
|
||||
fileName = getStrParam(&ptr);
|
||||
if(*fileName == 0x00)
|
||||
{
|
||||
|
||||
293
apps/include/tranzputer.h
Executable file
293
apps/include/tranzputer.h
Executable file
@@ -0,0 +1,293 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: tranzputer.h
|
||||
// Created: May 2020
|
||||
// Author(s): Philip Smart
|
||||
// Description: The TranZPUter library.
|
||||
// This file contains methods which allow applications to access and control the traZPUter board and the underlying Sharp MZ80A host.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2020 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: May 2020 - Initial write of the TranZPUter software.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef TRANZPUTER_H
|
||||
#define TRANZPUTER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Configurable constants.
|
||||
//
|
||||
#define REFRESH_BYTE_COUNT 8 // This constant controls the number of bytes read/written to the z80 bus before a refresh cycle is needed.
|
||||
#define FILL_RFSH_BYTE_CNT 256 // Number of bytes we can write before needing a full refresh for the DRAM.
|
||||
|
||||
// IO addresses on the tranZPUter or mainboard.
|
||||
//
|
||||
#define IO_TZ_CTRLLATCH 0x60
|
||||
|
||||
|
||||
// SHarp MZ80A constants.
|
||||
//
|
||||
#define MZ_VID_RAM_ADDR 0xD000 // Start of Video RAM
|
||||
#define MZ_VID_RAM_SIZE 2048 // Size of Video RAM.
|
||||
#define MZ_VID_DFLT_BYTE 0x00 // Default character (SPACE) for video RAM.
|
||||
#define MZ_ATTR_RAM_ADDR 0xD800 // On machines with the upgrade, the start of the Attribute RAM.
|
||||
#define MZ_ATTR_RAM_SIZE 2048 // Size of the attribute RAM.
|
||||
#define MZ_ATTR_DFLT_BYTE 0x07 // Default colour (White on Black) for the attribute.
|
||||
#define MZ_SCROL_BASE 0xE200 // Base address of the hardware scroll registers.
|
||||
|
||||
|
||||
// Pin Constants - Pins assigned at the hardware level to specific tasks/signals.
|
||||
//
|
||||
#define MAX_TRANZPUTER_PINS 47
|
||||
#define Z80_MEM0_PIN 46
|
||||
#define Z80_MEM1_PIN 47
|
||||
#define Z80_MEM2_PIN 48
|
||||
#define Z80_MEM3_PIN 49
|
||||
#define Z80_MEM4_PIN 50
|
||||
#define Z80_WR_PIN 10
|
||||
#define Z80_RD_PIN 12
|
||||
#define Z80_IORQ_PIN 8
|
||||
#define Z80_MREQ_PIN 9
|
||||
#define Z80_A0_PIN 39
|
||||
#define Z80_A1_PIN 38
|
||||
#define Z80_A2_PIN 37
|
||||
#define Z80_A3_PIN 36
|
||||
#define Z80_A4_PIN 35
|
||||
#define Z80_A5_PIN 34
|
||||
#define Z80_A6_PIN 33
|
||||
#define Z80_A7_PIN 32
|
||||
#define Z80_A8_PIN 31
|
||||
#define Z80_A9_PIN 30
|
||||
#define Z80_A10_PIN 29
|
||||
#define Z80_A11_PIN 28
|
||||
#define Z80_A12_PIN 27
|
||||
#define Z80_A13_PIN 26
|
||||
#define Z80_A14_PIN 25
|
||||
#define Z80_A15_PIN 24
|
||||
#define Z80_A16_PIN 23
|
||||
#define Z80_A17_PIN 22
|
||||
#define Z80_A18_PIN 21
|
||||
#define Z80_D0_PIN 0
|
||||
#define Z80_D1_PIN 1
|
||||
#define Z80_D2_PIN 2
|
||||
#define Z80_D3_PIN 3
|
||||
#define Z80_D4_PIN 4
|
||||
#define Z80_D5_PIN 5
|
||||
#define Z80_D6_PIN 6
|
||||
#define Z80_D7_PIN 7
|
||||
#define Z80_WAIT_PIN 13
|
||||
#define Z80_BUSACK_PIN 17
|
||||
#define Z80_NMI_PIN 43
|
||||
#define Z80_INT_PIN 44
|
||||
#define CTL_RFSH_PIN 45
|
||||
#define CTL_HALT_PIN 14
|
||||
#define CTL_M1_PIN 20
|
||||
#define CTL_BUSRQ_PIN 15
|
||||
#define CTL_BUSACK_PIN 16
|
||||
#define CTL_CLK_PIN 18
|
||||
#define CTL_CLKSLCT_PIN 19
|
||||
|
||||
// Customised pin manipulation methods implemented as stripped down macros. The original had too much additional overhead with procedure call and validation tests,
|
||||
// speed is of the essence for this project as pins change mode and value constantly.
|
||||
//
|
||||
#define pinLow(a) *portClearRegister(pinMap[a]) = 1
|
||||
#define pinHigh(a) *portSetRegister(pinMap[a]) = 1
|
||||
#define pinSet(a, b) if(b) { *portSetRegister(pinMap[a]) = 1; } else { *portClearRegister(pinMap[a]) = 1; }
|
||||
#define pinGet(a) *portInputRegister(pinMap[a])
|
||||
#define pinInput(a) { *portModeRegister(pinMap[a]) = 0; *ioPin[pinMap[a]] = PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS; }
|
||||
#define pinOutput(a) { *portModeRegister(pinMap[a]) = 1;\
|
||||
*ioPin[pinMap[a]] = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);\
|
||||
*ioPin[pinMap[a]] &= ~PORT_PCR_ODE; }
|
||||
#define pinOutputSet(a,b) { *portModeRegister(pinMap[a]) = 1;\
|
||||
*ioPin[pinMap[a]] = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);\
|
||||
*ioPin[pinMap[a]] &= ~PORT_PCR_ODE;\
|
||||
if(b) { *portSetRegister(pinMap[a]) = 1; } else { *portClearRegister(pinMap[a]) = 1; } }
|
||||
|
||||
#define setZ80Data(a) { pinSet(Z80_D7, ((a >> 7) & 0x1)); pinSet(Z80_D6, ((a >> 6) & 0x1));\
|
||||
pinSet(Z80_D5, ((a >> 5) & 0x1)); pinSet(Z80_D4, ((a >> 4) & 0x1));\
|
||||
pinSet(Z80_D3, ((a >> 3) & 0x1)); pinSet(Z80_D2, ((a >> 2) & 0x1));\
|
||||
pinSet(Z80_D1, ((a >> 1) & 0x1)); pinSet(Z80_D0, ((a ) & 0x1)); }
|
||||
#define setZ80Addr(a) { pinSet(Z80_A15, ((a >> 15) & 0x1)); pinSet(Z80_A14, ((a >> 14) & 0x1));\
|
||||
pinSet(Z80_A13, ((a >> 13) & 0x1)); pinSet(Z80_A12, ((a >> 12) & 0x1));\
|
||||
pinSet(Z80_A11, ((a >> 11) & 0x1)); pinSet(Z80_A10, ((a >> 10) & 0x1));\
|
||||
pinSet(Z80_A9, ((a >> 9) & 0x1)); pinSet(Z80_A8, ((a >> 8) & 0x1));\
|
||||
pinSet(Z80_A7, ((a >> 7) & 0x1)); pinSet(Z80_A6, ((a >> 6) & 0x1));\
|
||||
pinSet(Z80_A5, ((a >> 5) & 0x1)); pinSet(Z80_A4, ((a >> 4) & 0x1));\
|
||||
pinSet(Z80_A3, ((a >> 3) & 0x1)); pinSet(Z80_A2, ((a >> 2) & 0x1));\
|
||||
pinSet(Z80_A1, ((a >> 1) & 0x1)); pinSet(Z80_A0, ((a ) & 0x1)); }
|
||||
#define setZ80RefreshAddr(a) { pinSet(Z80_A6, ((a >> 6) & 0x1)); pinSet(Z80_A5, ((a >> 5) & 0x1));\
|
||||
pinSet(Z80_A4, ((a >> 4) & 0x1)); pinSet(Z80_A3, ((a >> 3) & 0x1));\
|
||||
pinSet(Z80_A2, ((a >> 2) & 0x1)); pinSet(Z80_A1, ((a >> 1) & 0x1));\
|
||||
pinSet(Z80_A0, ((a ) & 0x1)); }
|
||||
#define readDataBus() ( pinGet(Z80_D7) << 7 | pinGet(Z80_D6) << 6 | pinGet(Z80_D5) << 5 | pinGet(Z80_D4) << 4 |\
|
||||
pinGet(Z80_D3) << 3 | pinGet(Z80_D2) << 2 | pinGet(Z80_D1) << 1 | pinGet(Z80_D0) )
|
||||
//#define readCtrlLatch() ( pinGet(Z80_A18) << 7 | pinGet(Z80_A17) << 6 | pinGet(Z80_A16) << 5 | pinGet(Z80_MEM4) << 4 |\
|
||||
// pinGet(Z80_MEM3) << 3 | pinGet(Z80_MEM2) << 2 | pinGet(Z80_MEM1) << 1 | pinGet(Z80_MEM0) )
|
||||
// Special case during development where the pins for the MEM4:1 are not connected.
|
||||
#define readCtrlLatch() ((pinGet(Z80_A18) << 7 | pinGet(Z80_A17) << 6 | pinGet(Z80_A16) << 5) & 0b11100000)
|
||||
#define writeCtrlLatch(a) { writeZ80IO(IO_TZ_CTRLLATCH, a); }
|
||||
#define readUpperAddr() ((pinGet(Z80_A18) << 2 | pinGet(Z80_A17) << 1 | pinGet(Z80_A16)) & 0b00000111)
|
||||
#define setZ80Direction(a) { for(uint8_t idx=Z80_D0; idx <= Z80_D7; idx++) { if(a == WRITE) { pinOutput(idx); } else { pinInput(idx); } }; z80Control.busDir = a; }
|
||||
#define reqZ80BusChange(a) { if(a == MAINBOARD_ACCESS && z80Control.ctrlMode == TRANZPUTER_ACCESS) \
|
||||
{\
|
||||
pinHigh(CTL_BUSACK);\
|
||||
z80Control.ctrlMode = MAINBOARD_ACCESS;\
|
||||
z80Control.curCtrlLatch = 0b00000000;\
|
||||
writeCtrlLatch(z80Control.curCtrlLatch);\
|
||||
} else if(a == TRANZPUTER_ACCESS && z80Control.ctrlMode == MAINBOARD_ACCESS)\
|
||||
{\
|
||||
pinLow(CTL_BUSACK);\
|
||||
z80Control.ctrlMode = TRANZPUTER_ACCESS;\
|
||||
z80Control.curCtrlLatch = 0b00011111;\
|
||||
writeCtrlLatch(z80Control.curCtrlLatch);\
|
||||
} }
|
||||
|
||||
|
||||
// Enumeration of the various pins on the project. These enums make it easy to refer to a signal and they are mapped
|
||||
// to the actual hardware pin via the pinMap array.
|
||||
// One of the big advantages is that a swath of pins, such as the address lines, can be switched in a tight loop rather than
|
||||
// individual pin assignments or clunky lists.
|
||||
//
|
||||
enum pinIdxToPinNumMap {
|
||||
Z80_A0 = 0,
|
||||
Z80_A1 = 1,
|
||||
Z80_A2 = 2,
|
||||
Z80_A3 = 3,
|
||||
Z80_A4 = 4,
|
||||
Z80_A5 = 5,
|
||||
Z80_A6 = 6,
|
||||
Z80_A7 = 7,
|
||||
Z80_A8 = 8,
|
||||
Z80_A9 = 9,
|
||||
Z80_A10 = 10,
|
||||
Z80_A11 = 11,
|
||||
Z80_A12 = 12,
|
||||
Z80_A13 = 13,
|
||||
Z80_A14 = 14,
|
||||
Z80_A15 = 15,
|
||||
Z80_A16 = 16,
|
||||
Z80_A17 = 17,
|
||||
Z80_A18 = 18,
|
||||
|
||||
Z80_D0 = 19,
|
||||
Z80_D1 = 20,
|
||||
Z80_D2 = 21,
|
||||
Z80_D3 = 22,
|
||||
Z80_D4 = 23,
|
||||
Z80_D5 = 24,
|
||||
Z80_D6 = 25,
|
||||
Z80_D7 = 26,
|
||||
|
||||
Z80_MEM0 = 27,
|
||||
Z80_MEM1 = 28,
|
||||
Z80_MEM2 = 29,
|
||||
Z80_MEM3 = 30,
|
||||
Z80_MEM4 = 31,
|
||||
|
||||
Z80_IORQ = 32,
|
||||
Z80_MREQ = 33,
|
||||
Z80_RD = 34,
|
||||
Z80_WR = 35,
|
||||
Z80_WAIT = 36,
|
||||
Z80_BUSACK = 37,
|
||||
|
||||
Z80_NMI = 38,
|
||||
Z80_INT = 39,
|
||||
|
||||
CTL_BUSACK = 40,
|
||||
CTL_BUSRQ = 41,
|
||||
CTL_RFSH = 42,
|
||||
CTL_HALT = 43,
|
||||
CTL_M1 = 44,
|
||||
CTL_CLK = 45,
|
||||
CTL_CLKSLCT = 46
|
||||
};
|
||||
|
||||
// Possible control modes that the K64F can be in, do nothing where the Z80 runs normally, control the Z80 and mainboard, or control the Z80 and tranZPUter.
|
||||
enum CTRL_MODE {
|
||||
Z80_RUN = 0,
|
||||
TRANZPUTER_ACCESS = 1,
|
||||
MAINBOARD_ACCESS = 2
|
||||
};
|
||||
|
||||
// Possible bus directions that the K64F can setup for controlling the Z80.
|
||||
enum BUS_DIRECTION {
|
||||
READ = 0,
|
||||
WRITE = 1,
|
||||
TRISTATE = 2
|
||||
};
|
||||
|
||||
// Possible video frames stored internally.
|
||||
//
|
||||
enum VIDEO_FRAMES {
|
||||
SAVED = 0,
|
||||
WORKING = 1
|
||||
};
|
||||
|
||||
// Structure to maintain all the control and management variables so that the state of run is well known by any called method.
|
||||
//
|
||||
typedef struct {
|
||||
uint8_t refreshAddr; // Refresh address for times when the K64F must issue refresh cycles on the Z80 bus.
|
||||
uint8_t runCtrlLatch; // Latch value the Z80 is running with.
|
||||
uint8_t curCtrlLatch; // Latch value set during tranZPUter access of the Z80 bus.
|
||||
uint8_t videoRAM[2][2048]; // Two video memory buffer frames, allows for storage of original frame in [0] and working frame in [1].
|
||||
uint8_t attributeRAM[2][2048]; // Two attribute memory buffer frames, allows for storage of original frame in [0] and working frame in [1].
|
||||
enum CTRL_MODE ctrlMode; // Mode of control, ie normal Z80 Running, controlling mainboard, controlling tranZPUter.
|
||||
enum BUS_DIRECTION busDir; // Direction the bus has been configured for.
|
||||
} t_z80Control;
|
||||
|
||||
// Application execution constants.
|
||||
//
|
||||
|
||||
|
||||
// References to variables within the main library code.
|
||||
extern volatile uint32_t *ioPin[MAX_TRANZPUTER_PINS];
|
||||
extern uint8_t pinMap[MAX_TRANZPUTER_PINS];
|
||||
|
||||
// Prototypes.
|
||||
//
|
||||
void yield(void);
|
||||
void setupPins(volatile uint32_t *);
|
||||
uint8_t reqZ80Bus(uint32_t);
|
||||
void relinquishZ80Bus(void);
|
||||
uint8_t reqMainboardBus(uint32_t);
|
||||
uint8_t reqTranZPUterBus(uint32_t);
|
||||
void setupSignalsForZ80Access(enum BUS_DIRECTION);
|
||||
void releaseZ80(void);
|
||||
void refreshZ80(void);
|
||||
uint8_t writeZ80Memory(uint16_t, uint8_t);
|
||||
uint8_t readZ80Memory(uint16_t);
|
||||
uint8_t writeZ80IO(uint16_t, uint8_t);
|
||||
uint8_t readZ80IO(uint16_t);
|
||||
void fillZ80Memory(uint32_t, uint32_t, uint8_t, uint8_t);
|
||||
void captureVideoFrame(enum VIDEO_FRAMES, uint8_t);
|
||||
void refreshVideoFrame(enum VIDEO_FRAMES, uint8_t, uint8_t);
|
||||
FRESULT loadVideoFrameBuffer(char *, enum VIDEO_FRAMES);
|
||||
FRESULT saveVideoFrameBuffer(char *, enum VIDEO_FRAMES);
|
||||
FRESULT loadZ80Memory(char *, uint32_t, uint8_t, uint8_t);
|
||||
FRESULT saveZ80Memory(char *, uint32_t, uint32_t, uint8_t);
|
||||
// Debug methods.
|
||||
void displaySignals(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // TRANZPUTER_H
|
||||
83
apps/tzload/Makefile
Executable file
83
apps/tzload/Makefile
Executable file
@@ -0,0 +1,83 @@
|
||||
#########################################################################################################
|
||||
##
|
||||
## Name: Makefile
|
||||
## Created: July 2019
|
||||
## Author(s): Philip Smart
|
||||
## Description: App Makefile - Build an App for the ZPU Test Application (zputa) or the zOS
|
||||
## operating system.
|
||||
## This makefile builds an app which is stored on an SD card and called by ZPUTA/zOS
|
||||
## The app is for testing some component where the code is not built into ZPUTA or
|
||||
## a user application for zOS.
|
||||
##
|
||||
## Credits:
|
||||
## Copyright: (c) 2019-20 Philip Smart <philip.smart@net2net.org>
|
||||
##
|
||||
## History: July 2019 - Initial Makefile created for template use.
|
||||
## April 2020 - Added K64F as an additional target and resplit ZPUTA into zOS.
|
||||
##
|
||||
## Notes: Optional component enables:
|
||||
## USELOADB - The Byte write command is implemented in hw#sw so use it.
|
||||
## USE_BOOT_ROM - The target is ROM so dont use initialised data.
|
||||
## MINIMUM_FUNTIONALITY - Minimise functionality to limit code size.
|
||||
##
|
||||
#########################################################################################################
|
||||
## This source file is free software: you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published
|
||||
## by the Free Software Foundation, either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This source file is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#########################################################################################################
|
||||
|
||||
APP_NAME = tzload
|
||||
APP_DIR = $(CURDIR)/..
|
||||
APP_COMMON_DIR = $(CURDIR)/../common
|
||||
BASEDIR = ../../..
|
||||
TEENSYDIR = ../../teensy3/
|
||||
|
||||
# Override values given by parent make for this application as its memory usage differs from the standard app.
|
||||
ifeq ($(__K64F__),1)
|
||||
#override HEAPADDR = 0x2002f000
|
||||
#override HEAPSIZE = 0x00000000
|
||||
#override STACKADDR = 0x2002f000
|
||||
#override STACKSIZE = 0x00000000
|
||||
|
||||
# Modules making up tzpu.
|
||||
APP_C_SRC = $(APP_COMMON_DIR)/pins_teensy.c $(APP_COMMON_DIR)/analog.c $(APP_COMMON_DIR)/tranzputer.c #$(TEENSYDIR)/yield.cpp
|
||||
CFLAGS =
|
||||
CPPFLAGS =
|
||||
LDFLAGS =
|
||||
LIBS =
|
||||
else
|
||||
|
||||
# Modules making up tcpu.
|
||||
APP_C_SRC = #$(APP_COMMON_DIR)/sysutils.c $(APP_COMMON_DIR)/ctypelocal.c
|
||||
CFLAGS =
|
||||
CPPFLAGS =
|
||||
LDFLAGS = -nostdlib
|
||||
LIBS = -lumansi-zpu -limath-zpu
|
||||
endif
|
||||
|
||||
# Filter out the standard HEAP address and size, replacing with the ones required for this application.
|
||||
# Useful for sub-makes
|
||||
FILTER1 = $(filter-out $(filter HEAPADDR=%,$(MAKEFLAGS)), $(MAKEFLAGS))
|
||||
FILTER2 = $(filter-out $(filter HEAPSIZE=%,$(FILTER1)), $(FILTER1))
|
||||
NEWMAKEFLAGS = $(FILTER2) HEAPADDR=$(HEADADDR) HEAPSIZE=$(HEAPSIZE)
|
||||
|
||||
ifeq ($(__K64F__),1)
|
||||
include $(APP_DIR)/Makefile.k64f
|
||||
else
|
||||
|
||||
# There currently is no code for the ZPU, all development being done on the K64F for this app.
|
||||
all:
|
||||
|
||||
clean:
|
||||
|
||||
install:
|
||||
endif
|
||||
403
apps/tzload/tzload.c
Normal file
403
apps/tzload/tzload.c
Normal file
@@ -0,0 +1,403 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: tzload.c
|
||||
// Created: May 2020
|
||||
// Author(s): Philip Smart
|
||||
// Description: A TranZPUter helper program, responsible for loading images off the SD card into
|
||||
// memory on the tranZPUter board or host mainboard./
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2020 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: May 2020 - Initial write of the TranZPUter software.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__K64F__)
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include <usb_serial.h>
|
||||
#include <core_pins.h>
|
||||
#include <Arduino.h>
|
||||
#include <getopt.h>
|
||||
#include "k64f_soc.h"
|
||||
#include <../../libraries/include/stdmisc.h>
|
||||
#elif defined(__ZPU__)
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "zpu_soc.h"
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <stdmisc.h>
|
||||
#else
|
||||
#error "Target CPU not defined, use __ZPU__ or __K64F__"
|
||||
#endif
|
||||
#include "interrupts.h"
|
||||
#include "ff.h" /* Declarations of FatFs API */
|
||||
#include "utils.h"
|
||||
//
|
||||
#if defined __ZPUTA__
|
||||
#include "zputa_app.h"
|
||||
#elif defined __ZOS__
|
||||
#include "zOS_app.h"
|
||||
#else
|
||||
#error OS not defined, use __ZPUTA__ or __ZOS__
|
||||
#endif
|
||||
//
|
||||
#include <app.h>
|
||||
#include <tranzputer.h>
|
||||
#include "tzload.h"
|
||||
|
||||
// Utility functions.
|
||||
#include <tools.c>
|
||||
|
||||
// Version info.
|
||||
#define VERSION "v1.0"
|
||||
#define VERSION_DATE "15/05/2020"
|
||||
#define APP_NAME "TZLOAD"
|
||||
|
||||
// Simple help screen to remmber how this utility works!!
|
||||
//
|
||||
void usage(void)
|
||||
{
|
||||
printf("%s %s\n", APP_NAME, VERSION);
|
||||
printf("\nCommands:-\n");
|
||||
printf(" -h | --help This help text.\n");
|
||||
printf(" -d | --download <file> File into which memory contents from the tranZPUter are stored.\n");
|
||||
printf(" -u | --upload <file> File whose contents are uploaded into the traZPUter memory.\n");
|
||||
printf(" -U | --uploadset <file>:<addr>,...,<file>:<addr>\n");
|
||||
printf(" Upload a set of files at the specified locations. --mainboard specifies mainboard is target, default is tranZPUter.\n");
|
||||
printf(" -f | --fill <byte> Fill the memory specified by --addr, --size and [--mainboard] with the value <byte>.\n");
|
||||
printf(" -V | --video The specified input file is uploaded into the video frame buffer or the specified output file is filled with the video frame buffer.\n");
|
||||
printf("\nOptions:-\n");
|
||||
printf(" -a | --addr Memory address to read/write.\n");
|
||||
printf(" -l | --size Size of memory block to read. This option is only used when reading tranZPUter memory, for writing, the file size is used.\n");
|
||||
printf(" -s | --swap Read tranZPUter memory and store in <infile> then write out <outfile> to the same memory location.\n");
|
||||
printf(" -m | --mainboard Operations will take place on the MZ80A mainboard. Default without this flag is to target the tranZPUter memory.\n");
|
||||
printf(" -v | --verbose Output more messages.\n");
|
||||
|
||||
printf("\nExamples:\n");
|
||||
printf(" tzload --outfile monitor.rom -a 0x000000 # Load the file monitor.rom into the tranZPUter memory at address 0x000000.\n");
|
||||
|
||||
}
|
||||
|
||||
// Main entry and start point of a zOS/ZPUTA Application. Only 2 parameters are catered for and a 32bit return code, additional parameters can be added by changing the appcrt0.s
|
||||
// startup code to add them to the stack prior to app() call.
|
||||
//
|
||||
// Return code for the ZPU is saved in _memreg by the C compiler, this is transferred to _memreg in zOS/ZPUTA in appcrt0.s prior to return.
|
||||
// The K64F ARM processor uses the standard register passing conventions, return code is stored in R0.
|
||||
//
|
||||
uint32_t app(uint32_t param1, uint32_t param2)
|
||||
{
|
||||
// Initialisation.
|
||||
//
|
||||
uint32_t memAddr = 0xFFFFFFFF;
|
||||
uint32_t memSize = 0xFFFFFFFF;
|
||||
uint16_t fillByte = 0xFFFF;
|
||||
int argc = 0;
|
||||
int help_flag = 0;
|
||||
int mainboard_flag = 0;
|
||||
int swap_flag = 0;
|
||||
int verbose_flag = 0;
|
||||
int video_flag = 0;
|
||||
int opt;
|
||||
int option_index = 0;
|
||||
int uploadFNLen = 0;
|
||||
int downloadFNLen = 0;
|
||||
int uploadCnt = 0;
|
||||
long val;
|
||||
char *argv[20];
|
||||
char *uploadArr[20];
|
||||
char *ptr = strtok((char *)param1, " ");
|
||||
char uploadFile[32];
|
||||
char downloadFile[32];
|
||||
|
||||
// Initialisation.
|
||||
uploadFile[0] = '\0';
|
||||
downloadFile[0] = '\0';
|
||||
|
||||
// If the invoking command is given, add it to argv at the start.
|
||||
//
|
||||
if(param2 != 0)
|
||||
{
|
||||
argv[argc++] = (char *)param2;
|
||||
}
|
||||
|
||||
// Now convert the parameter line into argc/argv suitable for getopt to use.
|
||||
while (ptr && argc < 20-1)
|
||||
{
|
||||
argv[argc++] = ptr;
|
||||
ptr = strtok(0, " ");
|
||||
}
|
||||
argv[argc] = 0;
|
||||
|
||||
// Define parameters to be processed.
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"download", required_argument, 0, 'd'},
|
||||
{"upload", required_argument, 0, 'u'},
|
||||
{"uploadset", required_argument, 0, 'U'},
|
||||
{"addr", required_argument, 0, 'a'},
|
||||
{"size", required_argument, 0, 'l'},
|
||||
{"fill", required_argument, 0, 'f'},
|
||||
{"mainboard", no_argument, 0, 'm'},
|
||||
{"swap", no_argument, 0, 's'},
|
||||
{"verbose", no_argument, 0, 'v'},
|
||||
{"video", no_argument, 0, 'V'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
// Parse the command line options.
|
||||
//
|
||||
while((opt = getopt_long(argc, argv, ":ha:l:mvU:Vsd:u:", long_options, &option_index)) != -1)
|
||||
{
|
||||
switch(opt)
|
||||
{
|
||||
case 'h':
|
||||
help_flag = 1;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
mainboard_flag = 1;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
swap_flag = 1;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if(xatoi(&argv[optind-1], &val) == 0)
|
||||
{
|
||||
printf("Illegal numeric:%s\n", argv[optind-1]);
|
||||
return(5);
|
||||
}
|
||||
fillByte = (uint16_t)val;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
if(xatoi(&argv[optind-1], &val) == 0)
|
||||
{
|
||||
printf("Illegal numeric:%s\n", argv[optind-1]);
|
||||
return(6);
|
||||
}
|
||||
memAddr = (uint32_t)val;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
if(xatoi(&argv[optind-1], &val) == 0)
|
||||
{
|
||||
printf("Illegal numeric:%s\n", argv[optind-1]);
|
||||
return(7);
|
||||
}
|
||||
memSize = (uint32_t)val;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
// Data is read from the tranZPUter and stored in the given file.
|
||||
strcpy(downloadFile, argv[optind-1]);
|
||||
downloadFNLen = strlen(downloadFile);
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
// Data is uploaded from the given file into the tranZPUter.
|
||||
strcpy(uploadFile, argv[optind-1]);
|
||||
uploadFNLen = strlen(uploadFile);
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
// Extract an array of <file>:<addr>,... sets for upload.
|
||||
//
|
||||
printf("This line:%s\n", argv[optind-1]);
|
||||
ptr = strtok((char *)argv[optind-1], ",");
|
||||
while (ptr && uploadCnt < 20-1)
|
||||
{
|
||||
printf("Split:%s\n", ptr);
|
||||
uploadArr[uploadCnt++] = ptr;
|
||||
ptr = strtok(0, ",");
|
||||
}
|
||||
printf("Final count=%d\n", uploadCnt);
|
||||
if(uploadCnt == 0)
|
||||
{
|
||||
printf("Upload set command should use format <file>:<addr>,...\n");
|
||||
return(6);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose_flag = 1;
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
video_flag = 1;
|
||||
break;
|
||||
|
||||
case ':':
|
||||
printf("Option %s needs a value\n", argv[optind-1]);
|
||||
break;
|
||||
case '?':
|
||||
printf("Unknown option: %s, ignoring!\n", argv[optind-1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate the input.
|
||||
if(uploadCnt && (help_flag == 1 || uploadFNLen > 0 || downloadFNLen > 0 || swap_flag == 1 || video_flag == 1 || fillByte != 0xFFFF || memAddr != 0xFFFFFFFF || memSize != 0xFFFFFFFF))
|
||||
{
|
||||
printf("Illegal combination of flags, --upload can only be used with --mainboard.\n");
|
||||
return(10);
|
||||
}
|
||||
if(video_flag == 1 && (help_flag == 1 || swap_flag == 1 || fillByte != 0xFFFF || mainboard_flag == 1 || memAddr != 0xFFFFFFFF || memSize != 0xFFFFFFFF))
|
||||
{
|
||||
printf("Illegal combination of flags, --video can only be used with --infile, --outfile and --mainboard.\n");
|
||||
return(11);
|
||||
}
|
||||
if(fillByte != 0xFFFF && (help_flag == 1 || uploadFNLen > 0 || downloadFNLen > 0 || swap_flag == 1 || video_flag == 1 || memAddr == 0xFFFFFFFF || memSize == 0xFFFFFFFF))
|
||||
{
|
||||
printf("Illegal combination of flags, --fill can only be used with --addr, --size and --mainboard.\n");
|
||||
return(12);
|
||||
}
|
||||
|
||||
// If the Video and Upload modes arent required, check other argument combinations.
|
||||
//
|
||||
if(uploadCnt == 0 && video_flag == 0 && fillByte == 0xFFFF)
|
||||
{
|
||||
if(help_flag == 1)
|
||||
{
|
||||
usage();
|
||||
return(0);
|
||||
}
|
||||
if( (uploadFNLen == 0 && downloadFNLen == 0) ||
|
||||
(swap_flag == 0 && uploadFNLen > 0 && downloadFNLen > 0) )
|
||||
{
|
||||
if(swap_flag == 0)
|
||||
{
|
||||
printf("Input file or Output file (only one) needs to be specified.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Both an Input file and an Output file need to be specified for swap mode.\n");
|
||||
}
|
||||
return(15);
|
||||
}
|
||||
if(swap_flag == 0 && downloadFNLen > 0 && memSize == 0xFFFFFFFF)
|
||||
{
|
||||
printf("Please define the size of memory you wish to read.\n");
|
||||
return(16);
|
||||
}
|
||||
if(memAddr == 0xFFFFFFFF)
|
||||
{
|
||||
printf("Please define the target address.\n");
|
||||
return(17);
|
||||
}
|
||||
}
|
||||
if(uploadCnt == 0 && video_flag == 0)
|
||||
{
|
||||
if(mainboard_flag == 1 && (memAddr > 0x10000 || memAddr + memSize > 0x10000))
|
||||
{
|
||||
printf("Mainboard only has 64K, please change the address and size.\n");
|
||||
return(17);
|
||||
}
|
||||
if(mainboard_flag == 0 && (memAddr >= 0x80000 || memAddr + memSize > 0x80000))
|
||||
{
|
||||
printf("tranZPUter board only has 512K, please change the address and size.\n");
|
||||
return(18);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialise the IO.
|
||||
setupPins(G->millis);
|
||||
|
||||
// Bulk file upload command (used to preload a file set).
|
||||
//
|
||||
if(uploadCnt > 0)
|
||||
{
|
||||
// Process all the files in the upload list.
|
||||
//
|
||||
for(uint8_t idx=0; idx < uploadCnt; idx++)
|
||||
{
|
||||
strcpy(uploadFile, strtok((char *)uploadArr[idx], ":"));
|
||||
ptr = strtok(0, ",");
|
||||
if(xatoi(&ptr, &val) == 0)
|
||||
{
|
||||
printf("Illegal numeric in upload list:%s\n", ptr);
|
||||
return(20);
|
||||
}
|
||||
memAddr = (uint32_t)val;
|
||||
|
||||
// Now we have the input file and the address where it should be loaded, call the load function.
|
||||
//
|
||||
loadZ80Memory(uploadFile, memAddr, mainboard_flag, (idx == uploadCnt-1) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Standard read/write operation or swapping out memory?
|
||||
//
|
||||
else if(video_flag)
|
||||
{
|
||||
if(downloadFNLen > 0)
|
||||
{
|
||||
captureVideoFrame(SAVED, 0);
|
||||
saveVideoFrameBuffer(downloadFile, SAVED);
|
||||
} else
|
||||
{
|
||||
loadVideoFrameBuffer(uploadFile, SAVED);
|
||||
refreshVideoFrame(SAVED, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Fill tranZPUter memory or mainboard memory with a fixed value to initialise memory before an upload?
|
||||
//
|
||||
else if(fillByte != 0xFFFF)
|
||||
{
|
||||
fillZ80Memory(memAddr, memSize, (uint8_t)fillByte, mainboard_flag);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if(downloadFNLen > 0)
|
||||
{
|
||||
if(verbose_flag)
|
||||
{
|
||||
printf("Saving %s memory at address:%06lx into file:%s\n", (mainboard_flag == 0 ? "tranZPUter" : "mainboard"), memAddr, downloadFile);
|
||||
}
|
||||
saveZ80Memory(downloadFile, memAddr, memSize, mainboard_flag);
|
||||
}
|
||||
if(uploadFNLen > 0)
|
||||
{
|
||||
if(verbose_flag)
|
||||
{
|
||||
printf("Loading file:%s into the %s at address:%06lx\n", uploadFile, (mainboard_flag == 0 ? "tranZPUter" : "mainboard"), memAddr);
|
||||
}
|
||||
loadZ80Memory(uploadFile, memAddr, mainboard_flag, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
46
apps/tzload/tzload.h
Executable file
46
apps/tzload/tzload.h
Executable file
@@ -0,0 +1,46 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: tzload.h
|
||||
// Created: May 2020
|
||||
// Author(s): Philip Smart
|
||||
// Description: A TranZPUter helper program, responsible for loading images off the SD card into
|
||||
// memory on the tranZPUter board or host mainboard.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2020 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: May 2020 - Initial write of the TranZPUter software.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef TZLOAD_H
|
||||
#define TZLOAD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Components to be embedded in the program.
|
||||
//
|
||||
// Filesystem components to be embedded in the program.
|
||||
|
||||
// Application execution constants.
|
||||
//
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // TZLOAD_H
|
||||
83
apps/tzpu/Makefile
Executable file
83
apps/tzpu/Makefile
Executable file
@@ -0,0 +1,83 @@
|
||||
#########################################################################################################
|
||||
##
|
||||
## Name: Makefile
|
||||
## Created: July 2019
|
||||
## Author(s): Philip Smart
|
||||
## Description: App Makefile - Build an App for the ZPU Test Application (zputa) or the zOS
|
||||
## operating system.
|
||||
## This makefile builds an app which is stored on an SD card and called by ZPUTA/zOS
|
||||
## The app is for testing some component where the code is not built into ZPUTA or
|
||||
## a user application for zOS.
|
||||
##
|
||||
## Credits:
|
||||
## Copyright: (c) 2019-20 Philip Smart <philip.smart@net2net.org>
|
||||
##
|
||||
## History: July 2019 - Initial Makefile created for template use.
|
||||
## April 2020 - Added K64F as an additional target and resplit ZPUTA into zOS.
|
||||
##
|
||||
## Notes: Optional component enables:
|
||||
## USELOADB - The Byte write command is implemented in hw#sw so use it.
|
||||
## USE_BOOT_ROM - The target is ROM so dont use initialised data.
|
||||
## MINIMUM_FUNTIONALITY - Minimise functionality to limit code size.
|
||||
##
|
||||
#########################################################################################################
|
||||
## This source file is free software: you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published
|
||||
## by the Free Software Foundation, either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This source file is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#########################################################################################################
|
||||
|
||||
APP_NAME = tzpu
|
||||
APP_DIR = $(CURDIR)/..
|
||||
APP_COMMON_DIR = $(CURDIR)/../common
|
||||
BASEDIR = ../../..
|
||||
TEENSYDIR = ../../teensy3/
|
||||
|
||||
# Override values given by parent make for this application as its memory usage differs from the standard app.
|
||||
ifeq ($(__K64F__),1)
|
||||
#override HEAPADDR = 0x2002f000
|
||||
#override HEAPSIZE = 0x00000000
|
||||
#override STACKADDR = 0x2002f000
|
||||
#override STACKSIZE = 0x00000000
|
||||
|
||||
# Modules making up tzpu.
|
||||
APP_C_SRC = $(APP_COMMON_DIR)/pins_teensy.c $(APP_COMMON_DIR)/analog.c $(APP_COMMON_DIR)/tranzputer.c #$(TEENSYDIR)/yield.cpp
|
||||
CFLAGS =
|
||||
CPPFLAGS =
|
||||
LDFLAGS =
|
||||
LIBS =
|
||||
else
|
||||
|
||||
# Modules making up tcpu.
|
||||
APP_C_SRC = #$(APP_COMMON_DIR)/sysutils.c $(APP_COMMON_DIR)/ctypelocal.c
|
||||
CFLAGS =
|
||||
CPPFLAGS =
|
||||
LDFLAGS = -nostdlib
|
||||
LIBS = -lumansi-zpu -limath-zpu
|
||||
endif
|
||||
|
||||
# Filter out the standard HEAP address and size, replacing with the ones required for this application.
|
||||
# Useful for sub-makes
|
||||
FILTER1 = $(filter-out $(filter HEAPADDR=%,$(MAKEFLAGS)), $(MAKEFLAGS))
|
||||
FILTER2 = $(filter-out $(filter HEAPSIZE=%,$(FILTER1)), $(FILTER1))
|
||||
NEWMAKEFLAGS = $(FILTER2) HEAPADDR=$(HEADADDR) HEAPSIZE=$(HEAPSIZE)
|
||||
|
||||
ifeq ($(__K64F__),1)
|
||||
include $(APP_DIR)/Makefile.k64f
|
||||
else
|
||||
|
||||
# There currently is no code for the ZPU, all development being done on the K64F for this app.
|
||||
all:
|
||||
|
||||
clean:
|
||||
|
||||
install:
|
||||
endif
|
||||
152
apps/tzpu/tzpu.c
Normal file
152
apps/tzpu/tzpu.c
Normal file
@@ -0,0 +1,152 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: tzpu.c
|
||||
// Created: May 2020
|
||||
// Author(s): Philip Smart
|
||||
// Description: The TranZPUter control program, responsible for booting up and configuring the
|
||||
// underlying host, providing SD card services and interactive menus.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2020 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: May 2020 - Initial write of the TranZPUter software.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define TZPU_VERSION "1.0"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__K64F__)
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include <usb_serial.h>
|
||||
#include <core_pins.h>
|
||||
#include <Arduino.h>
|
||||
#include "k64f_soc.h"
|
||||
#include <../../libraries/include/stdmisc.h>
|
||||
#elif defined(__ZPU__)
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "zpu_soc.h"
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <stdmisc.h>
|
||||
#else
|
||||
#error "Target CPU not defined, use __ZPU__ or __K64F__"
|
||||
#endif
|
||||
#include "interrupts.h"
|
||||
#include "ff.h" /* Declarations of FatFs API */
|
||||
#include "utils.h"
|
||||
//
|
||||
#if defined __ZPUTA__
|
||||
#include "zputa_app.h"
|
||||
#elif defined __ZOS__
|
||||
#include "zOS_app.h"
|
||||
#else
|
||||
#error OS not defined, use __ZPUTA__ or __ZOS__
|
||||
#endif
|
||||
//
|
||||
#include <app.h>
|
||||
#include <tranzputer.h>
|
||||
#include "tzpu.h"
|
||||
|
||||
// Utility functions.
|
||||
#include <tools.c>
|
||||
|
||||
// Version info.
|
||||
#define VERSION "v1.0"
|
||||
#define VERSION_DATE "15/05/2020"
|
||||
#define APP_NAME "TZPU"
|
||||
|
||||
void testBus(void)
|
||||
{
|
||||
printf("Requesting Z80 BUS and Mainboard access\n");
|
||||
if(reqMainboardBus(100) == 0)
|
||||
{
|
||||
setupSignalsForZ80Access(WRITE);
|
||||
uint8_t data = 0x00;
|
||||
// while(digitalRead(Z80_WAIT) == 0);
|
||||
for(uint16_t idx=0xD000; idx < 0xD800; idx++)
|
||||
{
|
||||
writeZ80Memory(idx, data);
|
||||
// delay(1000000);
|
||||
data++;
|
||||
}
|
||||
releaseZ80();
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Failed to obtain the Z80 bus.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Main entry and start point of a zOS/ZPUTA Application. Only 2 parameters are catered for and a 32bit return code, additional parameters can be added by changing the appcrt0.s
|
||||
// startup code to add them to the stack prior to app() call.
|
||||
//
|
||||
// Return code for the ZPU is saved in _memreg by the C compiler, this is transferred to _memreg in zOS/ZPUTA in appcrt0.s prior to return.
|
||||
// The K64F ARM processor uses the standard register passing conventions, return code is stored in R0.
|
||||
//
|
||||
uint32_t app(uint32_t param1, uint32_t param2)
|
||||
{
|
||||
// Initialisation.
|
||||
//
|
||||
// char *ptr = (char *)param1;
|
||||
// char *pathName;
|
||||
uint32_t retCode = 1;
|
||||
|
||||
// Get name of file to load.
|
||||
//
|
||||
//pathName = getStrParam(&ptr);
|
||||
//if(strlen(pathName) == 0)
|
||||
//{
|
||||
// printf("Usage: tzpu <file>\n");
|
||||
//}
|
||||
_init_Teensyduino_internal_();
|
||||
setupPins(G->millis);
|
||||
|
||||
printf("Loading Monitor ROM\n");
|
||||
loadZ80Memory("SA1510.rom", 0x00000000, 0, 1);
|
||||
|
||||
printf("Loading Floppy ROM\n");
|
||||
loadZ80Memory("1Z-013A.rom", 0x0000F000, 0, 1);
|
||||
|
||||
printf("Testing Display\n");
|
||||
testBus();
|
||||
displaySignals();
|
||||
|
||||
pinMode(13, OUTPUT);
|
||||
while (1) {
|
||||
digitalWriteFast(13, HIGH);
|
||||
delay(500);
|
||||
digitalWriteFast(13, LOW);
|
||||
delay(500);
|
||||
}
|
||||
|
||||
return(retCode);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
46
apps/tzpu/tzpu.h
Executable file
46
apps/tzpu/tzpu.h
Executable file
@@ -0,0 +1,46 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: tzpu.h
|
||||
// Created: May 2020
|
||||
// Author(s): Philip Smart
|
||||
// Description: The TranZPUter control program, responsible for booting up and configuring the
|
||||
// underlying host, providing SD card services and interactive menus.
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2020 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: May 2020 - Initial write of the TranZPUter software.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This source file is free software: you can redistribute it and#or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef TZPU_H
|
||||
#define TZPU_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Components to be embedded in the program.
|
||||
//
|
||||
// Filesystem components to be embedded in the program.
|
||||
|
||||
// Application execution constants.
|
||||
//
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // TZPU_H
|
||||
@@ -399,6 +399,7 @@ int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
|
||||
#define AM_DIR 0x10 /* Directory */
|
||||
#define AM_ARC 0x20 /* Archive */
|
||||
|
||||
#define SECTOR_SIZE 512
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -57,8 +57,6 @@ int16_t decodeCommand(char **ptr)
|
||||
{
|
||||
uint8_t idx;
|
||||
char *paramptr = (*ptr);
|
||||
// char *spaceptr = NULL;
|
||||
// char *splitptr = NULL;
|
||||
|
||||
// If no command entered, exit.
|
||||
if(*ptr == 0x0)
|
||||
@@ -66,9 +64,6 @@ int16_t decodeCommand(char **ptr)
|
||||
|
||||
// Find the end of the command and terminate it for comparison.
|
||||
while(*paramptr == ' ') paramptr++;
|
||||
// spaceptr = paramptr;
|
||||
// while(*spaceptr != ' ' && *spaceptr != 0x00) spaceptr++;
|
||||
// if(*spaceptr == ' ') { (*spaceptr) = 0x00; splitptr = spaceptr; spaceptr++; }
|
||||
|
||||
// Loop through all the commands and try to find a match.
|
||||
for (idx=0; idx < NCMDKEYS; idx++)
|
||||
@@ -82,10 +77,6 @@ int16_t decodeCommand(char **ptr)
|
||||
}
|
||||
}
|
||||
|
||||
// // Restore buffer as we didnt process it.
|
||||
// if(splitptr != NULL)
|
||||
// *splitptr = ' ';
|
||||
|
||||
// No command found, so raise error.
|
||||
return CMD_BADKEY;
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ char *getStrParam(char **ptr)
|
||||
{
|
||||
char *paramptr = (*ptr);
|
||||
char *spaceptr;
|
||||
uint8_t inQuotes = 0;
|
||||
uint8_t inQuotes = 0;
|
||||
|
||||
// If no parameter available, exit.
|
||||
if(*ptr == 0x0)
|
||||
@@ -158,15 +158,15 @@ char *getStrParam(char **ptr)
|
||||
|
||||
// Find the end of the command and terminate it.
|
||||
while(*paramptr == ' ') paramptr++;
|
||||
if(*paramptr == '"') { paramptr++; inQuotes=1; }
|
||||
if(*paramptr == '"') { paramptr++; inQuotes=1; }
|
||||
spaceptr = paramptr;
|
||||
if(inQuotes == 1)
|
||||
{
|
||||
while(*spaceptr != '"' && *spaceptr != 0x00) spaceptr++;
|
||||
} else
|
||||
{
|
||||
while(*spaceptr != ' ' && *spaceptr != 0x00) spaceptr++;
|
||||
}
|
||||
if(inQuotes == 1)
|
||||
{
|
||||
while(*spaceptr != '"' && *spaceptr != 0x00) spaceptr++;
|
||||
} else
|
||||
{
|
||||
while(*spaceptr != ' ' && *spaceptr != 0x00) spaceptr++;
|
||||
}
|
||||
if(*spaceptr == ' ' || *spaceptr == '"') { (*spaceptr) = 0x00; spaceptr++; }
|
||||
|
||||
// Callers pointer is advanced to the next argument or end of string.
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
120
zOS/src/zOS.cpp
120
zOS/src/zOS.cpp
@@ -233,6 +233,7 @@ int cmdProcessor(void)
|
||||
// Local variables.
|
||||
char *ptr;
|
||||
char line[120];
|
||||
char *cmdline;
|
||||
long p1;
|
||||
long p2;
|
||||
long p3;
|
||||
@@ -242,9 +243,9 @@ int cmdProcessor(void)
|
||||
#if defined(__SD_CARD__)
|
||||
char *src1FileName;
|
||||
uint8_t diskInitialised = 0;
|
||||
uint8_t fsInitialised = 0;
|
||||
uint8_t trying = 0;
|
||||
uint32_t retCode;
|
||||
uint8_t fsInitialised = 0;
|
||||
uint8_t trying = 0;
|
||||
uint32_t retCode = 0xffffffff;
|
||||
FRESULT fr;
|
||||
#if defined(BUILTIN_HW_TEST_TIMERS) && BUILTIN_HW_TEST_TIMERS == 1
|
||||
RTC rtc;
|
||||
@@ -614,66 +615,81 @@ int cmdProcessor(void)
|
||||
default:
|
||||
// Reset to start of line - if we match a command but it isnt built in, need to search for it on disk.
|
||||
//
|
||||
ptr = line;
|
||||
if(*ptr != 0x00)
|
||||
if(line[0] != '\0')
|
||||
{
|
||||
#if defined(__SD_CARD__)
|
||||
if(diskInitialised && fsInitialised)
|
||||
// Duplicate the command line to pass it unmodified to the application.
|
||||
cmdline = strndup(line, sizeof(line));
|
||||
if(cmdline != NULL)
|
||||
{
|
||||
// Append the app extension to the command and try to execute.
|
||||
#if defined(__SD_CARD__)
|
||||
// Get the name of the command to try the various formats of using it.
|
||||
ptr = cmdline;
|
||||
src1FileName=getStrParam(&ptr);
|
||||
|
||||
// The user normally just types the command, but it is possible to type the drive and or path and or extension, so cater
|
||||
// for these possibilities by trial. An alternate way is to disect the entered command but I think this would take more code space.
|
||||
trying = 1;
|
||||
while(trying)
|
||||
if(diskInitialised && fsInitialised && strlen(src1FileName) < 16)
|
||||
{
|
||||
switch(trying)
|
||||
// The user normally just types the command, but it is possible to type the drive and or path and or extension, so cater
|
||||
// for these possibilities by trial. An alternate way is to disect the entered command but I think this would take more code space.
|
||||
trying = 1;
|
||||
while(trying)
|
||||
{
|
||||
// Try formatting with all the required drive and path fields.
|
||||
case 1:
|
||||
sprintf(&line[40], "%d:\\%s\\%s.%s", APP_CMD_BIN_DRIVE, APP_CMD_BIN_DIR, src1FileName, APP_CMD_EXTENSION);
|
||||
break;
|
||||
|
||||
// Try command as is.
|
||||
case 2:
|
||||
sprintf(&line[40], "%s", src1FileName);
|
||||
break;
|
||||
|
||||
// Try command as is but with drive and bin dir.
|
||||
case 3:
|
||||
sprintf(&line[40], "%d:\\%s\\%s", APP_CMD_BIN_DRIVE, APP_CMD_BIN_DIR, src1FileName);
|
||||
break;
|
||||
|
||||
// Try command as is but with just drive.
|
||||
case 4:
|
||||
default:
|
||||
sprintf(&line[40], "%d:\\%s", APP_CMD_BIN_DRIVE, src1FileName);
|
||||
break;
|
||||
}
|
||||
// command Load addr Exec addr Mode of exec Param1 Param2 Global struct SoC Config struct
|
||||
#if defined __ZPU__
|
||||
retCode = fileExec(&line[40], APP_CMD_LOAD_ADDR, APP_CMD_EXEC_ADDR, EXEC_MODE_CALL, (uint32_t)ptr, 0, (uint32_t)&G, (uint32_t)&cfgSoC);
|
||||
#else
|
||||
retCode = fileExec(&line[40], APP_CMD_LOAD_ADDR, APP_CMD_EXEC_ADDR, EXEC_MODE_CALL, (uint32_t)ptr, 0, (uint32_t)&G, (uint32_t)&cfgSoC);
|
||||
#endif
|
||||
switch(trying)
|
||||
{
|
||||
// Try formatting with all the required drive and path fields.
|
||||
case 1:
|
||||
sprintf(&line[40], "%d:\\%s\\%s.%s", APP_CMD_BIN_DRIVE, APP_CMD_BIN_DIR, src1FileName, APP_CMD_EXTENSION);
|
||||
break;
|
||||
|
||||
// Try command as is.
|
||||
case 2:
|
||||
sprintf(&line[40], "%s", src1FileName);
|
||||
break;
|
||||
|
||||
// Try command as is but with drive and bin dir.
|
||||
case 3:
|
||||
sprintf(&line[40], "%d:\\%s\\%s", APP_CMD_BIN_DRIVE, APP_CMD_BIN_DIR, src1FileName);
|
||||
break;
|
||||
|
||||
// Try command as is but with just drive.
|
||||
case 4:
|
||||
default:
|
||||
sprintf(&line[40], "%d:\\%s", APP_CMD_BIN_DRIVE, src1FileName);
|
||||
break;
|
||||
}
|
||||
// command Load addr Exec addr Mode of exec Param1 Param2 Global struct SoC Config struct
|
||||
#if defined __ZPU__
|
||||
retCode = fileExec(&line[40], APP_CMD_LOAD_ADDR, APP_CMD_EXEC_ADDR, EXEC_MODE_CALL, (uint32_t)ptr, (uint32_t)cmdline, (uint32_t)&G, (uint32_t)&cfgSoC);
|
||||
#else
|
||||
retCode = fileExec(&line[40], APP_CMD_LOAD_ADDR, APP_CMD_EXEC_ADDR, EXEC_MODE_CALL, (uint32_t)ptr, (uint32_t)cmdline, (uint32_t)&G, (uint32_t)&cfgSoC);
|
||||
#endif
|
||||
|
||||
if(retCode == 0xffffffff && trying <= 3)
|
||||
{
|
||||
trying++;
|
||||
} else
|
||||
{
|
||||
trying = 0;
|
||||
if(retCode == 0xffffffff && trying <= 3)
|
||||
{
|
||||
trying++;
|
||||
} else
|
||||
{
|
||||
trying = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!diskInitialised || !fsInitialised || retCode == 0xffffffff)
|
||||
{
|
||||
printf("Bad command.\n");
|
||||
}
|
||||
if(!diskInitialised || !fsInitialised || retCode == 0xffffffff)
|
||||
{
|
||||
printf("Bad command.\n");
|
||||
}
|
||||
|
||||
// Free up the duplicated command line.
|
||||
//
|
||||
free(cmdline);
|
||||
#else
|
||||
printf("Unknown command!\n");
|
||||
// Free up the duplicated command line.
|
||||
//
|
||||
free(cmdline);
|
||||
printf("Unknown command!\n");
|
||||
#endif
|
||||
} else
|
||||
{
|
||||
printf("Memory exhausted, cannot process command.\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user