Developments for the tranZPUter SW, core library and initials tools

This commit is contained in:
Philip Smart
2020-05-19 00:54:25 +01:00
parent 673e2fa3f4
commit d88a36c65c
22 changed files with 4311 additions and 79 deletions

View File

@@ -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
View 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

File diff suppressed because it is too large Load Diff

1165
apps/common/tranzputer.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View File

@@ -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
}

View File

@@ -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;
}

View File

@@ -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.

View File

@@ -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;