mirror of
https://github.com/equant/apple2idiot.git
synced 2025-03-19 23:31:16 +00:00
KFest
This commit is contained in:
parent
c8e475d90d
commit
55ed4c8bd6
@ -37,9 +37,10 @@
|
||||
# PROGRAM IDS #
|
||||
################################################*/
|
||||
|
||||
#define APP_WEATHER 200
|
||||
#define APP_CHESS 201
|
||||
#define APP_ISS 202
|
||||
#define APP_WEATHER 200
|
||||
#define APP_CHESS 201
|
||||
#define APP_ISS 202
|
||||
#define APP_DND5EAPI 202
|
||||
|
||||
|
||||
/*################################################
|
||||
|
@ -309,7 +309,7 @@
|
||||
"workbook_filename": ""
|
||||
},
|
||||
"page_layout_descr_file": "",
|
||||
"plot_directory": "",
|
||||
"plot_directory": "/home/equant/Sync/projects/apple_ii/kfest_2022/Presentation/assets/",
|
||||
"spice_adjust_passive_values": false,
|
||||
"spice_external_command": "spice \"%I\"",
|
||||
"subpart_first_id": 65,
|
||||
|
BIN
card/apple2idiot_new/apple2idiot_new.pdf
Normal file
BIN
card/apple2idiot_new/apple2idiot_new.pdf
Normal file
Binary file not shown.
@ -5,7 +5,7 @@
|
||||
|
||||
#include "globals.h"
|
||||
#include "apple2idiot.h"
|
||||
#include "../../../../arduino-lib/Apple2Idiot/A2I_commands.h"
|
||||
#include "A2I_commands.h"
|
||||
|
||||
#define MAX_STR_LEN 250
|
||||
|
||||
|
@ -7,17 +7,15 @@ github.com/equant
|
||||
// Load Wi-Fi library
|
||||
#include <WiFi.h>
|
||||
#include <Apple2Idiot.h>
|
||||
//#include <ArduinoJson.h>
|
||||
//#include <HTTPClient.h>
|
||||
#include "credentials.h"
|
||||
#include "a2i_weather.h"
|
||||
#include "a2i_iss.h"
|
||||
#include "a2i_chess.h"
|
||||
|
||||
#define AUTO_CONNECT_TO_WIFI 1
|
||||
#define AUTO_CONNECT_TIMEOUT 5
|
||||
|
||||
Apple2Idiot a2i = Apple2Idiot();
|
||||
//HTTPClient http;
|
||||
|
||||
/*################################################
|
||||
# Applications we're going to support #
|
||||
@ -33,13 +31,12 @@ Apple2Idiot a2i = Apple2Idiot();
|
||||
# app.
|
||||
################################################*/
|
||||
|
||||
//Chess chess_app = Chess();
|
||||
Chess chess_app = Chess();
|
||||
Weather weather_app = Weather();
|
||||
Iss iss_app = Iss();
|
||||
|
||||
#define N_APPS 2
|
||||
//byte app_ids[N_APPS] = {APP_WEATHER, APP_ISS};
|
||||
byte app_ids[N_APPS] = {APP_ISS, APP_WEATHER};
|
||||
#define N_APPS 3
|
||||
byte app_ids[N_APPS] = {APP_ISS, APP_WEATHER, APP_CHESS};
|
||||
|
||||
/*******************/
|
||||
/* Variables */
|
||||
@ -155,6 +152,13 @@ void loop() {
|
||||
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
//a2i.write_data(ESP_COMMAND_ADDRESS, EOT); // notify Apple IIe we are done processing command byte
|
||||
}
|
||||
else if (current_app_id == chess_app.appId) {
|
||||
Serial.println("Received a command for Chess()");
|
||||
chess_app.handleCommand(command_byte);
|
||||
Serial.println("...command for Chess() handled");
|
||||
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
//a2i.write_data(ESP_COMMAND_ADDRESS, EOT); // notify Apple IIe we are done processing command byte
|
||||
}
|
||||
else {
|
||||
Serial.println("Received a command for UNKNOWN()");
|
||||
}
|
||||
|
@ -4,4 +4,5 @@ For now, this works with both the basic and and cc65 clients
|
||||
|
||||
`../15_fixed_essid_weather-basic`
|
||||
`../15_fixed_essid_weather-cc65`
|
||||
|
||||
if arduino-cli compile --fqbn esp32:esp32:nodemcu-32s .; then arduino-cli upload -p /dev/ttyUSB0 --fqbn esp32:esp32:esp32-poe-iso .; fi
|
||||
|
@ -30,13 +30,13 @@ byte Chess::handleCommand(byte command) {
|
||||
}
|
||||
a2i->write_data(ESP_COMMAND_ADDRESS, result);
|
||||
a2i->read_ram(11);
|
||||
break;
|
||||
return ACK;
|
||||
}
|
||||
case CHESS_NEW_GAME: {
|
||||
a2i->write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
Serial.println("CHESS_NEW_GAME");
|
||||
strcpy(game_string, "");
|
||||
break;
|
||||
return ACK;
|
||||
}
|
||||
default: {
|
||||
return COMMAND_NOT_FOUND;
|
||||
@ -55,6 +55,8 @@ byte Chess::makeMove(String move_string) {
|
||||
* getAIMove() Then we get the AI move.
|
||||
* Then we check the status and return (did someone win or lose?)
|
||||
*/
|
||||
Apple2Idiot a2i;
|
||||
HTTPClient http;
|
||||
if (validateMove(move_string) == CHESS_VALID_MOVE) {
|
||||
strcat(game_string, move_string.c_str());
|
||||
} else {
|
||||
@ -97,17 +99,19 @@ byte Chess::makeMove(String move_string) {
|
||||
}
|
||||
|
||||
char* Chess::getGameStatus(char* game_string) {
|
||||
Apple2Idiot a2i;
|
||||
HTTPClient http;
|
||||
Serial.print("getGameStatus() "); Serial.println(game_status);
|
||||
|
||||
char api_request[MAX_STR_LEN];
|
||||
sprintf(api_request, "%s/status/%s", api_entry_point, game_string);
|
||||
Serial.print(" "); Serial.println(api_request);
|
||||
http->begin(api_request);
|
||||
int httpCode = http->GET(); //Make the request
|
||||
http.begin(api_request);
|
||||
int httpCode = http.GET(); //Make the request
|
||||
delay(10);
|
||||
if (httpCode > 0) { //Check for the returning code
|
||||
Serial.println(" Success on HTTP request");
|
||||
String payload = http->getString();
|
||||
String payload = http.getString();
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
//Serial.println(payload);
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
@ -135,17 +139,19 @@ char* Chess::getGameStatus(char* game_string) {
|
||||
}
|
||||
|
||||
char* Chess::getAIMove() {
|
||||
Apple2Idiot a2i;
|
||||
HTTPClient http;
|
||||
Serial.print("getAIMove() "); Serial.println(game_status);
|
||||
|
||||
char api_request[MAX_STR_LEN];
|
||||
sprintf(api_request, "%s/next_best/%s", api_entry_point, game_string);
|
||||
Serial.print(" "); Serial.println(api_request);
|
||||
http->begin(api_request);
|
||||
int httpCode = http->GET(); //Make the request
|
||||
http.begin(api_request);
|
||||
int httpCode = http.GET(); //Make the request
|
||||
delay(10);
|
||||
if (httpCode > 0) { //Check for the returning code
|
||||
Serial.println(" Success on HTTP request");
|
||||
String payload = http->getString();
|
||||
String payload = http.getString();
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
//Serial.println(payload);
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
@ -173,16 +179,18 @@ char* Chess::getAIMove() {
|
||||
}
|
||||
|
||||
byte Chess::validateMove(String move_string) {
|
||||
Apple2Idiot a2i;
|
||||
HTTPClient http;
|
||||
Serial.print("validateMove() "); Serial.println(move_string);
|
||||
char api_request[MAX_STR_LEN];
|
||||
sprintf(api_request, "%s/valid_move/%s%s", api_entry_point, game_string, move_string);
|
||||
Serial.print(" "); Serial.println(api_request);
|
||||
http->begin(api_request);
|
||||
int httpCode = http->GET(); //Make the request
|
||||
http.begin(api_request);
|
||||
int httpCode = http.GET(); //Make the request
|
||||
delay(10);
|
||||
if (httpCode > 0) { //Check for the returning code
|
||||
Serial.println(" Success on HTTP request");
|
||||
String payload = http->getString();
|
||||
String payload = http.getString();
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
//Serial.println(payload);
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
@ -226,16 +234,18 @@ void Chess::removeSubstr (char *string, char *sub) {
|
||||
}
|
||||
|
||||
void Chess::getBoard() {
|
||||
Apple2Idiot a2i;
|
||||
HTTPClient http;
|
||||
Serial.println("getBoard() ");
|
||||
char api_request[MAX_STR_LEN];
|
||||
sprintf(api_request, "%s/board_string/%s", api_entry_point, game_string);
|
||||
Serial.print(" "); Serial.println(api_request);
|
||||
http->begin(api_request);
|
||||
int httpCode = http->GET(); //Make the request
|
||||
http.begin(api_request);
|
||||
int httpCode = http.GET(); //Make the request
|
||||
delay(10);
|
||||
if (httpCode > 0) { //Check for the returning code
|
||||
Serial.println(" Success on HTTP request");
|
||||
String payload = http->getString();
|
||||
String payload = http.getString();
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
//Serial.println(payload);
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef A2I_CHESS_H
|
||||
#define A2I_CHESS_H
|
||||
#ifndef A2I_WEATHER_H
|
||||
#define A2I_WEATHER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
|
12
examples/20-multiapp-arduino/iss-tracker/.gitignore
vendored
Normal file
12
examples/20-multiapp-arduino/iss-tracker/.gitignore
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
iss.xex
|
||||
json_test
|
||||
iss.s
|
||||
iss.o
|
||||
nsio.s
|
||||
nsio.o
|
||||
faux_json.s
|
||||
faux_json.o
|
||||
app_key.s
|
||||
app_key.o
|
||||
colors.s
|
||||
colors.o
|
353
examples/20-multiapp-arduino/iss-tracker/apple2/Makefile
Normal file
353
examples/20-multiapp-arduino/iss-tracker/apple2/Makefile
Normal file
@ -0,0 +1,353 @@
|
||||
###############################################################################
|
||||
### Generic Makefile for cc65 projects - full version with abstract options ###
|
||||
### V1.3.0(w) 2010 - 2013 Oliver Schmidt & Patryk "Silver Dream !" Łogiewa ###
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
### In order to override defaults - values can be assigned to the variables ###
|
||||
###############################################################################
|
||||
|
||||
# Space or comma separated list of cc65 supported target platforms to build for.
|
||||
# Default: c64 (lowercase!)
|
||||
TARGETS := apple2
|
||||
|
||||
# Name of the final, single-file executable.
|
||||
# Default: name of the current dir with target name appended
|
||||
PROGRAM := iss
|
||||
|
||||
# Path(s) to additional libraries required for linking the program
|
||||
# Use only if you don't want to place copies of the libraries in SRCDIR
|
||||
# Default: none
|
||||
LIBS :=
|
||||
|
||||
# Custom linker issuration file
|
||||
# Use only if you don't want to place it in SRCDIR
|
||||
# Default: none
|
||||
CONFIG :=
|
||||
|
||||
# Additional C compiler flags and options.
|
||||
# Default: none
|
||||
CFLAGS = -Os --static-locals -DBUILD_APPLE2
|
||||
|
||||
# Additional assembler flags and options.
|
||||
# Default: none
|
||||
ASFLAGS =
|
||||
|
||||
# Additional linker flags and options.
|
||||
# Default: none
|
||||
LDFLAGS = --start-addr 0x4000 --ld-args -D,__HIMEM__=0xBF00 apple2-iobuf-0800.o
|
||||
|
||||
# Path to the directory containing C and ASM sources.
|
||||
# Default: src
|
||||
SRCDIR :=
|
||||
|
||||
# Path to the directory where object files are to be stored (inside respective target subdirectories).
|
||||
# Default: obj
|
||||
OBJDIR :=
|
||||
|
||||
# Command used to run the emulator.
|
||||
# Default: depending on target platform. For default (c64) target: x64 -kernal kernal -VICIIdsize -autoload
|
||||
EMUCMD :=
|
||||
|
||||
# Optional commands used before starting the emulation process, and after finishing it.
|
||||
# Default: none
|
||||
#PREEMUCMD := osascript -e "tell application \"System Events\" to set isRunning to (name of processes) contains \"X11.bin\"" -e "if isRunning is true then tell application \"X11\" to activate"
|
||||
#PREEMUCMD := osascript -e "tell application \"X11\" to activate"
|
||||
#POSTEMUCMD := osascript -e "tell application \"System Events\" to tell process \"X11\" to set visible to false"
|
||||
#POSTEMUCMD := osascript -e "tell application \"Terminal\" to activate"
|
||||
PREEMUCMD :=
|
||||
POSTEMUCMD :=
|
||||
|
||||
# On Windows machines VICE emulators may not be available in the PATH by default.
|
||||
# In such case, please set the variable below to point to directory containing
|
||||
# VICE emulators.
|
||||
#VICE_HOME := "C:\Program Files\WinVICE-2.2-x86\"
|
||||
VICE_HOME :=
|
||||
|
||||
# Options state file name. You should not need to change this, but for those
|
||||
# rare cases when you feel you really need to name it differently - here you are
|
||||
STATEFILE := Makefile.options
|
||||
|
||||
###################################################################################
|
||||
#### DO NOT EDIT BELOW THIS LINE, UNLESS YOU REALLY KNOW WHAT YOU ARE DOING! ####
|
||||
###################################################################################
|
||||
|
||||
###################################################################################
|
||||
### Mapping abstract options to the actual compiler, assembler and linker flags ###
|
||||
### Predefined compiler, assembler and linker flags, used with abstract options ###
|
||||
### valid for 2.14.x. Consult the documentation of your cc65 version before use ###
|
||||
###################################################################################
|
||||
|
||||
# Compiler flags used to tell the compiler to optimise for SPEED
|
||||
define _optspeed_
|
||||
CFLAGS += -Oris
|
||||
endef
|
||||
|
||||
# Compiler flags used to tell the compiler to optimise for SIZE
|
||||
define _optsize_
|
||||
CFLAGS += -Or
|
||||
endef
|
||||
|
||||
# Compiler and assembler flags for generating listings
|
||||
define _listing_
|
||||
CFLAGS += --listing $$(@:.o=.lst)
|
||||
ASFLAGS += --listing $$(@:.o=.lst)
|
||||
REMOVES += $(addsuffix .lst,$(basename $(OBJECTS)))
|
||||
endef
|
||||
|
||||
# Linker flags for generating map file
|
||||
define _mapfile_
|
||||
LDFLAGS += --mapfile $$@.map
|
||||
REMOVES += $(PROGRAM).map
|
||||
endef
|
||||
|
||||
# Linker flags for generating VICE label file
|
||||
define _labelfile_
|
||||
LDFLAGS += -Ln $$@.lbl
|
||||
REMOVES += $(PROGRAM).lbl
|
||||
endef
|
||||
|
||||
# Linker flags for generating a debug file
|
||||
define _debugfile_
|
||||
LDFLAGS += -Wl --dbgfile,$$@.dbg
|
||||
REMOVES += $(PROGRAM).dbg
|
||||
endef
|
||||
|
||||
###############################################################################
|
||||
### Defaults to be used if nothing defined in the editable sections above ###
|
||||
###############################################################################
|
||||
|
||||
# Presume the C64 target like the cl65 compile & link utility does.
|
||||
# Set TARGETS to override.
|
||||
ifeq ($(TARGETS),)
|
||||
TARGETS := c64
|
||||
endif
|
||||
|
||||
# Presume we're in a project directory so name the program like the current
|
||||
# directory. Set PROGRAM to override.
|
||||
ifeq ($(PROGRAM),)
|
||||
PROGRAM := $(notdir $(CURDIR))
|
||||
endif
|
||||
|
||||
# Presume the C and asm source files to be located in the subdirectory 'src'.
|
||||
# Set SRCDIR to override.
|
||||
ifeq ($(SRCDIR),)
|
||||
SRCDIR := src
|
||||
endif
|
||||
|
||||
# Presume the object and dependency files to be located in the subdirectory
|
||||
# 'obj' (which will be created). Set OBJDIR to override.
|
||||
ifeq ($(OBJDIR),)
|
||||
OBJDIR := obj
|
||||
endif
|
||||
TARGETOBJDIR := $(OBJDIR)/$(TARGETS)
|
||||
|
||||
# On Windows it is mandatory to have CC65_HOME set. So do not unnecessarily
|
||||
# rely on cl65 being added to the PATH in this scenario.
|
||||
ifdef CC65_HOME
|
||||
CC := $(CC65_HOME)/bin/cl65
|
||||
else
|
||||
CC := cl65
|
||||
endif
|
||||
|
||||
# Default emulator commands and options for particular targets.
|
||||
# Set EMUCMD to override.
|
||||
c64_EMUCMD := $(VICE_HOME)xscpu64 -VICIIdsize -autostart
|
||||
c128_EMUCMD := $(VICE_HOME)x128 -kernal kernal -VICIIdsize -autoload
|
||||
vic20_EMUCMD := $(VICE_HOME)xvic -kernal kernal -VICdsize -autoload
|
||||
pet_EMUCMD := $(VICE_HOME)xpet -Crtcdsize -autoload
|
||||
plus4_EMUCMD := $(VICE_HOME)xplus4 -TEDdsize -autoload
|
||||
# So far there is no x16 emulator in VICE (why??) so we have to use xplus4 with -memsize option
|
||||
c16_EMUCMD := $(VICE_HOME)xplus4 -ramsize 16 -TEDdsize -autoload
|
||||
cbm510_EMUCMD := $(VICE_HOME)xcbm2 -model 510 -VICIIdsize -autoload
|
||||
cbm610_EMUCMD := $(VICE_HOME)xcbm2 -model 610 -Crtcdsize -autoload
|
||||
atari_EMUCMD := atari800 -windowed -xl -pal -nopatchall -run
|
||||
|
||||
ifeq ($(EMUCMD),)
|
||||
EMUCMD = $($(CC65TARGET)_EMUCMD)
|
||||
endif
|
||||
|
||||
###############################################################################
|
||||
### The magic begins ###
|
||||
###############################################################################
|
||||
|
||||
# The "Native Win32" GNU Make contains quite some workarounds to get along with
|
||||
# cmd.exe as shell. However it does not provide means to determine that it does
|
||||
# actually activate those workarounds. Especially does $(SHELL) NOT contain the
|
||||
# value 'cmd.exe'. So the usual way to determine if cmd.exe is being used is to
|
||||
# execute the command 'echo' without any parameters. Only cmd.exe will return a
|
||||
# non-empy string - saying 'ECHO is on/off'.
|
||||
#
|
||||
# Many "Native Win32" prorams accept '/' as directory delimiter just fine. How-
|
||||
# ever the internal commands of cmd.exe generally require '\' to be used.
|
||||
#
|
||||
# cmd.exe has an internal command 'mkdir' that doesn't understand nor require a
|
||||
# '-p' to create parent directories as needed.
|
||||
#
|
||||
# cmd.exe has an internal command 'del' that reports a syntax error if executed
|
||||
# without any file so make sure to call it only if there's an actual argument.
|
||||
ifeq ($(shell echo),)
|
||||
MKDIR = mkdir -p $1
|
||||
RMDIR = rmdir $1
|
||||
RMFILES = $(RM) $1
|
||||
else
|
||||
MKDIR = mkdir $(subst /,\,$1)
|
||||
RMDIR = rmdir $(subst /,\,$1)
|
||||
RMFILES = $(if $1,del /f $(subst /,\,$1))
|
||||
endif
|
||||
COMMA := ,
|
||||
SPACE := $(N/A) $(N/A)
|
||||
define NEWLINE
|
||||
|
||||
|
||||
endef
|
||||
# Note: Do not remove any of the two empty lines above !
|
||||
|
||||
TARGETLIST := $(subst $(COMMA),$(SPACE),$(TARGETS))
|
||||
|
||||
ifeq ($(words $(TARGETLIST)),1)
|
||||
|
||||
# Set PROGRAM to something like 'myprog.c64'.
|
||||
override PROGRAM := $(PROGRAM)
|
||||
|
||||
# Set SOURCES to something like 'src/foo.c src/bar.s'.
|
||||
# Use of assembler files with names ending differently than .s is deprecated!
|
||||
SOURCES := $(wildcard $(SRCDIR)/*.c)
|
||||
SOURCES += $(wildcard $(SRCDIR)/*.s)
|
||||
SOURCES += $(wildcard $(SRCDIR)/*.asm)
|
||||
SOURCES += $(wildcard $(SRCDIR)/*.a65)
|
||||
|
||||
# Add to SOURCES something like 'src/c64/me.c src/c64/too.s'.
|
||||
# Use of assembler files with names ending differently than .s is deprecated!
|
||||
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.c)
|
||||
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.s)
|
||||
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.asm)
|
||||
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.a65)
|
||||
|
||||
# Set OBJECTS to something like 'obj/c64/foo.o obj/c64/bar.o'.
|
||||
OBJECTS := $(addsuffix .o,$(basename $(addprefix $(TARGETOBJDIR)/,$(notdir $(SOURCES)))))
|
||||
|
||||
# Set DEPENDS to something like 'obj/c64/foo.d obj/c64/bar.d'.
|
||||
DEPENDS := $(OBJECTS:.o=.d)
|
||||
|
||||
# Add to LIBS something like 'src/foo.lib src/c64/bar.lib'.
|
||||
LIBS += $(wildcard $(SRCDIR)/*.lib)
|
||||
LIBS += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.lib)
|
||||
|
||||
# Add to CONFIG something like 'src/c64/bar.cfg src/foo.cfg'.
|
||||
CONFIG += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.cfg)
|
||||
CONFIG += $(wildcard $(SRCDIR)/*.cfg)
|
||||
|
||||
# Select CONFIG file to use. Target specific isss have higher priority.
|
||||
ifneq ($(word 2,$(CONFIG)),)
|
||||
CONFIG := $(firstword $(CONFIG))
|
||||
$(info Using iss file $(CONFIG) for linking)
|
||||
endif
|
||||
|
||||
.SUFFIXES:
|
||||
.PHONY: all test clean zap love
|
||||
|
||||
all: $(PROGRAM)
|
||||
|
||||
-include $(DEPENDS)
|
||||
-include $(STATEFILE)
|
||||
|
||||
# If OPTIONS are given on the command line then save them to STATEFILE
|
||||
# if (and only if) they have actually changed. But if OPTIONS are not
|
||||
# given on the command line then load them from STATEFILE. Have object
|
||||
# files depend on STATEFILE only if it actually exists.
|
||||
ifeq ($(origin OPTIONS),command line)
|
||||
ifneq ($(OPTIONS),$(_OPTIONS_))
|
||||
ifeq ($(OPTIONS),)
|
||||
$(info Removing OPTIONS)
|
||||
$(shell $(RM) $(STATEFILE))
|
||||
$(eval $(STATEFILE):)
|
||||
else
|
||||
$(info Saving OPTIONS=$(OPTIONS))
|
||||
$(shell echo _OPTIONS_=$(OPTIONS) > $(STATEFILE))
|
||||
endif
|
||||
$(eval $(OBJECTS): $(STATEFILE))
|
||||
endif
|
||||
else
|
||||
ifeq ($(origin _OPTIONS_),file)
|
||||
$(info Using saved OPTIONS=$(_OPTIONS_))
|
||||
OPTIONS = $(_OPTIONS_)
|
||||
$(eval $(OBJECTS): $(STATEFILE))
|
||||
endif
|
||||
endif
|
||||
|
||||
# Transform the abstract OPTIONS to the actual cc65 options.
|
||||
$(foreach o,$(subst $(COMMA),$(SPACE),$(OPTIONS)),$(eval $(_$o_)))
|
||||
|
||||
# Strip potential variant suffix from the actual cc65 target.
|
||||
CC65TARGET := $(firstword $(subst .,$(SPACE),$(TARGETLIST)))
|
||||
|
||||
# The remaining targets.
|
||||
$(TARGETOBJDIR):
|
||||
$(call MKDIR,$@)
|
||||
|
||||
vpath %.c $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
|
||||
|
||||
$(TARGETOBJDIR)/%.o: %.c | $(TARGETOBJDIR)
|
||||
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(CFLAGS) -o $@ $<
|
||||
|
||||
vpath %.s $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
|
||||
|
||||
$(TARGETOBJDIR)/%.o: %.s | $(TARGETOBJDIR)
|
||||
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
|
||||
|
||||
vpath %.asm $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
|
||||
|
||||
$(TARGETOBJDIR)/%.o: %.asm | $(TARGETOBJDIR)
|
||||
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
|
||||
|
||||
vpath %.a65 $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
|
||||
|
||||
$(TARGETOBJDIR)/%.o: %.a65 | $(TARGETOBJDIR)
|
||||
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
|
||||
|
||||
$(PROGRAM): $(CONFIG) $(OBJECTS) $(LIBS)
|
||||
$(CC) -t $(CC65TARGET) $(LDFLAGS) -o $@ $(patsubst %.cfg,-C %.cfg,$^)
|
||||
|
||||
test: $(PROGRAM)
|
||||
$(PREEMUCMD)
|
||||
$(EMUCMD) $<
|
||||
$(POSTEMUCMD)
|
||||
|
||||
dist: $(PROGRAM)
|
||||
cp dist.apple2/bootable.po dist.apple2/dist.po
|
||||
java -jar dist.apple2/ac.jar -p dist.apple2/dist.po iss.system sys <dist.apple2/iss.system
|
||||
java -jar dist.apple2/ac.jar -as dist.apple2/dist.po iss bin <iss
|
||||
java -jar dist.apple2/ac.jar -p dist.apple2/dist.po MAP.HGR bin <gfx/MAP.HGR
|
||||
cp dist.apple2/dist.po /run/media/equant/BMOW/equant/
|
||||
|
||||
clean:
|
||||
$(call RMFILES,$(OBJECTS))
|
||||
$(call RMFILES,$(DEPENDS))
|
||||
$(call RMFILES,$(REMOVES))
|
||||
$(call RMFILES,$(PROGRAM))
|
||||
$(call RMFILES,*.map)
|
||||
|
||||
else # $(words $(TARGETLIST)),1
|
||||
|
||||
all test clean:
|
||||
$(foreach t,$(TARGETLIST),$(MAKE) TARGETS=$t $@$(NEWLINE))
|
||||
|
||||
endif # $(words $(TARGETLIST)),1
|
||||
|
||||
OBJDIRLIST := $(wildcard $(OBJDIR)/*)
|
||||
|
||||
zap:
|
||||
$(foreach o,$(OBJDIRLIST),-$(call RMFILES,$o/*.o $o/*.d $o/*.lst)$(NEWLINE))
|
||||
$(foreach o,$(OBJDIRLIST),-$(call RMDIR,$o)$(NEWLINE))
|
||||
-$(call RMDIR,$(OBJDIR))
|
||||
-$(call RMFILES,$(basename $(PROGRAM)).* $(STATEFILE))
|
||||
|
||||
love:
|
||||
@echo "Not war, eh?"
|
||||
|
||||
###################################################################
|
||||
### Place your additional targets in the additional Makefiles ###
|
||||
### in the same directory - their names have to end with ".mk"! ###
|
||||
###################################################################
|
||||
-include *.mk
|
@ -0,0 +1,352 @@
|
||||
###############################################################################
|
||||
### Generic Makefile for cc65 projects - full version with abstract options ###
|
||||
### V1.3.0(w) 2010 - 2013 Oliver Schmidt & Patryk "Silver Dream !" Łogiewa ###
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
### In order to override defaults - values can be assigned to the variables ###
|
||||
###############################################################################
|
||||
|
||||
# Space or comma separated list of cc65 supported target platforms to build for.
|
||||
# Default: c64 (lowercase!)
|
||||
TARGETS := apple2 apple.ip65
|
||||
|
||||
# Name of the final, single-file executable.
|
||||
# Default: name of the current dir with target name appended
|
||||
PROGRAM := iss
|
||||
|
||||
# Path(s) to additional libraries required for linking the program
|
||||
# Use only if you don't want to place copies of the libraries in SRCDIR
|
||||
# Default: none
|
||||
LIBS :=
|
||||
|
||||
# Custom linker issuration file
|
||||
# Use only if you don't want to place it in SRCDIR
|
||||
# Default: none
|
||||
CONFIG :=
|
||||
|
||||
# Additional C compiler flags and options.
|
||||
# Default: none
|
||||
CFLAGS = -Os --static-locals -DBUILD_APPLE2
|
||||
|
||||
# Additional assembler flags and options.
|
||||
# Default: none
|
||||
ASFLAGS =
|
||||
|
||||
# Additional linker flags and options.
|
||||
# Default: none
|
||||
LDFLAGS = --start-addr 0x4000 --ld-args -D,__HIMEM__=0xBF00 apple2-iobuf-0800.o
|
||||
|
||||
# Path to the directory containing C and ASM sources.
|
||||
# Default: src
|
||||
SRCDIR :=
|
||||
|
||||
# Path to the directory where object files are to be stored (inside respective target subdirectories).
|
||||
# Default: obj
|
||||
OBJDIR :=
|
||||
|
||||
# Command used to run the emulator.
|
||||
# Default: depending on target platform. For default (c64) target: x64 -kernal kernal -VICIIdsize -autoload
|
||||
EMUCMD :=
|
||||
|
||||
# Optional commands used before starting the emulation process, and after finishing it.
|
||||
# Default: none
|
||||
#PREEMUCMD := osascript -e "tell application \"System Events\" to set isRunning to (name of processes) contains \"X11.bin\"" -e "if isRunning is true then tell application \"X11\" to activate"
|
||||
#PREEMUCMD := osascript -e "tell application \"X11\" to activate"
|
||||
#POSTEMUCMD := osascript -e "tell application \"System Events\" to tell process \"X11\" to set visible to false"
|
||||
#POSTEMUCMD := osascript -e "tell application \"Terminal\" to activate"
|
||||
PREEMUCMD :=
|
||||
POSTEMUCMD :=
|
||||
|
||||
# On Windows machines VICE emulators may not be available in the PATH by default.
|
||||
# In such case, please set the variable below to point to directory containing
|
||||
# VICE emulators.
|
||||
#VICE_HOME := "C:\Program Files\WinVICE-2.2-x86\"
|
||||
VICE_HOME :=
|
||||
|
||||
# Options state file name. You should not need to change this, but for those
|
||||
# rare cases when you feel you really need to name it differently - here you are
|
||||
STATEFILE := Makefile.options
|
||||
|
||||
###################################################################################
|
||||
#### DO NOT EDIT BELOW THIS LINE, UNLESS YOU REALLY KNOW WHAT YOU ARE DOING! ####
|
||||
###################################################################################
|
||||
|
||||
###################################################################################
|
||||
### Mapping abstract options to the actual compiler, assembler and linker flags ###
|
||||
### Predefined compiler, assembler and linker flags, used with abstract options ###
|
||||
### valid for 2.14.x. Consult the documentation of your cc65 version before use ###
|
||||
###################################################################################
|
||||
|
||||
# Compiler flags used to tell the compiler to optimise for SPEED
|
||||
define _optspeed_
|
||||
CFLAGS += -Oris
|
||||
endef
|
||||
|
||||
# Compiler flags used to tell the compiler to optimise for SIZE
|
||||
define _optsize_
|
||||
CFLAGS += -Or
|
||||
endef
|
||||
|
||||
# Compiler and assembler flags for generating listings
|
||||
define _listing_
|
||||
CFLAGS += --listing $$(@:.o=.lst)
|
||||
ASFLAGS += --listing $$(@:.o=.lst)
|
||||
REMOVES += $(addsuffix .lst,$(basename $(OBJECTS)))
|
||||
endef
|
||||
|
||||
# Linker flags for generating map file
|
||||
define _mapfile_
|
||||
LDFLAGS += --mapfile $$@.map
|
||||
REMOVES += $(PROGRAM).map
|
||||
endef
|
||||
|
||||
# Linker flags for generating VICE label file
|
||||
define _labelfile_
|
||||
LDFLAGS += -Ln $$@.lbl
|
||||
REMOVES += $(PROGRAM).lbl
|
||||
endef
|
||||
|
||||
# Linker flags for generating a debug file
|
||||
define _debugfile_
|
||||
LDFLAGS += -Wl --dbgfile,$$@.dbg
|
||||
REMOVES += $(PROGRAM).dbg
|
||||
endef
|
||||
|
||||
###############################################################################
|
||||
### Defaults to be used if nothing defined in the editable sections above ###
|
||||
###############################################################################
|
||||
|
||||
# Presume the C64 target like the cl65 compile & link utility does.
|
||||
# Set TARGETS to override.
|
||||
ifeq ($(TARGETS),)
|
||||
TARGETS := c64
|
||||
endif
|
||||
|
||||
# Presume we're in a project directory so name the program like the current
|
||||
# directory. Set PROGRAM to override.
|
||||
ifeq ($(PROGRAM),)
|
||||
PROGRAM := $(notdir $(CURDIR))
|
||||
endif
|
||||
|
||||
# Presume the C and asm source files to be located in the subdirectory 'src'.
|
||||
# Set SRCDIR to override.
|
||||
ifeq ($(SRCDIR),)
|
||||
SRCDIR := src
|
||||
endif
|
||||
|
||||
# Presume the object and dependency files to be located in the subdirectory
|
||||
# 'obj' (which will be created). Set OBJDIR to override.
|
||||
ifeq ($(OBJDIR),)
|
||||
OBJDIR := obj
|
||||
endif
|
||||
TARGETOBJDIR := $(OBJDIR)/$(TARGETS)
|
||||
|
||||
# On Windows it is mandatory to have CC65_HOME set. So do not unnecessarily
|
||||
# rely on cl65 being added to the PATH in this scenario.
|
||||
ifdef CC65_HOME
|
||||
CC := $(CC65_HOME)/bin/cl65
|
||||
else
|
||||
CC := cl65
|
||||
endif
|
||||
|
||||
# Default emulator commands and options for particular targets.
|
||||
# Set EMUCMD to override.
|
||||
c64_EMUCMD := $(VICE_HOME)xscpu64 -VICIIdsize -autostart
|
||||
c128_EMUCMD := $(VICE_HOME)x128 -kernal kernal -VICIIdsize -autoload
|
||||
vic20_EMUCMD := $(VICE_HOME)xvic -kernal kernal -VICdsize -autoload
|
||||
pet_EMUCMD := $(VICE_HOME)xpet -Crtcdsize -autoload
|
||||
plus4_EMUCMD := $(VICE_HOME)xplus4 -TEDdsize -autoload
|
||||
# So far there is no x16 emulator in VICE (why??) so we have to use xplus4 with -memsize option
|
||||
c16_EMUCMD := $(VICE_HOME)xplus4 -ramsize 16 -TEDdsize -autoload
|
||||
cbm510_EMUCMD := $(VICE_HOME)xcbm2 -model 510 -VICIIdsize -autoload
|
||||
cbm610_EMUCMD := $(VICE_HOME)xcbm2 -model 610 -Crtcdsize -autoload
|
||||
atari_EMUCMD := atari800 -windowed -xl -pal -nopatchall -run
|
||||
|
||||
ifeq ($(EMUCMD),)
|
||||
EMUCMD = $($(CC65TARGET)_EMUCMD)
|
||||
endif
|
||||
|
||||
###############################################################################
|
||||
### The magic begins ###
|
||||
###############################################################################
|
||||
|
||||
# The "Native Win32" GNU Make contains quite some workarounds to get along with
|
||||
# cmd.exe as shell. However it does not provide means to determine that it does
|
||||
# actually activate those workarounds. Especially does $(SHELL) NOT contain the
|
||||
# value 'cmd.exe'. So the usual way to determine if cmd.exe is being used is to
|
||||
# execute the command 'echo' without any parameters. Only cmd.exe will return a
|
||||
# non-empy string - saying 'ECHO is on/off'.
|
||||
#
|
||||
# Many "Native Win32" prorams accept '/' as directory delimiter just fine. How-
|
||||
# ever the internal commands of cmd.exe generally require '\' to be used.
|
||||
#
|
||||
# cmd.exe has an internal command 'mkdir' that doesn't understand nor require a
|
||||
# '-p' to create parent directories as needed.
|
||||
#
|
||||
# cmd.exe has an internal command 'del' that reports a syntax error if executed
|
||||
# without any file so make sure to call it only if there's an actual argument.
|
||||
ifeq ($(shell echo),)
|
||||
MKDIR = mkdir -p $1
|
||||
RMDIR = rmdir $1
|
||||
RMFILES = $(RM) $1
|
||||
else
|
||||
MKDIR = mkdir $(subst /,\,$1)
|
||||
RMDIR = rmdir $(subst /,\,$1)
|
||||
RMFILES = $(if $1,del /f $(subst /,\,$1))
|
||||
endif
|
||||
COMMA := ,
|
||||
SPACE := $(N/A) $(N/A)
|
||||
define NEWLINE
|
||||
|
||||
|
||||
endef
|
||||
# Note: Do not remove any of the two empty lines above !
|
||||
|
||||
TARGETLIST := $(subst $(COMMA),$(SPACE),$(TARGETS))
|
||||
|
||||
ifeq ($(words $(TARGETLIST)),1)
|
||||
|
||||
# Set PROGRAM to something like 'myprog.c64'.
|
||||
override PROGRAM := $(PROGRAM)
|
||||
|
||||
# Set SOURCES to something like 'src/foo.c src/bar.s'.
|
||||
# Use of assembler files with names ending differently than .s is deprecated!
|
||||
SOURCES := $(wildcard $(SRCDIR)/*.c)
|
||||
SOURCES += $(wildcard $(SRCDIR)/*.s)
|
||||
SOURCES += $(wildcard $(SRCDIR)/*.asm)
|
||||
SOURCES += $(wildcard $(SRCDIR)/*.a65)
|
||||
|
||||
# Add to SOURCES something like 'src/c64/me.c src/c64/too.s'.
|
||||
# Use of assembler files with names ending differently than .s is deprecated!
|
||||
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.c)
|
||||
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.s)
|
||||
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.asm)
|
||||
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.a65)
|
||||
|
||||
# Set OBJECTS to something like 'obj/c64/foo.o obj/c64/bar.o'.
|
||||
OBJECTS := $(addsuffix .o,$(basename $(addprefix $(TARGETOBJDIR)/,$(notdir $(SOURCES)))))
|
||||
|
||||
# Set DEPENDS to something like 'obj/c64/foo.d obj/c64/bar.d'.
|
||||
DEPENDS := $(OBJECTS:.o=.d)
|
||||
|
||||
# Add to LIBS something like 'src/foo.lib src/c64/bar.lib'.
|
||||
LIBS += $(wildcard $(SRCDIR)/*.lib)
|
||||
LIBS += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.lib)
|
||||
|
||||
# Add to CONFIG something like 'src/c64/bar.cfg src/foo.cfg'.
|
||||
CONFIG += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.cfg)
|
||||
CONFIG += $(wildcard $(SRCDIR)/*.cfg)
|
||||
|
||||
# Select CONFIG file to use. Target specific isss have higher priority.
|
||||
ifneq ($(word 2,$(CONFIG)),)
|
||||
CONFIG := $(firstword $(CONFIG))
|
||||
$(info Using iss file $(CONFIG) for linking)
|
||||
endif
|
||||
|
||||
.SUFFIXES:
|
||||
.PHONY: all test clean zap love
|
||||
|
||||
all: $(PROGRAM)
|
||||
|
||||
-include $(DEPENDS)
|
||||
-include $(STATEFILE)
|
||||
|
||||
# If OPTIONS are given on the command line then save them to STATEFILE
|
||||
# if (and only if) they have actually changed. But if OPTIONS are not
|
||||
# given on the command line then load them from STATEFILE. Have object
|
||||
# files depend on STATEFILE only if it actually exists.
|
||||
ifeq ($(origin OPTIONS),command line)
|
||||
ifneq ($(OPTIONS),$(_OPTIONS_))
|
||||
ifeq ($(OPTIONS),)
|
||||
$(info Removing OPTIONS)
|
||||
$(shell $(RM) $(STATEFILE))
|
||||
$(eval $(STATEFILE):)
|
||||
else
|
||||
$(info Saving OPTIONS=$(OPTIONS))
|
||||
$(shell echo _OPTIONS_=$(OPTIONS) > $(STATEFILE))
|
||||
endif
|
||||
$(eval $(OBJECTS): $(STATEFILE))
|
||||
endif
|
||||
else
|
||||
ifeq ($(origin _OPTIONS_),file)
|
||||
$(info Using saved OPTIONS=$(_OPTIONS_))
|
||||
OPTIONS = $(_OPTIONS_)
|
||||
$(eval $(OBJECTS): $(STATEFILE))
|
||||
endif
|
||||
endif
|
||||
|
||||
# Transform the abstract OPTIONS to the actual cc65 options.
|
||||
$(foreach o,$(subst $(COMMA),$(SPACE),$(OPTIONS)),$(eval $(_$o_)))
|
||||
|
||||
# Strip potential variant suffix from the actual cc65 target.
|
||||
CC65TARGET := $(firstword $(subst .,$(SPACE),$(TARGETLIST)))
|
||||
|
||||
# The remaining targets.
|
||||
$(TARGETOBJDIR):
|
||||
$(call MKDIR,$@)
|
||||
|
||||
vpath %.c $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
|
||||
|
||||
$(TARGETOBJDIR)/%.o: %.c | $(TARGETOBJDIR)
|
||||
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(CFLAGS) -o $@ $<
|
||||
|
||||
vpath %.s $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
|
||||
|
||||
$(TARGETOBJDIR)/%.o: %.s | $(TARGETOBJDIR)
|
||||
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
|
||||
|
||||
vpath %.asm $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
|
||||
|
||||
$(TARGETOBJDIR)/%.o: %.asm | $(TARGETOBJDIR)
|
||||
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
|
||||
|
||||
vpath %.a65 $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
|
||||
|
||||
$(TARGETOBJDIR)/%.o: %.a65 | $(TARGETOBJDIR)
|
||||
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
|
||||
|
||||
$(PROGRAM): $(CONFIG) $(OBJECTS) $(LIBS)
|
||||
$(CC) -t $(CC65TARGET) $(LDFLAGS) -o $@ $(patsubst %.cfg,-C %.cfg,$^)
|
||||
|
||||
test: $(PROGRAM)
|
||||
$(PREEMUCMD)
|
||||
$(EMUCMD) $<
|
||||
$(POSTEMUCMD)
|
||||
|
||||
dist: $(PROGRAM)
|
||||
cp dist.apple2/bootable.po dist.apple2/dist.po
|
||||
java -jar dist.apple2/ac.jar -p dist.apple2/dist.po iss.system sys <dist.apple2/iss.system
|
||||
java -jar dist.apple2/ac.jar -as dist.apple2/dist.po iss bin <iss
|
||||
java -jar dist.apple2/ac.jar -p dist.apple2/dist.po MAP.HGR bin <gfx/MAP.HGR
|
||||
|
||||
clean:
|
||||
$(call RMFILES,$(OBJECTS))
|
||||
$(call RMFILES,$(DEPENDS))
|
||||
$(call RMFILES,$(REMOVES))
|
||||
$(call RMFILES,$(PROGRAM))
|
||||
$(call RMFILES,*.map)
|
||||
|
||||
else # $(words $(TARGETLIST)),1
|
||||
|
||||
all test clean:
|
||||
$(foreach t,$(TARGETLIST),$(MAKE) TARGETS=$t $@$(NEWLINE))
|
||||
|
||||
endif # $(words $(TARGETLIST)),1
|
||||
|
||||
OBJDIRLIST := $(wildcard $(OBJDIR)/*)
|
||||
|
||||
zap:
|
||||
$(foreach o,$(OBJDIRLIST),-$(call RMFILES,$o/*.o $o/*.d $o/*.lst)$(NEWLINE))
|
||||
$(foreach o,$(OBJDIRLIST),-$(call RMDIR,$o)$(NEWLINE))
|
||||
-$(call RMDIR,$(OBJDIR))
|
||||
-$(call RMFILES,$(basename $(PROGRAM)).* $(STATEFILE))
|
||||
|
||||
love:
|
||||
@echo "Not war, eh?"
|
||||
|
||||
###################################################################
|
||||
### Place your additional targets in the additional Makefiles ###
|
||||
### in the same directory - their names have to end with ".mk"! ###
|
||||
###################################################################
|
||||
-include *.mk
|
BIN
examples/20-multiapp-arduino/iss-tracker/apple2/apple2/ac.jar
Normal file
BIN
examples/20-multiapp-arduino/iss-tracker/apple2/apple2/ac.jar
Normal file
Binary file not shown.
Binary file not shown.
BIN
examples/20-multiapp-arduino/iss-tracker/apple2/apple2/dist.po
Normal file
BIN
examples/20-multiapp-arduino/iss-tracker/apple2/apple2/dist.po
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
examples/20-multiapp-arduino/iss-tracker/apple2/gfx/MAP.HGR
Normal file
BIN
examples/20-multiapp-arduino/iss-tracker/apple2/gfx/MAP.HGR
Normal file
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
BIN
examples/20-multiapp-arduino/iss-tracker/apple2/iss
Normal file
BIN
examples/20-multiapp-arduino/iss-tracker/apple2/iss
Normal file
Binary file not shown.
@ -0,0 +1,4 @@
|
||||
obj/apple2/apple2idiot.o: src/apple2idiot.c src/apple2idiot.h
|
||||
|
||||
src/apple2idiot.c src/apple2idiot.h:
|
||||
|
@ -0,0 +1,4 @@
|
||||
obj/apple2/main.o: src/main.c src/map.h src/satellite.h src/osd.h src/apple2idiot.h
|
||||
|
||||
src/main.c src/map.h src/satellite.h src/osd.h src/apple2idiot.h:
|
||||
|
@ -0,0 +1,4 @@
|
||||
obj/apple2/map.o: src/map.c
|
||||
|
||||
src/map.c:
|
||||
|
@ -0,0 +1,4 @@
|
||||
obj/apple2/osd.o: src/osd.c
|
||||
|
||||
src/osd.c:
|
||||
|
@ -0,0 +1,4 @@
|
||||
obj/apple2/satellite.o: src/satellite.c src/satellite.h src/apple2idiot.h
|
||||
|
||||
src/satellite.c src/satellite.h src/apple2idiot.h:
|
||||
|
@ -0,0 +1,4 @@
|
||||
obj/apple2/sp.o: src/sp.c src/sp.h
|
||||
|
||||
src/sp.c src/sp.h:
|
||||
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,412 @@
|
||||
#ifndef _IP65_H
|
||||
#define _IP65_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// Ethernet driver initialization parameter values
|
||||
//
|
||||
#if defined(__APPLE2__)
|
||||
#define ETH_INIT_DEFAULT 3 // Apple II slot number
|
||||
#elif defined(__ATARI__)
|
||||
#define ETH_INIT_DEFAULT 8 // ATARI PBI device ID
|
||||
#else
|
||||
#define ETH_INIT_DEFAULT 0 // Unused
|
||||
#endif
|
||||
|
||||
// Initialize the IP stack
|
||||
//
|
||||
// This calls the individual protocol & driver initializations, so this is
|
||||
// the only *_init routine that must be called by a user application,
|
||||
// except for dhcp_init which must also be called if the application
|
||||
// is using DHCP rather than hardcoded IP configuration.
|
||||
//
|
||||
// Inputs: eth_init: Ethernet driver initialization parameter
|
||||
// Output: true if there was an error, false otherwise
|
||||
//
|
||||
bool __fastcall__ ip65_init(uint8_t eth_init);
|
||||
|
||||
// Access to Ethernet configuration
|
||||
//
|
||||
// Access to the two items below is only valid after ip65_init returned false.
|
||||
//
|
||||
extern uint8_t cfg_mac[6]; // MAC address of local machine
|
||||
extern char eth_name[]; // Zero terminated string containing Ethernet driver name
|
||||
|
||||
// Error codes
|
||||
//
|
||||
#define IP65_ERROR_PORT_IN_USE 0x80
|
||||
#define IP65_ERROR_TIMEOUT_ON_RECEIVE 0x81
|
||||
#define IP65_ERROR_TRANSMIT_FAILED 0x82
|
||||
#define IP65_ERROR_TRANSMISSION_REJECTED_BY_PEER 0x83
|
||||
#define IP65_ERROR_NAME_TOO_LONG 0x84
|
||||
#define IP65_ERROR_DEVICE_FAILURE 0x85
|
||||
#define IP65_ERROR_ABORTED_BY_USER 0x86
|
||||
#define IP65_ERROR_LISTENER_NOT_AVAILABLE 0x87
|
||||
#define IP65_ERROR_CONNECTION_RESET_BY_PEER 0x89
|
||||
#define IP65_ERROR_CONNECTION_CLOSED 0x8A
|
||||
#define IP65_ERROR_MALFORMED_URL 0xA0
|
||||
#define IP65_ERROR_DNS_LOOKUP_FAILED 0xA1
|
||||
|
||||
// Last error code
|
||||
//
|
||||
extern uint8_t ip65_error;
|
||||
|
||||
// Convert error code into a string describing the error
|
||||
//
|
||||
// The pointer returned is a static string, which mustn't be modified.
|
||||
//
|
||||
// Inputs: err_code: Error code
|
||||
// Output: Zero terminated string describing the error
|
||||
//
|
||||
char* __fastcall__ ip65_strerror(uint8_t err_code);
|
||||
|
||||
// Main IP polling loop
|
||||
//
|
||||
// This routine should be periodically called by an application at any time
|
||||
// that an inbound packet needs to be handled.
|
||||
// It is 'non-blocking', i.e. it will return if there is no packet waiting to be
|
||||
// handled. Any inbound packet will be handed off to the appropriate handler.
|
||||
//
|
||||
// Inputs: None
|
||||
// Output: true if no packet was waiting or packet handling caused error, false otherwise
|
||||
//
|
||||
bool ip65_process(void);
|
||||
|
||||
// Generate a 'random' 16 bit word
|
||||
//
|
||||
// Entropy comes from the last ethernet frame, counters, and timer.
|
||||
//
|
||||
// Inputs: None
|
||||
// Output: Pseudo-random 16 bit number
|
||||
//
|
||||
uint16_t ip65_random_word(void);
|
||||
|
||||
// Convert 4 octets (IP address, netmask) into a string representing a dotted quad
|
||||
//
|
||||
// The string is returned in a statically allocated buffer, which subsequent calls
|
||||
// will overwrite.
|
||||
//
|
||||
// Inputs: quad: IP address
|
||||
// Output: Zero terminated string containing dotted quad (e.g. "192.168.1.0")
|
||||
//
|
||||
char* __fastcall__ dotted_quad(uint32_t quad);
|
||||
|
||||
// Convert a string representing a dotted quad (IP address, netmask) into 4 octets
|
||||
//
|
||||
// Inputs: quad: Zero terminated string containing dotted quad (e.g. "192.168.1.0"),
|
||||
// to simplify URL parsing, a ':' or '/' can also terminate the string.
|
||||
// Output: IP address, 0 on error
|
||||
//
|
||||
uint32_t __fastcall__ parse_dotted_quad(char* quad);
|
||||
|
||||
// Minimal DHCP client implementation
|
||||
//
|
||||
// IP addresses are requested from a DHCP server (aka 'leased') but are not renewed
|
||||
// or released. Although this is not correct behaviour according to the DHCP RFC,
|
||||
// this works fine in practice in a typical home network environment.
|
||||
//
|
||||
// Inputs: None (although ip65_init should be called first)
|
||||
// Output: false if IP config has been sucesfully obtained and cfg_ip, cfg_netmask,
|
||||
// cfg_gateway and cfg_dns will be set per response from dhcp server.
|
||||
// dhcp_server will be set to address of server that provided configuration.
|
||||
// true if there was an error
|
||||
//
|
||||
bool dhcp_init(void);
|
||||
|
||||
// Access to IP configuration
|
||||
//
|
||||
// The five items below will be overwritten if dhcp_init is called.
|
||||
//
|
||||
extern uint32_t cfg_ip; // IP address of local machine
|
||||
extern uint32_t cfg_netmask; // Netmask of local network
|
||||
extern uint32_t cfg_gateway; // IP address of router on local network
|
||||
extern uint32_t cfg_dns; // IP address of DNS server to use
|
||||
extern uint32_t dhcp_server; // Address of DHCP server that config was obtained from
|
||||
|
||||
// Resolve a string containing a hostname (or a dotted quad) to an IP address
|
||||
//
|
||||
// Inputs: hostname: Zero terminated string containing either a DNS hostname
|
||||
// (e.g. "host.example.com") or an address in "dotted quad"
|
||||
// format (e.g. "192.168.1.0")
|
||||
// Output: IP address of the hostname, 0 on error
|
||||
//
|
||||
uint32_t __fastcall__ dns_resolve(const char* hostname);
|
||||
|
||||
// Send a ping (ICMP echo request) to a remote host, and wait for a response
|
||||
//
|
||||
// Inputs: dest: Destination IP address
|
||||
// Output: 0 if no response, otherwise time (in miliseconds) for host to respond
|
||||
//
|
||||
uint16_t __fastcall__ icmp_ping(uint32_t dest);
|
||||
|
||||
// Add a UDP listener
|
||||
//
|
||||
// Inputs: port: UDP port to listen on
|
||||
// callback: Vector to call when UDP packet arrives on specified port
|
||||
// Output: true if too may listeners already installed, false otherwise
|
||||
//
|
||||
bool __fastcall__ udp_add_listener(uint16_t port, void (*callback)(void));
|
||||
|
||||
// Remove a UDP listener
|
||||
//
|
||||
// Inputs: port: UDP port to stop listening on
|
||||
// Output: false if handler found and removed,
|
||||
// true if handler for specified port not found
|
||||
//
|
||||
bool __fastcall__ udp_remove_listener(uint16_t port);
|
||||
|
||||
// Access to received UDP packet
|
||||
//
|
||||
// Access to the four items below is only valid in the context of a callback
|
||||
// added with udp_add_listener.
|
||||
//
|
||||
extern uint8_t udp_recv_buf[1476]; // Buffer with data received
|
||||
uint16_t udp_recv_len(void); // Length of data received
|
||||
uint32_t udp_recv_src(void); // Source IP address
|
||||
uint16_t udp_recv_src_port(void); // Source port
|
||||
|
||||
// Send a UDP packet
|
||||
//
|
||||
// If the correct MAC address can't be found in the ARP cache then
|
||||
// an ARP request is sent - and the UDP packet is NOT sent. The caller
|
||||
// should wait a while calling ip65_process (to allow time for an ARP
|
||||
// response to arrive) and then call upd_send again. This behavior
|
||||
// makes sense as a UDP packet may get lost in transit at any time
|
||||
// so the caller should to be prepared to resend it after a while
|
||||
// anyway.
|
||||
//
|
||||
// Inputs: buf: Pointer to buffer containing data to be sent
|
||||
// len: Length of data to send (exclusive of any headers)
|
||||
// dest: Destination IP address
|
||||
// dest_port: Destination port
|
||||
// src_port: Source port
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool __fastcall__ udp_send(const uint8_t* buf, uint16_t len, uint32_t dest,
|
||||
uint16_t dest_port, uint16_t src_port);
|
||||
|
||||
// Listen for an inbound TCP connection
|
||||
//
|
||||
// This is a 'blocking' call, i.e. it will not return until a connection has been made.
|
||||
//
|
||||
// Inputs: port: TCP port to listen on
|
||||
// callback: Vector to call when data arrives on this connection
|
||||
// buf: Pointer to buffer with data received
|
||||
// len: -1 on close, otherwise length of data received
|
||||
// Output: IP address of the connected client, 0 on error
|
||||
//
|
||||
uint32_t __fastcall__ tcp_listen(uint16_t port,
|
||||
void __fastcall__ (*callback)(const uint8_t* buf,
|
||||
int16_t len));
|
||||
|
||||
// Make outbound TCP connection
|
||||
//
|
||||
// Inputs: dest: Destination IP address
|
||||
// dest_port: Destination port
|
||||
// callback: Vector to call when data arrives on this connection
|
||||
// buf: Pointer to buffer with data received
|
||||
// len: -1 on close, otherwise length of data received
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool __fastcall__ tcp_connect(uint32_t dest, uint16_t dest_port,
|
||||
void __fastcall__ (*callback)(const uint8_t* buf,
|
||||
int16_t len));
|
||||
|
||||
// Close the current TCP connection
|
||||
//
|
||||
// Inputs: None
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool tcp_close(void);
|
||||
|
||||
// Send data on the current TCP connection
|
||||
//
|
||||
// Inputs: buf: Pointer to buffer containing data to be sent
|
||||
// len: Length of data to send (up to 1460 bytes)
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool __fastcall__ tcp_send(const uint8_t* buf, uint16_t len);
|
||||
|
||||
// Send an empty ACK packet on the current TCP connection
|
||||
//
|
||||
// Inputs: None
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool tcp_send_keep_alive(void);
|
||||
|
||||
// Query an SNTP server for current UTC time
|
||||
//
|
||||
// Inputs: SNTP server IP address
|
||||
// Output: The number of seconds since 00:00 on Jan 1 1900 (UTC), 0 on error
|
||||
//
|
||||
uint32_t __fastcall__ sntp_get_time(uint32_t server);
|
||||
|
||||
// Download a file from a TFTP server and provide data to user supplied vector
|
||||
//
|
||||
// Inputs: server: IP address of server to receive file from
|
||||
// name: Zero terminated string containing the name of file to download
|
||||
// callback: Vector to call once for each 512 byte packet received
|
||||
// buf: Pointer to buffer containing data received
|
||||
// len: 512 if buffer is full, otherwise number of bytes
|
||||
// in the buffer
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool __fastcall__ tftp_download(uint32_t server, const char* name,
|
||||
void __fastcall__ (*callback)(const uint8_t* buf,
|
||||
uint16_t len));
|
||||
|
||||
// Download a file from a TFTP server and provide data to specified memory location
|
||||
//
|
||||
// Inputs: server: IP address of server to receive file from
|
||||
// name: Zero terminated string containing the name of file to download
|
||||
// buf: Pointer to buffer containing data received
|
||||
// Output: Length of data received, 0 on error
|
||||
//
|
||||
uint16_t __fastcall__ tftp_download_to_memory(uint32_t server, const char* name,
|
||||
const uint8_t* buf);
|
||||
|
||||
// Upload a file to a TFTP server with data retrieved from user supplied vector
|
||||
//
|
||||
// Inputs: server: IP address of server to send file to
|
||||
// name: Zero terminated string containing the name of file to upload
|
||||
// callback: Vector to call once for each 512 byte packet to be sent
|
||||
// buf: Pointer to buffer containing data to be sent
|
||||
// Output: 512 if buffer is full, otherwise number of bytes
|
||||
// in the buffer
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool __fastcall__ tftp_upload(uint32_t server, const char* name,
|
||||
uint16_t __fastcall__ (*callback)(const uint8_t* buf));
|
||||
|
||||
// Upload a file to a TFTP server with data retrieved from specified memory location
|
||||
//
|
||||
// Inputs: server: IP address of server to send file to
|
||||
// name: Zero terminated string containing the name of file to upload
|
||||
// buf: Pointer to buffer containing data to be sent
|
||||
// len: Length of data to be sent
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool __fastcall__ tftp_upload_from_memory(uint32_t server, const char* name,
|
||||
const uint8_t* buf, uint16_t len);
|
||||
|
||||
// Parse an HTTP URL into a form that makes it easy to retrieve the specified resource
|
||||
//
|
||||
// On success the variables url_ip, url_port and url_selector (see below) are valid.
|
||||
//
|
||||
// Inputs: url: Zero (or ctrl char) terminated string containing the URL
|
||||
// resolve: Resolve host in URL
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool __fastcall__ url_parse(const char* url, bool resolve);
|
||||
|
||||
// Access to parsed HTTP URL
|
||||
//
|
||||
// Access to the four items below is only valid after url_parse returned false.
|
||||
//
|
||||
extern char* url_host; // Zero terminated string containing host in URL + "\r\n\r\n"
|
||||
extern uint32_t url_ip; // IP address of host in URL (only if 'resolve' is true)
|
||||
extern uint16_t url_port; // Port number of URL
|
||||
extern char* url_selector; // Zero terminated string containing selector part of URL
|
||||
|
||||
// Download a resource specified by an HTTP URL
|
||||
//
|
||||
// The URL mustn't be longer than 1400 chars. The buffer is temporarily used to hold the
|
||||
// generated HTTP request so it should have a length of at least 1460 bytes. On success
|
||||
// the resource is zero terminated.
|
||||
//
|
||||
// Inputs: url: Zero (or ctrl char) terminated string containing the URL
|
||||
// buf: Pointer to a buffer that the resource will be downloaded into
|
||||
// len: Length of buffer
|
||||
// Output: Length of resource downloaded, 0 on error
|
||||
//
|
||||
uint16_t __fastcall__ url_download(const char* url, const uint8_t* buf, uint16_t len);
|
||||
|
||||
// Start an HTTP server
|
||||
//
|
||||
// This routine will stay in an endless loop that is broken only if user press the abort key.
|
||||
//
|
||||
// Inputs: port: TCP port to listen on
|
||||
// callback: Vector to call for each inbound HTTP request
|
||||
// client: IP address of the client that sent the request
|
||||
// method: Zero terminated string containing the HTTP method
|
||||
// path: Zero terminated string containing the HTTP path
|
||||
// Output: None
|
||||
//
|
||||
void __fastcall__ httpd_start(uint16_t port,
|
||||
void __fastcall__ (*callback)(uint32_t client,
|
||||
const char* method,
|
||||
const char* path));
|
||||
|
||||
// HTTP response types
|
||||
//
|
||||
#define HTTPD_RESPONSE_NOHEADER 0 // No HTTP response header
|
||||
#define HTTPD_RESPONSE_200_TEXT 1 // HTTP Code: 200 OK, Content Type: 'text/text'
|
||||
#define HTTPD_RESPONSE_200_HTML 2 // HTTP Code: 200 OK, Content Type: 'text/html'
|
||||
#define HTTPD_RESPONSE_200_DATA 3 // HTTP Code: 200 OK, Content Type: 'application/octet-stream'
|
||||
#define HTTPD_RESPONSE_404 4 // HTTP Code: 404 Not Found
|
||||
#define HTTPD_RESPONSE_500 5 // HTTP Code: 500 System Error
|
||||
|
||||
// Send HTTP response
|
||||
//
|
||||
// Calling httpd_send_response is only valid in the context of a httpd_start callback.
|
||||
// For the response types HTTPD_RESPONSE_404 and HTTPD_RESPONSE_500 'buf' is ignored.
|
||||
// With the response type HTTPD_RESPONSE_NOHEADER it's possible to add more content to
|
||||
// an already sent HTTP response.
|
||||
//
|
||||
// Inputs: response_type: Value describing HTTP code and content type in response header
|
||||
// buf: Pointer to buffer with HTTP response content
|
||||
// len: Length of buffer with HTTP response content
|
||||
// Output: None
|
||||
//
|
||||
void __fastcall__ httpd_send_response(uint8_t response_type,
|
||||
const uint8_t* buf, uint16_t len);
|
||||
|
||||
// Retrieve the value of a variable defined in the previously received HTTP request
|
||||
//
|
||||
// Calling http_get_value is only valid in the context of a httpd_start callback.
|
||||
// Only the first letter in a variable name is significant. E.g. if a querystring contains
|
||||
// the variables 'a','alpha' and 'alabama', then only the first one will be retrievable.
|
||||
//
|
||||
// Inputs: name: Variable to retrieve
|
||||
// Output: Variable value (zero terminated string) if variable exists, null otherwise.
|
||||
//
|
||||
char* __fastcall__ http_get_value(char name);
|
||||
|
||||
// Get number of milliseconds since initialization
|
||||
//
|
||||
// Inputs: None
|
||||
// Output: Current number of milliseconds
|
||||
//
|
||||
uint16_t timer_read(void);
|
||||
|
||||
// Check if specified period of time has passed yet
|
||||
//
|
||||
// Inputs: time: Number of milliseconds we are willing to wait for
|
||||
// Output: true if timeout occured, false otherwise
|
||||
//
|
||||
bool __fastcall__ timer_timeout(uint16_t time);
|
||||
|
||||
// Check whether the abort key is being pressed
|
||||
//
|
||||
// Inputs: None
|
||||
// Output: true if abort key pressed, false otherwise
|
||||
//
|
||||
bool input_check_for_abort_key(void);
|
||||
|
||||
// Control abort key
|
||||
//
|
||||
// Control if the user can abort blocking functions with the abort key
|
||||
// (making them return IP65_ERROR_ABORTED_BY_USER). Initially the abort
|
||||
// key is enabled.
|
||||
//
|
||||
// Inputs: enable: false to disable the key, true to enable the key
|
||||
// Output: None
|
||||
//
|
||||
void __fastcall__ input_set_abort_key(bool enable);
|
||||
|
||||
// Access to actual abort key code
|
||||
//
|
||||
extern uint8_t abort_key;
|
||||
|
||||
#endif
|
@ -0,0 +1,84 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#include <conio.h>
|
||||
#include <tgi.h>
|
||||
#include <apple2.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "map.h"
|
||||
#include "satellite.h"
|
||||
#include "osd.h"
|
||||
#include "ip65.h"
|
||||
|
||||
unsigned char net = ETH_INIT_DEFAULT;
|
||||
char lon_s[16], lat_s[16];
|
||||
int lat, lon;
|
||||
long timer;
|
||||
unsigned long ts;
|
||||
|
||||
void error_exit(char *op)
|
||||
{
|
||||
printf("%s:%s\n",op,ip65_strerror(ip65_error));
|
||||
cgetc();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
int f;
|
||||
f = open("ethernet.slot",O_RDONLY);
|
||||
if (f!=-1)
|
||||
{
|
||||
read(f,&net,sizeof(net));
|
||||
close(f);
|
||||
net &= ~'0';
|
||||
}
|
||||
|
||||
if (ip65_init(net))
|
||||
error_exit("ip65_init");
|
||||
|
||||
if (dhcp_init())
|
||||
error_exit("dhcp_init");
|
||||
|
||||
tgi_install(tgi_static_stddrv);
|
||||
tgi_init();
|
||||
tgi_apple2_mix(true);
|
||||
tgi_clear();
|
||||
|
||||
while (1)
|
||||
{
|
||||
timer=524088;
|
||||
clrscr();
|
||||
satellite_fetch(&lon,&lat,lon_s,lat_s,&ts);
|
||||
map();
|
||||
osd(lon_s,lat_s,ts);
|
||||
satellite(lon,lat);
|
||||
|
||||
while (timer>0)
|
||||
{
|
||||
if (kbhit())
|
||||
switch(cgetc())
|
||||
{
|
||||
case 0x1b:
|
||||
return;
|
||||
case 0x0D:
|
||||
case 0x0A:
|
||||
timer=0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
timer--;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#ifndef MAP_H
|
||||
#define MAP_H
|
||||
|
||||
void map(void);
|
||||
|
||||
#endif /* MAP_H */
|
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#ifndef OSD_H
|
||||
#define OSD_H
|
||||
|
||||
void osd(char *lon, char *lat, unsigned long ts);
|
||||
|
||||
#endif /* OSD_H */
|
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#define CENTER_X 4
|
||||
#define CENTER_Y 4
|
||||
|
||||
#include <apple2.h>
|
||||
#include <tgi.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <conio.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include "satellite.h"
|
||||
#include "ip65.h"
|
||||
|
||||
const unsigned char _satellite[8] = {
|
||||
0x20, /* ..X.|.... */
|
||||
0x50, /* .X.X|.... */
|
||||
0xA4, /* X.X.|.X.. */
|
||||
0x58, /* .X.X|X... */
|
||||
0x1A, /* ...X|X.X. */
|
||||
0x05, /* ....|.X.X */
|
||||
0x0A, /* ....|X.X. */
|
||||
0x04, /* ....|.X.. */
|
||||
};
|
||||
|
||||
// TODO: These tables are broken, recalculate them!
|
||||
|
||||
unsigned char xpos[360] =
|
||||
{ 0,0,1,2,3,3,4,5,6,7,7,8,9,10,10,11,12,13,14,14,15,16,17,17,18,19,20,21,21,22,23,24,24,25,26,27,28,28,29,30,31,31,32,33,34,35,35,36,37,38,38,39,40,41,42,42,43,44,45,45,46,47,48,49,49,50,51,52,52,53,54,55,56,56,57,58,59,59,60,61,62,63,63,64,65,66,66,67,68,69,70,70,71,72,73,73,74,75,76,77,77,78,79,80,80,81,82,83,84,84,85,86,87,87,88,89,90,91,91,92,93,94,94,95,96,97,98,98,99,100,101,101,102,103,104,105,105,106,107,108,108,109,110,111,112,112,113,114,115,115,116,117,118,119,119,120,121,122,122,123,124,125,126,126,127,128,129,129,130,131,132,133,133,134,135,136,136,137,138,139,140,140,141,142,143,143,144,145,146,147,147,148,149,150,150,151,152,153,154,154,155,156,157,157,158,159,160,161,161,162,163,164,164,165,166,167,168,168,169,170,171,171,172,173,174,175,175,176,177,178,178,179,180,181,182,182,183,184,185,185,186,187,188,189,189,190,191,192,192,193,194,195,196,196,197,198,199,199,200,201,202,203,203,204,205,206,206,207,208,209,210,210,211,212,213,213,214,215,216,217,217,218,219,220,220,221,222,223,224,224,225,226,227,227,228,229,230,231,231,232,233,234,234,235,236,237,238,238,239,240,241,241,242,243,244,245,245,246,247,248,248,249,250,251,252,252,253,254,255,255,0,1,2,3,3,4,5,6,6,7,8,9,10,10,11,12,13,13,14,15,16,17,17,18,19,20,20,21,22,23, };
|
||||
|
||||
unsigned char ypos[360] =
|
||||
{ 0,0,0,1,1,2,2,3,3,4,4,4,5,5,6,6,7,7,8,8,8,9,9,10,10,11,11,12,12,12,13,13,14,14,15,15,16,16,16,17,17,18,18,19,19,20,20,20,21,21,22,22,23,23,24,24,24,25,25,26,26,27,27,28,28,28,29,29,30,30,31,31,32,32,32,33,33,34,34,35,35,36,36,36,37,37,38,38,39,39,40,40,40,41,41,42,42,43,43,44,44,44,45,45,46,46,47,47,48,48,48,49,49,50,50,51,51,52,52,52,53,53,54,54,55,55,56,56,56,57,57,58,58,59,59,60,60,60,61,61,62,62,63,63,64,64,64,65,65,66,66,67,67,68,68,68,69,69,70,70,71,71,72,72,72,73,73,74,74,75,75,76,76,76,77,77,78,78,79,79,80,80,80,81,81,82,82,83,83,84,84,84,85,85,86,86,87,87,88,88,88,89,89,90,90,91,91,92,92,92,93,93,94,94,95,95,96,96,96,97,97,98,98,99,99,100,100,100,101,101,102,102,103,103,104,104,104,105,105,106,106,107,107,108,108,108,109,109,110,110,111,111,112,112,112,113,113,114,114,115,115,116,116,116,117,117,118,118,119,119,120,120,120,121,121,122,122,123,123,124,124,124,125,125,126,126,127,127,128,128,128,129,129,130,130,131,131,132,132,132,133,133,134,134,135,135,136,136,136,137,137,138,138,139,139,140,140,140,141,141,142,142,143,143,144,144,144,145,145,146,146,147,147,148,148,148,149,149,150,150,151,151,152,152,152,153,153,154,154,155,155,156,156,156,157,157,158,158,159,159, };
|
||||
|
||||
const char url[]="HTTP://api.open-notify.org/iss-now.json";
|
||||
const char fmt[]="{\"iss_position\": {\"latitude\": \"%s \"longitude\": \"%s \"timestamp\": %ld, \"message\": \"success\"}";
|
||||
|
||||
char download[1024];
|
||||
|
||||
int post_proc(char *s)
|
||||
{
|
||||
char *c = strchr(s,'"');
|
||||
*c = 0;
|
||||
return atoi(s);
|
||||
}
|
||||
|
||||
bool satellite_fetch(int *lon, int *lat, char *lon_s, char *lat_s, unsigned long *ts)
|
||||
{
|
||||
char *bdy;
|
||||
|
||||
memset(lon_s,0,16);
|
||||
memset(lat_s,0,16);
|
||||
|
||||
if (!url_download(url,(uint8_t*)download,sizeof(download)))
|
||||
return false;
|
||||
|
||||
bdy=strstr(download,"\r\n\r\n");
|
||||
if (!bdy)
|
||||
return false;
|
||||
bdy += 4;
|
||||
|
||||
if (sscanf(bdy,fmt,lon_s,lat_s,ts)!=3)
|
||||
return false;
|
||||
|
||||
*lon = post_proc(lon_s);
|
||||
*lat = post_proc(lat_s);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void satellite(int lon, int lat)
|
||||
{
|
||||
unsigned char x = xpos[lon + 180] - CENTER_X;
|
||||
unsigned char y = ypos[lat + 180] - CENTER_Y;
|
||||
unsigned char i,j;
|
||||
int8_t b;
|
||||
|
||||
for (i=0;i<8;i++)
|
||||
{
|
||||
b=_satellite[i];
|
||||
for (j=0;j<16;j+=2)
|
||||
{
|
||||
if (b < 0)
|
||||
tgi_setcolor(TGI_COLOR_WHITE2);
|
||||
else
|
||||
tgi_setcolor(TGI_COLOR_BLACK2);
|
||||
tgi_setpixel(x+j,y+i);
|
||||
tgi_setpixel(x+j+1,y+i);
|
||||
b <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#ifndef SATELLITE_H
|
||||
#define SATELLITE_H
|
||||
|
||||
void satellite(int lon, int lat);
|
||||
bool satellite_fetch(int *lon, int *lat, char *lon_s, char *lat_s, unsigned long *ts);
|
||||
|
||||
#endif /* SATELLITE_H */
|
@ -0,0 +1,87 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <conio.h>
|
||||
#include <peekpoke.h>
|
||||
|
||||
//#include "globals.h"
|
||||
#include "apple2idiot.h"
|
||||
//#include "../../../../arduino-lib/Apple2Idiot/A2I_commands.h"
|
||||
|
||||
#define MAX_STR_LEN 250
|
||||
|
||||
#define CARD_ADDRESS 0xC200
|
||||
#define APPLE_COMMAND_ADDRESS 0xC201
|
||||
#define RAM_DATA_START_ADDRESS 0xC202
|
||||
#define ESP_TIMEOUT 5555
|
||||
#define ACK 6 // Acknowledge
|
||||
#define APP_ID = 202
|
||||
|
||||
unsigned int read_byte(unsigned int address) {
|
||||
unsigned int b = 0;
|
||||
b = PEEK(address);
|
||||
//printf("read_data(%u)", address);
|
||||
return b;
|
||||
}
|
||||
|
||||
unsigned char write_byte(unsigned int address, unsigned char byte_to_write) {
|
||||
//printf("%u <- %d, [%c]\n", address, byte_to_write, byte_to_write);
|
||||
POKE(address, byte_to_write);
|
||||
}
|
||||
|
||||
unsigned char write_byte_wait_for_ack(unsigned int address, unsigned char byte_to_write) {
|
||||
unsigned char received_esp_response = 0;
|
||||
int timeout_count = 0;
|
||||
unsigned char timeout_happened = 0;
|
||||
int delay_count = 0;
|
||||
unsigned char read_char;
|
||||
write_byte(address, byte_to_write);
|
||||
while ((received_esp_response==0) || (timeout_happened==0)) {
|
||||
timeout_count++;
|
||||
if (timeout_count > ESP_TIMEOUT) {
|
||||
timeout_happened = 1;
|
||||
return 0;
|
||||
}
|
||||
//read_char = read_byte(ESP_COMMAND_ADDRESS);
|
||||
read_char = read_byte(APPLE_COMMAND_ADDRESS);
|
||||
if (read_char == ACK) {
|
||||
received_esp_response = 1;
|
||||
return 1;
|
||||
}
|
||||
for (delay_count=0; delay_count < 1111; ++delay_count) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char* write_string_to_ram(unsigned int address, char* string_to_send) {
|
||||
unsigned char i;
|
||||
unsigned char size = strlen(string_to_send);
|
||||
//gotoxy(0,2);
|
||||
if (string_to_send[size-1] == '\n') {
|
||||
string_to_send[size-1] = '\0';
|
||||
}
|
||||
//printf("%u (%s)\n", address, string_to_send);
|
||||
for (i=0; i<size; i++) {
|
||||
write_byte(address+i, string_to_send[i]);
|
||||
}
|
||||
if (string_to_send[size-1] != '\0') {
|
||||
write_byte(address+i, '\0');
|
||||
}
|
||||
}
|
||||
|
||||
// HOW DO I PASS THE ADDRESS TO read_string_from_ram ???
|
||||
|
||||
void read_string_from_ram(unsigned int address, char *data, char length) {
|
||||
unsigned char c, i;
|
||||
//gotoxy(0,0);
|
||||
//printf("A: %u, L: %u\n", address, length);
|
||||
//cgetc();
|
||||
for (i=0; i<length; i++) {
|
||||
c = PEEK(address + i);
|
||||
//printf("PEEK[%u]: %c\n", i, c);
|
||||
data[i] = c;
|
||||
if (c == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
#ifndef _A2I_H
|
||||
#define _A2I_H
|
||||
|
||||
unsigned int read_byte(unsigned int address);
|
||||
unsigned char write_byte(unsigned int address, unsigned char byte_to_write);
|
||||
unsigned char* write_string_to_ram(unsigned int address, char* string_to_send);
|
||||
void read_string_from_ram(unsigned int address, char *data, char length);
|
||||
unsigned char write_byte_wait_for_ack(unsigned int address, unsigned char byte_to_write);
|
||||
|
||||
#endif
|
70
examples/20-multiapp-arduino/iss-tracker/apple2/src/main.c
Normal file
70
examples/20-multiapp-arduino/iss-tracker/apple2/src/main.c
Normal file
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#include <conio.h>
|
||||
#include <tgi.h>
|
||||
#include <apple2.h>
|
||||
#include <stdbool.h>
|
||||
#include "map.h"
|
||||
#include "satellite.h"
|
||||
#include "osd.h"
|
||||
//#include "sp.h"
|
||||
#include "apple2idiot.h"
|
||||
|
||||
#define CARD_ADDRESS 0xC200
|
||||
#define APPLE_COMMAND_ADDRESS 0xC201
|
||||
#define RAM_DATA_START_ADDRESS 0xC202
|
||||
#define ESP_TIMEOUT 5555
|
||||
#define ACK 6 // Acknowledge
|
||||
#define APP_ID = 202
|
||||
|
||||
//unsigned char net;
|
||||
char lon_s[16], lat_s[16];
|
||||
int lat, lon;
|
||||
long timer;
|
||||
unsigned long ts;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
//sp_init();
|
||||
//net = sp_find_network();
|
||||
tgi_install(tgi_static_stddrv);
|
||||
tgi_init();
|
||||
tgi_apple2_mix(true);
|
||||
tgi_clear();
|
||||
|
||||
write_byte(APPLE_COMMAND_ADDRESS, 202);
|
||||
|
||||
while (1)
|
||||
{
|
||||
timer=524088;
|
||||
clrscr();
|
||||
satellite_fetch(&lon,&lat,&lon_s,&lat_s,&ts);
|
||||
map();
|
||||
osd(lon_s,lat_s,ts);
|
||||
satellite(lon,lat);
|
||||
|
||||
while (timer>0)
|
||||
{
|
||||
if (kbhit())
|
||||
switch(cgetc())
|
||||
{
|
||||
case 0x1b:
|
||||
return;
|
||||
case 0x0D:
|
||||
case 0x0A:
|
||||
timer=0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
timer--;
|
||||
}
|
||||
}
|
||||
}
|
31
examples/20-multiapp-arduino/iss-tracker/apple2/src/map.c
Normal file
31
examples/20-multiapp-arduino/iss-tracker/apple2/src/map.c
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
#include <apple2.h>
|
||||
#include <6502.h>
|
||||
#include <peekpoke.h>
|
||||
#include <conio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
void map(void)
|
||||
{
|
||||
int f = open("MAP.HGR",O_RDONLY);
|
||||
|
||||
if (f==-1)
|
||||
{
|
||||
perror("map open");
|
||||
cgetc();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
read(f,(void *)0x2000,0x2000);
|
||||
close(f);
|
||||
}
|
14
examples/20-multiapp-arduino/iss-tracker/apple2/src/map.h
Normal file
14
examples/20-multiapp-arduino/iss-tracker/apple2/src/map.h
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#ifndef MAP_H
|
||||
#define MAP_H
|
||||
|
||||
void map(void);
|
||||
|
||||
#endif /* MAP_H */
|
18
examples/20-multiapp-arduino/iss-tracker/apple2/src/osd.c
Normal file
18
examples/20-multiapp-arduino/iss-tracker/apple2/src/osd.c
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#include <conio.h>
|
||||
#include <apple2.h>
|
||||
#include <time.h>
|
||||
|
||||
void osd(char *lon, char *lat,unsigned long ts)
|
||||
{
|
||||
cprintf(" ** CURRENT ISS POSITION **\r\n");
|
||||
cprintf(" LON: %-14s LAT: %-14s",lon,lat);
|
||||
cprintf(" AS OF: %s",ctime(&ts));
|
||||
}
|
14
examples/20-multiapp-arduino/iss-tracker/apple2/src/osd.h
Normal file
14
examples/20-multiapp-arduino/iss-tracker/apple2/src/osd.h
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#ifndef OSD_H
|
||||
#define OSD_H
|
||||
|
||||
void osd(char *lon, char *lat, unsigned long ts);
|
||||
|
||||
#endif /* OSD_H */
|
116
examples/20-multiapp-arduino/iss-tracker/apple2/src/satellite.c
Normal file
116
examples/20-multiapp-arduino/iss-tracker/apple2/src/satellite.c
Normal file
@ -0,0 +1,116 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#define CENTER_X 4
|
||||
#define CENTER_Y 4
|
||||
|
||||
#define APPLE_COMMAND_ADDRESS 0xC201
|
||||
#define RAM_DATA_START_ADDRESS 0xC202
|
||||
|
||||
#include <apple2.h>
|
||||
#include <tgi.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <conio.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include "satellite.h"
|
||||
#include "apple2idiot.h"
|
||||
//#include "sp.h"
|
||||
|
||||
//extern unsigned char net; // Network device as found by sp_find_network()
|
||||
|
||||
const unsigned char _satellite[8] = {
|
||||
0x20, /* ..X.|.... */
|
||||
0x50, /* .X.X|.... */
|
||||
0xA4, /* X.X.|.X.. */
|
||||
0x58, /* .X.X|X... */
|
||||
0x1A, /* ...X|X.X. */
|
||||
0x05, /* ....|.X.X */
|
||||
0x0A, /* ....|X.X. */
|
||||
0x04, /* ....|.X.. */
|
||||
};
|
||||
|
||||
// TODO: These tables are broken, recalculate them!
|
||||
|
||||
unsigned char xpos[360] =
|
||||
{ 0,0,1,2,3,3,4,5,6,7,7,8,9,10,10,11,12,13,14,14,15,16,17,17,18,19,20,21,21,22,23,24,24,25,26,27,28,28,29,30,31,31,32,33,34,35,35,36,37,38,38,39,40,41,42,42,43,44,45,45,46,47,48,49,49,50,51,52,52,53,54,55,56,56,57,58,59,59,60,61,62,63,63,64,65,66,66,67,68,69,70,70,71,72,73,73,74,75,76,77,77,78,79,80,80,81,82,83,84,84,85,86,87,87,88,89,90,91,91,92,93,94,94,95,96,97,98,98,99,100,101,101,102,103,104,105,105,106,107,108,108,109,110,111,112,112,113,114,115,115,116,117,118,119,119,120,121,122,122,123,124,125,126,126,127,128,129,129,130,131,132,133,133,134,135,136,136,137,138,139,140,140,141,142,143,143,144,145,146,147,147,148,149,150,150,151,152,153,154,154,155,156,157,157,158,159,160,161,161,162,163,164,164,165,166,167,168,168,169,170,171,171,172,173,174,175,175,176,177,178,178,179,180,181,182,182,183,184,185,185,186,187,188,189,189,190,191,192,192,193,194,195,196,196,197,198,199,199,200,201,202,203,203,204,205,206,206,207,208,209,210,210,211,212,213,213,214,215,216,217,217,218,219,220,220,221,222,223,224,224,225,226,227,227,228,229,230,231,231,232,233,234,234,235,236,237,238,238,239,240,241,241,242,243,244,245,245,246,247,248,248,249,250,251,252,252,253,254,255,255,0,1,2,3,3,4,5,6,6,7,8,9,10,10,11,12,13,13,14,15,16,17,17,18,19,20,20,21,22,23, };
|
||||
|
||||
unsigned char ypos[360] =
|
||||
{ 0,0,0,1,1,2,2,3,3,4,4,4,5,5,6,6,7,7,8,8,8,9,9,10,10,11,11,12,12,12,13,13,14,14,15,15,16,16,16,17,17,18,18,19,19,20,20,20,21,21,22,22,23,23,24,24,24,25,25,26,26,27,27,28,28,28,29,29,30,30,31,31,32,32,32,33,33,34,34,35,35,36,36,36,37,37,38,38,39,39,40,40,40,41,41,42,42,43,43,44,44,44,45,45,46,46,47,47,48,48,48,49,49,50,50,51,51,52,52,52,53,53,54,54,55,55,56,56,56,57,57,58,58,59,59,60,60,60,61,61,62,62,63,63,64,64,64,65,65,66,66,67,67,68,68,68,69,69,70,70,71,71,72,72,72,73,73,74,74,75,75,76,76,76,77,77,78,78,79,79,80,80,80,81,81,82,82,83,83,84,84,84,85,85,86,86,87,87,88,88,88,89,89,90,90,91,91,92,92,92,93,93,94,94,95,95,96,96,96,97,97,98,98,99,99,100,100,100,101,101,102,102,103,103,104,104,104,105,105,106,106,107,107,108,108,108,109,109,110,110,111,111,112,112,112,113,113,114,114,115,115,116,116,116,117,117,118,118,119,119,120,120,120,121,121,122,122,123,123,124,124,124,125,125,126,126,127,127,128,128,128,129,129,130,130,131,131,132,132,132,133,133,134,134,135,135,136,136,136,137,137,138,138,139,139,140,140,140,141,141,142,142,143,143,144,144,144,145,145,146,146,147,147,148,148,148,149,149,150,150,151,151,152,152,152,153,153,154,154,155,155,156,156,156,157,157,158,158,159,159, };
|
||||
|
||||
const char url[]="N:HTTP://api.open-notify.org/iss-now.json";
|
||||
const char longitude_query[]="/iss_position/longitude";
|
||||
const char latitude_query[]="/iss_position/latitude";
|
||||
const char timestamp_query[]="/timestamp";
|
||||
|
||||
int post_proc(char *s)
|
||||
{
|
||||
char *c = strchr(s,'"');
|
||||
*c = 0;
|
||||
return atoi(s);
|
||||
}
|
||||
|
||||
bool satellite_fetch(int *lon, int *lat, char *lon_s, char *lat_s, unsigned long *ts)
|
||||
{
|
||||
//unsigned short len;
|
||||
char ts_s[16];
|
||||
unsigned int address_offset = 0;
|
||||
|
||||
//gotoxy(0,0);
|
||||
|
||||
memset(lon_s,0,16);
|
||||
memset(lat_s,0,16);
|
||||
|
||||
write_byte_wait_for_ack(APPLE_COMMAND_ADDRESS, 20);
|
||||
|
||||
address_offset = 0;
|
||||
read_string_from_ram(RAM_DATA_START_ADDRESS + address_offset, lat_s, 9);
|
||||
address_offset += strlen(lat_s) + 1;
|
||||
read_string_from_ram(RAM_DATA_START_ADDRESS + address_offset, lon_s, 9);
|
||||
address_offset += strlen(lon_s) + 1;
|
||||
read_string_from_ram(RAM_DATA_START_ADDRESS + address_offset, ts_s, 9);
|
||||
|
||||
*ts=atol(ts_s);
|
||||
|
||||
//clrscr();
|
||||
//cprintf(" ** CURRENT ISS POSITION **\r\n");
|
||||
//cprintf(" LON: %-14s LAT: %-14s",lon_s,lat_s);
|
||||
//cprintf(" TS: %-14s",ts_s);
|
||||
//cprintf(" AS OF: %s",ctime(ts));
|
||||
|
||||
*lon=atoi(lon_s);
|
||||
*lat=atoi(lat_s);
|
||||
*ts=atol(ts_s);
|
||||
|
||||
return true; // todo come back here and add error handling.
|
||||
}
|
||||
|
||||
void satellite(int lon, int lat)
|
||||
{
|
||||
unsigned char x = xpos[lon + 180] - CENTER_X;
|
||||
unsigned char y = ypos[lat + 180] - CENTER_Y;
|
||||
unsigned char i,j;
|
||||
int8_t b;
|
||||
for (i=0;i<8;i++)
|
||||
{
|
||||
b=_satellite[i];
|
||||
for (j=0;j<16;j+=2)
|
||||
{
|
||||
if (b < 0)
|
||||
tgi_setcolor(TGI_COLOR_WHITE2);
|
||||
else
|
||||
tgi_setcolor(TGI_COLOR_BLACK2);
|
||||
tgi_setpixel(x+j,y+i);
|
||||
tgi_setpixel(x+j+1,y+i);
|
||||
b <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#ifndef SATELLITE_H
|
||||
#define SATELLITE_H
|
||||
|
||||
void satellite(int lon, int lat);
|
||||
bool satellite_fetch(int *lon, int *lat, char *lon_s, char *lat_s, unsigned long *ts);
|
||||
|
||||
#endif /* SATELLITE_H */
|
365
examples/20-multiapp-arduino/iss-tracker/apple2/src/sp.c
Normal file
365
examples/20-multiapp-arduino/iss-tracker/apple2/src/sp.c
Normal file
@ -0,0 +1,365 @@
|
||||
#ifdef BUILD_APPLE2
|
||||
/**
|
||||
* FujiNet CONFIG for #Apple2
|
||||
*
|
||||
* SmartPort MLI Routines
|
||||
*/
|
||||
|
||||
#ifdef __INTELLISENSE__
|
||||
// 18, expect closing parenthses - needed to use cc65 inline asm command with agruments.
|
||||
#pragma diag_suppress 18
|
||||
#endif
|
||||
|
||||
|
||||
#include "sp.h"
|
||||
#include <conio.h>
|
||||
#include <stdio.h>
|
||||
#include <apple2.h>
|
||||
#include <peekpoke.h>
|
||||
|
||||
#define SP_CMD_STATUS 0
|
||||
#define SP_CMD_CONTROL 4
|
||||
#define SP_CMD_OPEN 6
|
||||
#define SP_CMD_CLOSE 7
|
||||
#define SP_CMD_READ 8
|
||||
#define SP_CMD_WRITE 9
|
||||
#define SP_STATUS_PARAM_COUNT 3
|
||||
#define SP_CONTROL_PARAM_COUNT 3
|
||||
#define SP_OPEN_PARAM_COUNT 1
|
||||
#define SP_CLOSE_PARAM_COUNT 1
|
||||
#define SP_READ_PARAM_COUNT 4
|
||||
#define SP_WRITE_PARAM_COUNT 4
|
||||
|
||||
// extern globals:
|
||||
uint8_t sp_payload[1024];
|
||||
uint16_t sp_count;
|
||||
uint8_t sp_dest;
|
||||
uint16_t sp_dispatch;
|
||||
uint8_t sp_error;
|
||||
|
||||
static uint8_t sp_cmdlist[10];
|
||||
static uint8_t sp_cmdlist_low, sp_cmdlist_high;
|
||||
static uint8_t sp_err, sp_rtn_low, sp_rtn_high;
|
||||
|
||||
int8_t sp_status(uint8_t dest, uint8_t statcode)
|
||||
{
|
||||
sp_error = 0;
|
||||
// build the command list
|
||||
sp_cmdlist[0] = SP_STATUS_PARAM_COUNT;
|
||||
sp_cmdlist[1] = dest; // set before calling sp_status();
|
||||
sp_cmdlist[2] = (uint8_t)((uint16_t)&sp_payload & 0x00FF);
|
||||
sp_cmdlist[3] = (uint8_t)((uint16_t)&sp_payload >> 8) & 0xFF;
|
||||
sp_cmdlist[4] = statcode;
|
||||
|
||||
sp_cmdlist_low = (uint8_t)((uint16_t)&sp_cmdlist & 0x00FF);
|
||||
sp_cmdlist_high = (uint8_t)((uint16_t)&sp_cmdlist >> 8) & 0xFF;
|
||||
|
||||
|
||||
// store cmd list
|
||||
__asm__ volatile ("lda #%b", SP_CMD_STATUS);
|
||||
__asm__ volatile ("sta %g", spCmd); // store status command #
|
||||
__asm__ volatile ("lda %v", sp_cmdlist_low);
|
||||
__asm__ volatile ("sta %g", spCmdListLow); // store status command #
|
||||
__asm__ volatile ("lda %v", sp_cmdlist_high);
|
||||
__asm__ volatile ("sta %g", spCmdListHigh); // store status command #
|
||||
|
||||
__asm__ volatile ("jsr $C50D"); // to do - find SP entry point using algorithm from firmware reference
|
||||
spCmd:
|
||||
__asm__ volatile ("nop");
|
||||
spCmdListLow:
|
||||
__asm__ volatile ("nop");
|
||||
spCmdListHigh:
|
||||
__asm__ volatile ("nop");
|
||||
__asm__ volatile ("stx %v", sp_rtn_low);
|
||||
__asm__ volatile ("sty %v", sp_rtn_high);
|
||||
__asm__ volatile ("sta %v", sp_err);
|
||||
|
||||
sp_count = ((uint16_t)sp_rtn_high << 8) | (uint16_t)sp_rtn_low;
|
||||
sp_error = sp_err;
|
||||
return sp_err;
|
||||
}
|
||||
|
||||
int8_t sp_control(uint8_t dest, uint8_t ctrlcode)
|
||||
{
|
||||
sp_error = 0;
|
||||
// sp_dest = 5; // need to search
|
||||
// build the command list
|
||||
sp_cmdlist[0] = SP_CONTROL_PARAM_COUNT;
|
||||
sp_cmdlist[1] = dest; // set before calling sp_status();
|
||||
sp_cmdlist[2] = (uint8_t)((uint16_t)&sp_payload & 0x00FF);
|
||||
sp_cmdlist[3] = (uint8_t)((uint16_t)&sp_payload >> 8) & 0xFF;
|
||||
sp_cmdlist[4] = ctrlcode;
|
||||
|
||||
sp_cmdlist_low = (uint8_t)((uint16_t)&sp_cmdlist & 0x00FF);
|
||||
sp_cmdlist_high = (uint8_t)((uint16_t)&sp_cmdlist >> 8) & 0xFF;
|
||||
|
||||
// store cmd list
|
||||
__asm__ volatile ("lda #%b", SP_CMD_CONTROL);
|
||||
__asm__ volatile ("sta %g", spCmd); // store status command #
|
||||
__asm__ volatile ("lda %v", sp_cmdlist_low);
|
||||
__asm__ volatile ("sta %g", spCmdListLow); // store status command #
|
||||
__asm__ volatile ("lda %v", sp_cmdlist_high);
|
||||
__asm__ volatile ("sta %g", spCmdListHigh); // store status command #
|
||||
|
||||
__asm__ volatile ("jsr $C50D"); // to do - find entry point and used it instead of hardcoded address
|
||||
spCmd:
|
||||
__asm__ volatile ("nop");
|
||||
spCmdListLow:
|
||||
__asm__ volatile ("nop");
|
||||
spCmdListHigh:
|
||||
__asm__ volatile ("nop");
|
||||
__asm__ volatile ("sta %v", sp_err);
|
||||
sp_error = sp_err;
|
||||
return sp_err;
|
||||
}
|
||||
|
||||
int8_t sp_open(uint8_t dest)
|
||||
{
|
||||
sp_error = 0;
|
||||
// sp_dest = 5; // need to search
|
||||
// build the command list
|
||||
sp_cmdlist[0] = SP_OPEN_PARAM_COUNT;
|
||||
sp_cmdlist[1] = dest; // set before calling sp_status();
|
||||
|
||||
sp_cmdlist_low = (uint8_t)((uint16_t)&sp_cmdlist & 0x00FF);
|
||||
sp_cmdlist_high = (uint8_t)((uint16_t)&sp_cmdlist >> 8) & 0xFF;
|
||||
|
||||
// store cmd list
|
||||
__asm__ volatile ("lda #%b", SP_CMD_OPEN);
|
||||
__asm__ volatile ("sta %g", spCmd); // store status command #
|
||||
__asm__ volatile ("lda %v", sp_cmdlist_low);
|
||||
__asm__ volatile ("sta %g", spCmdListLow); // store status command #
|
||||
__asm__ volatile ("lda %v", sp_cmdlist_high);
|
||||
__asm__ volatile ("sta %g", spCmdListHigh); // store status command #
|
||||
|
||||
__asm__ volatile ("jsr $C50D"); // to do - find entry point and used it instead of hardcoded address
|
||||
spCmd:
|
||||
__asm__ volatile ("nop");
|
||||
spCmdListLow:
|
||||
__asm__ volatile ("nop");
|
||||
spCmdListHigh:
|
||||
__asm__ volatile ("nop");
|
||||
__asm__ volatile ("sta %v", sp_err);
|
||||
sp_error = sp_err;
|
||||
return sp_err;
|
||||
}
|
||||
|
||||
int8_t sp_close(uint8_t dest)
|
||||
{
|
||||
sp_error = 0;
|
||||
// sp_dest = 5; // need to search
|
||||
// build the command list
|
||||
sp_cmdlist[0] = SP_CLOSE_PARAM_COUNT;
|
||||
sp_cmdlist[1] = dest; // set before calling sp_status();
|
||||
|
||||
sp_cmdlist_low = (uint8_t)((uint16_t)&sp_cmdlist & 0x00FF);
|
||||
sp_cmdlist_high = (uint8_t)((uint16_t)&sp_cmdlist >> 8) & 0xFF;
|
||||
|
||||
// store cmd list
|
||||
__asm__ volatile ("lda #%b", SP_CMD_CLOSE);
|
||||
__asm__ volatile ("sta %g", spCmd); // store status command #
|
||||
__asm__ volatile ("lda %v", sp_cmdlist_low);
|
||||
__asm__ volatile ("sta %g", spCmdListLow); // store status command #
|
||||
__asm__ volatile ("lda %v", sp_cmdlist_high);
|
||||
__asm__ volatile ("sta %g", spCmdListHigh); // store status command #
|
||||
|
||||
__asm__ volatile ("jsr $C50D"); // to do - find entry point and used it instead of hardcoded address
|
||||
spCmd:
|
||||
__asm__ volatile ("nop");
|
||||
spCmdListLow:
|
||||
__asm__ volatile ("nop");
|
||||
spCmdListHigh:
|
||||
__asm__ volatile ("nop");
|
||||
__asm__ volatile ("sta %v", sp_err);
|
||||
sp_error = sp_err;
|
||||
return sp_err;
|
||||
}
|
||||
|
||||
int8_t sp_read(uint8_t dest, uint16_t len)
|
||||
{
|
||||
sp_error = 0;
|
||||
// sp_dest = 5; // need to search
|
||||
// build the command list
|
||||
sp_cmdlist[0] = SP_READ_PARAM_COUNT;
|
||||
sp_cmdlist[1] = dest; // set before calling sp_status();
|
||||
sp_cmdlist[2] = (uint8_t)((uint16_t)&sp_payload & 0x00FF);
|
||||
sp_cmdlist[3] = (uint8_t)((uint16_t)&sp_payload >> 8) & 0xFF;
|
||||
sp_cmdlist[4] = len & 0xFF;
|
||||
sp_cmdlist[5] = len >> 8;
|
||||
|
||||
sp_cmdlist_low = (uint8_t)((uint16_t)&sp_cmdlist & 0x00FF);
|
||||
sp_cmdlist_high = (uint8_t)((uint16_t)&sp_cmdlist >> 8) & 0xFF;
|
||||
|
||||
// store cmd list
|
||||
__asm__ volatile ("lda #%b", SP_CMD_READ);
|
||||
__asm__ volatile ("sta %g", spCmd); // store status command #
|
||||
__asm__ volatile ("lda %v", sp_cmdlist_low);
|
||||
__asm__ volatile ("sta %g", spCmdListLow); // store status command #
|
||||
__asm__ volatile ("lda %v", sp_cmdlist_high);
|
||||
__asm__ volatile ("sta %g", spCmdListHigh); // store status command #
|
||||
|
||||
__asm__ volatile ("jsr $C50D"); // to do - find entry point and used it instead of hardcoded address
|
||||
spCmd:
|
||||
__asm__ volatile ("nop");
|
||||
spCmdListLow:
|
||||
__asm__ volatile ("nop");
|
||||
spCmdListHigh:
|
||||
__asm__ volatile ("nop");
|
||||
__asm__ volatile ("sta %v", sp_err);
|
||||
sp_error = sp_err;
|
||||
return sp_err;
|
||||
}
|
||||
|
||||
int8_t sp_write(uint8_t dest, uint16_t len)
|
||||
{
|
||||
sp_error = 0;
|
||||
// build the command list
|
||||
sp_cmdlist[0] = SP_READ_PARAM_COUNT;
|
||||
sp_cmdlist[1] = dest; // set before calling sp_status();
|
||||
sp_cmdlist[2] = (uint8_t)((uint16_t)&sp_payload & 0x00FF);
|
||||
sp_cmdlist[3] = (uint8_t)((uint16_t)&sp_payload >> 8) & 0xFF;
|
||||
sp_cmdlist[4] = len & 0xFF;
|
||||
sp_cmdlist[5] = len >> 8;
|
||||
|
||||
sp_cmdlist_low = (uint8_t)((uint16_t)&sp_cmdlist & 0x00FF);
|
||||
sp_cmdlist_high = (uint8_t)((uint16_t)&sp_cmdlist >> 8) & 0xFF;
|
||||
|
||||
// store cmd list
|
||||
__asm__ volatile ("lda #%b", SP_CMD_WRITE);
|
||||
__asm__ volatile ("sta %g", spCmd); // store status command #
|
||||
__asm__ volatile ("lda %v", sp_cmdlist_low);
|
||||
__asm__ volatile ("sta %g", spCmdListLow); // store status command #
|
||||
__asm__ volatile ("lda %v", sp_cmdlist_high);
|
||||
__asm__ volatile ("sta %g", spCmdListHigh); // store status command #
|
||||
|
||||
__asm__ volatile ("jsr $C50D"); // to do - find entry point and used it instead of hardcoded address
|
||||
spCmd:
|
||||
__asm__ volatile ("nop");
|
||||
spCmdListLow:
|
||||
__asm__ volatile ("nop");
|
||||
spCmdListHigh:
|
||||
__asm__ volatile ("nop");
|
||||
__asm__ volatile ("sta %v", sp_err);
|
||||
sp_error = sp_err;
|
||||
return sp_err;
|
||||
}
|
||||
|
||||
int8_t sp_find_fuji()
|
||||
{
|
||||
// const char fuji[9] = "THE_FUJI";
|
||||
const char fuji[14] = "FUJINET_DISK_0";
|
||||
const uint8_t fuji_len = sizeof(fuji);
|
||||
int8_t err, num, i, j;
|
||||
|
||||
err = sp_status(0x00, 0x00); // get number of devices
|
||||
if (err)
|
||||
return -err;
|
||||
num = sp_payload[0];
|
||||
num++;
|
||||
for (i = 1; i < num; i++)
|
||||
{
|
||||
//do
|
||||
err = sp_status(i, 0x03); // get DIB
|
||||
//while (err);
|
||||
if (sp_payload[4] == fuji_len)
|
||||
{
|
||||
for (j = 0; j < fuji_len; j++)
|
||||
if (fuji[j]!=sp_payload[5+j])
|
||||
return 0;
|
||||
sp_dest = i; // store the fuji unit #
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t sp_find_network()
|
||||
{
|
||||
const char net[7] = "NETWORK";
|
||||
const uint8_t net_len = sizeof(net);
|
||||
int8_t err, num, i, j;
|
||||
|
||||
err = sp_status(0x00, 0x00); // get number of devices
|
||||
|
||||
if (err)
|
||||
return -err;
|
||||
|
||||
num = sp_payload[0];
|
||||
num+=2;
|
||||
|
||||
for (i = 1; i < num; i++)
|
||||
{
|
||||
err = sp_status(i, 0x03); // get DIB
|
||||
|
||||
if (sp_payload[4] == net_len)
|
||||
{
|
||||
for (j = 0; j < net_len; j++)
|
||||
if (net[j]!=sp_payload[5+j])
|
||||
return 0;
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
printf("NET NOT FOUND");
|
||||
cgetc();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apple // SmartPort routines for CC65
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check for SmartPort presence
|
||||
* @return slot #, or 0xFF if not present.
|
||||
*/
|
||||
uint8_t sp_find_slot(void)
|
||||
{
|
||||
uint8_t s=0;
|
||||
|
||||
for (s=7; s-- > 0;)
|
||||
{
|
||||
uint16_t a = 0xc000 + (s * 0x100);
|
||||
if ((PEEK(a+1) == 0x20) &&
|
||||
(PEEK(a+3) == 0x00) &&
|
||||
(PEEK(a+5) == 0x03) &&
|
||||
(PEEK(a+7) == 0x00))
|
||||
return s;
|
||||
}
|
||||
|
||||
// Did not find.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return dispatch address for Smartport slot.
|
||||
* @param s Slot # (1-7)
|
||||
* @return smartport dispatch address
|
||||
*/
|
||||
uint16_t sp_dispatch_address(uint8_t slot)
|
||||
{
|
||||
uint16_t a = (slot * 0x100) + 0xC000;
|
||||
uint8_t j = PEEK(a+0xFF);
|
||||
|
||||
return a + j + 3;
|
||||
}
|
||||
|
||||
void sp_init(void)
|
||||
{
|
||||
uint8_t slot, f;
|
||||
slot = sp_find_slot();
|
||||
if (slot)
|
||||
sp_dispatch = sp_dispatch_address(slot);
|
||||
else
|
||||
cprintf("No SmartPort Firmware Found!");
|
||||
//sp_list_devs();
|
||||
f = sp_find_fuji();
|
||||
if (f < 1)
|
||||
cprintf("FujiNet Not Found!");
|
||||
}
|
||||
|
||||
#endif /* BUILD_APPLE2 */
|
30
examples/20-multiapp-arduino/iss-tracker/apple2/src/sp.h
Normal file
30
examples/20-multiapp-arduino/iss-tracker/apple2/src/sp.h
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* FujiNet CONFIG for #Apple2
|
||||
*
|
||||
* SmartPort MLI Routines
|
||||
*/
|
||||
|
||||
#ifndef SP_H
|
||||
#define SP_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint8_t sp_payload[1024];
|
||||
extern uint16_t sp_count, sp_dispatch;
|
||||
extern uint8_t sp_dest;
|
||||
extern uint8_t sp_error;
|
||||
|
||||
int8_t sp_status(uint8_t dest, uint8_t statcode);
|
||||
int8_t sp_control(uint8_t dest, uint8_t ctrlcode);
|
||||
int8_t sp_open(uint8_t dest);
|
||||
int8_t sp_close(uint8_t dest);
|
||||
int8_t sp_read(uint8_t dest, uint16_t len);
|
||||
int8_t sp_write(uint8_t dest, uint16_t len);
|
||||
int8_t sp_find_fuji(void);
|
||||
int8_t sp_find_network(void);
|
||||
uint8_t sp_find_slot(void);
|
||||
uint16_t sp_dispatch_address(uint8_t slot);
|
||||
void sp_init(void);
|
||||
|
||||
#endif /* SP_H */
|
||||
|
154
examples/30-dnd5eapi-cc65/30-dnd5eapi-cc65.ino
Normal file
154
examples/30-dnd5eapi-cc65/30-dnd5eapi-cc65.ino
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
Nathanial Hendler
|
||||
2021
|
||||
github.com/equant
|
||||
*/
|
||||
|
||||
// Load Wi-Fi library
|
||||
#include <WiFi.h>
|
||||
#include <Apple2Idiot.h>
|
||||
#include "credentials.h"
|
||||
//#include "a2i_weather.h"
|
||||
//#include "a2i_iss.h"
|
||||
//#include "a2i_chess.h"
|
||||
#include "a2i_dnd5eapi.h"
|
||||
|
||||
#define AUTO_CONNECT_TO_WIFI 1
|
||||
#define AUTO_CONNECT_TIMEOUT 5
|
||||
|
||||
Apple2Idiot a2i = Apple2Idiot();
|
||||
|
||||
/*################################################
|
||||
# Applications we're going to support #
|
||||
#
|
||||
# An Apple ][ running this card may want to run
|
||||
# several different "apps" that utilize the card.
|
||||
# These "apps" are classes (instantiated below)
|
||||
# which the main loop uses to handle/manage
|
||||
# communication with the Apple. For example, the
|
||||
# card may want to handle requests to support
|
||||
# programs on the Apple ][ such as a wifi
|
||||
# selector, a chess game, and a weather lookup
|
||||
# app.
|
||||
################################################*/
|
||||
|
||||
Dnd5eapi dnd5eapi_app = Dnd5eapi();
|
||||
//Weather weather_app = Weather();
|
||||
//Iss iss_app = Iss();
|
||||
|
||||
#define N_APPS 1
|
||||
//byte app_ids[N_APPS] = {APP_ISS, APP_WEATHER, APP_DND5EAPI};
|
||||
byte app_ids[N_APPS] = {APP_DND5EAPI};
|
||||
|
||||
/*******************/
|
||||
/* Variables */
|
||||
/*******************/
|
||||
|
||||
byte current_app_id;
|
||||
|
||||
const long mainLoopInterval = 100; // millis
|
||||
//const long mainLoopInterval = 10000; // millis
|
||||
unsigned long lastMainLoopTime = 0;
|
||||
byte lastAppleCommand = 0;
|
||||
|
||||
/*################################################
|
||||
# Setup #
|
||||
################################################*/
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
a2i.init();
|
||||
|
||||
#ifdef AUTO_CONNECT_TO_WIFI
|
||||
Serial.println("");
|
||||
Serial.print("Starting wifi, connecting to: ");
|
||||
Serial.println(WIFI_SSID);
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
byte wifi_loop_count = 0;
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(600);
|
||||
wifi_loop_count++;
|
||||
Serial.print(".");
|
||||
if (wifi_loop_count > AUTO_CONNECT_TIMEOUT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected successfully");
|
||||
Serial.print("Got IP: ");
|
||||
Serial.println(WiFi.localIP()); //Show ESP32 IP on serial
|
||||
} else {
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connection failed.");
|
||||
}
|
||||
#else
|
||||
// Set WiFi to station mode and disconnect from an AP if it was previously connected
|
||||
Serial.println("Wifi autoconnect not enabled. No wifi connection attempted.");
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.disconnect();
|
||||
#endif
|
||||
|
||||
Serial.println("Setup done");
|
||||
current_app_id = app_ids[0];
|
||||
|
||||
}
|
||||
|
||||
/*################################################
|
||||
# Main #
|
||||
################################################*/
|
||||
|
||||
void loop() {
|
||||
|
||||
if ((millis() - lastMainLoopTime) > mainLoopInterval) {
|
||||
//Serial.print(".");
|
||||
byte command_byte = a2i.read_data(APPLE_COMMAND_ADDRESS);
|
||||
if (command_byte == RAM_BUSY) {
|
||||
Serial.println("Command Read: RAM BUSY");
|
||||
}
|
||||
else if (command_byte != lastAppleCommand){
|
||||
lastAppleCommand = command_byte;
|
||||
byte result = 0;
|
||||
Serial.print("Handling command_byte: ");
|
||||
Serial.println(command_byte);
|
||||
|
||||
/* Do we need to switch app context? */
|
||||
for (int i=0; i<N_APPS; i++) {
|
||||
Serial.print("App loop: ");
|
||||
Serial.println(i);
|
||||
Serial.print("Checking ID: ");
|
||||
Serial.println(app_ids[i]);
|
||||
if (command_byte == app_ids[i]) {
|
||||
// We were sent an app id.
|
||||
Serial.println("We were sent an app id");
|
||||
if (current_app_id != command_byte) {
|
||||
// We are talking to a new app
|
||||
Serial.println("We are talking to a new app");
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, ACK);
|
||||
current_app_id = command_byte;
|
||||
}
|
||||
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
a2i.write_data(ESP_COMMAND_ADDRESS, EOT);
|
||||
lastMainLoopTime = millis();
|
||||
Serial.println("About to return");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we got here, we need to pass the command to app's class to be handled */
|
||||
|
||||
if (current_app_id == dnd5eapi_app.appId) {
|
||||
Serial.println("Received a command for Dnd5eapi()");
|
||||
dnd5eapi_app.handleCommand(command_byte);
|
||||
Serial.println("...command for Dnd5eapi() handled");
|
||||
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
//a2i.write_data(ESP_COMMAND_ADDRESS, EOT); // notify Apple IIe we are done processing command byte
|
||||
}
|
||||
else {
|
||||
Serial.println("Received a command for UNKNOWN()");
|
||||
}
|
||||
}
|
||||
lastMainLoopTime = millis();
|
||||
}
|
||||
}
|
8
examples/30-dnd5eapi-cc65/README.md
Normal file
8
examples/30-dnd5eapi-cc65/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
# Arduno sketch for Apple2 Internet Weather Client Examples
|
||||
|
||||
For now, this works with both the basic and and cc65 clients
|
||||
|
||||
`../15_fixed_essid_weather-basic`
|
||||
`../15_fixed_essid_weather-cc65`
|
||||
|
||||
if arduino-cli compile --fqbn esp32:esp32:nodemcu-32s .; then arduino-cli upload -p /dev/ttyUSB0 --fqbn esp32:esp32:esp32-poe-iso .; fi
|
291
examples/30-dnd5eapi-cc65/a2i_chess.cpp
Normal file
291
examples/30-dnd5eapi-cc65/a2i_chess.cpp
Normal file
@ -0,0 +1,291 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <Apple2Idiot.h>
|
||||
#include "chess_commands.h"
|
||||
#include "a2i_chess.h"
|
||||
|
||||
|
||||
void Chess::init(Apple2Idiot *a2ip, HTTPClient *httpp) {
|
||||
a2i = a2ip;
|
||||
http = httpp;
|
||||
//strcpy(game_string, "a2a3e7e5e2e4");
|
||||
}
|
||||
|
||||
byte Chess::handleCommand(byte command) {
|
||||
switch(command) {
|
||||
case CHESS_MAKE_MOVE: {
|
||||
a2i->write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
Serial.println("CHESS() MAKE_MOVE");
|
||||
String move_string;
|
||||
move_string = a2i->read_string_from_ram(SHARED_RAM_START_ADDRESS);
|
||||
Serial.println("Received move: ["+move_string+"]");
|
||||
byte result = makeMove(move_string);
|
||||
int address_counter = a2i->write_string_to_shared_ram(last_ai_move, SHARED_RAM_START_ADDRESS);
|
||||
getBoard();
|
||||
for (int i=0; i<9; i++) {
|
||||
address_counter = a2i->write_string_to_shared_ram(game_board[i], address_counter + 1);
|
||||
}
|
||||
a2i->write_data(ESP_COMMAND_ADDRESS, result);
|
||||
a2i->read_ram(11);
|
||||
return ACK;
|
||||
}
|
||||
case CHESS_NEW_GAME: {
|
||||
a2i->write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
Serial.println("CHESS_NEW_GAME");
|
||||
strcpy(game_string, "");
|
||||
return ACK;
|
||||
}
|
||||
default: {
|
||||
return COMMAND_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte Chess::makeMove(String move_string) {
|
||||
/* Apple says MAKE_MOVE and sends "a2a3"
|
||||
*
|
||||
* The basic flow...
|
||||
*
|
||||
* validateMove() We check that it's valid.
|
||||
* If it is we accept the move and add it to game_string
|
||||
* getGameStatus() Then we check the status and return (did someone win or lose?)
|
||||
* getAIMove() Then we get the AI move.
|
||||
* Then we check the status and return (did someone win or lose?)
|
||||
*/
|
||||
Apple2Idiot a2i;
|
||||
HTTPClient http;
|
||||
if (validateMove(move_string) == CHESS_VALID_MOVE) {
|
||||
strcat(game_string, move_string.c_str());
|
||||
} else {
|
||||
return CHESS_INVALID_MOVE;
|
||||
}
|
||||
char* game_status;
|
||||
//b = getGameStatus(game_string);
|
||||
game_status = getGameStatus(game_string);
|
||||
Serial.print("after player move game_status:"); Serial.println(game_status);
|
||||
|
||||
if (strcmp(game_status, "in_progress") == 0) {
|
||||
//char* ai_move;
|
||||
//ai_move = getAIMove();
|
||||
//strcat(game_string, ai_move);
|
||||
//last_ai_move = getAIMove();
|
||||
strcpy(last_ai_move, getAIMove());
|
||||
strcat(game_string, last_ai_move);
|
||||
game_status = getGameStatus(game_string);
|
||||
Serial.print("after AI move game_status:"); Serial.println(game_status);
|
||||
if (strcmp(game_status, "in_progress") == 0) { return STATUS_IN_PROGRESS; }
|
||||
else if (strcmp(game_status, "black_won") == 0) { return STATUS_BLACK_WON; }
|
||||
else if (strcmp(game_status, "white_won") == 0) { return STATUS_WHITE_WON; }
|
||||
else if (strcmp(game_status, "white_won_resign") == 0) { return STATUS_UNHANDLED; }
|
||||
else if (strcmp(game_status, "black_won_resign") == 0) { return STATUS_UNHANDLED; }
|
||||
else if (strcmp(game_status, "stalemate") == 0) { return STATUS_STALEMATE; }
|
||||
else if (strcmp(game_status, "insufficient_material") == 0) { return STATUS_UNHANDLED; }
|
||||
else if (strcmp(game_status, "fifty_rule_move") == 0) { return STATUS_FIFTY_RULE_MOVE; }
|
||||
else if (strcmp(game_status, "threefold_repitition") == 0) { return STATUS_UNHANDLED; }
|
||||
else if (strcmp(game_status, "unknown") == 0) { return STATUS_UNKNOWN; } else { return STATUS_ERROR; }
|
||||
}
|
||||
else if (strcmp(game_status, "black_won") == 0) { return STATUS_BLACK_WON; }
|
||||
else if (strcmp(game_status, "white_won") == 0) { return STATUS_WHITE_WON; }
|
||||
else if (strcmp(game_status, "white_won_resign") == 0) { return STATUS_UNHANDLED; }
|
||||
else if (strcmp(game_status, "black_won_resign") == 0) { return STATUS_UNHANDLED; }
|
||||
else if (strcmp(game_status, "stalemate") == 0) { return STATUS_STALEMATE; }
|
||||
else if (strcmp(game_status, "insufficient_material") == 0) { return STATUS_UNHANDLED; }
|
||||
else if (strcmp(game_status, "fifty_rule_move") == 0) { return STATUS_FIFTY_RULE_MOVE; }
|
||||
else if (strcmp(game_status, "threefold_repitition") == 0) { return STATUS_UNHANDLED; }
|
||||
else if (strcmp(game_status, "unknown") == 0) { return STATUS_UNKNOWN; } else { return STATUS_ERROR; }
|
||||
}
|
||||
|
||||
char* Chess::getGameStatus(char* game_string) {
|
||||
Apple2Idiot a2i;
|
||||
HTTPClient http;
|
||||
Serial.print("getGameStatus() "); Serial.println(game_status);
|
||||
|
||||
char api_request[MAX_STR_LEN];
|
||||
sprintf(api_request, "%s/status/%s", api_entry_point, game_string);
|
||||
Serial.print(" "); Serial.println(api_request);
|
||||
http.begin(api_request);
|
||||
int httpCode = http.GET(); //Make the request
|
||||
delay(10);
|
||||
if (httpCode > 0) { //Check for the returning code
|
||||
Serial.println(" Success on HTTP request");
|
||||
String payload = http.getString();
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
//Serial.println(payload);
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
StaticJsonDocument<400> doc;
|
||||
DeserializationError error = deserializeJson(doc, payload);
|
||||
if (error) {
|
||||
Serial.print(F(" deserializeJson() failed: "));
|
||||
Serial.println(error.f_str());
|
||||
return "error";
|
||||
} else {
|
||||
Serial.println("----------------------");
|
||||
serializeJsonPretty(doc, Serial);
|
||||
Serial.println();
|
||||
Serial.println("----------------------");
|
||||
//return doc["gameStatus"];
|
||||
return (char *)doc["gameStatus"].as<char *>();
|
||||
}
|
||||
} else {
|
||||
Serial.println("Error on HTTP request");
|
||||
return "error";
|
||||
}
|
||||
// Don't know how we could get here without it being an error.
|
||||
|
||||
return "error";
|
||||
}
|
||||
|
||||
char* Chess::getAIMove() {
|
||||
Apple2Idiot a2i;
|
||||
HTTPClient http;
|
||||
Serial.print("getAIMove() "); Serial.println(game_status);
|
||||
|
||||
char api_request[MAX_STR_LEN];
|
||||
sprintf(api_request, "%s/next_best/%s", api_entry_point, game_string);
|
||||
Serial.print(" "); Serial.println(api_request);
|
||||
http.begin(api_request);
|
||||
int httpCode = http.GET(); //Make the request
|
||||
delay(10);
|
||||
if (httpCode > 0) { //Check for the returning code
|
||||
Serial.println(" Success on HTTP request");
|
||||
String payload = http.getString();
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
//Serial.println(payload);
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
StaticJsonDocument<400> doc;
|
||||
DeserializationError error = deserializeJson(doc, payload);
|
||||
if (error) {
|
||||
Serial.print(F(" deserializeJson() failed: "));
|
||||
Serial.println(error.f_str());
|
||||
return "jsonerror";
|
||||
} else {
|
||||
Serial.println("----------------------");
|
||||
serializeJsonPretty(doc, Serial);
|
||||
Serial.println();
|
||||
Serial.println("----------------------");
|
||||
//return doc["gameStatus"];
|
||||
return (char *)doc["bestNext"].as<char *>();
|
||||
}
|
||||
} else {
|
||||
Serial.println("Error on HTTP request");
|
||||
return "geterror";
|
||||
}
|
||||
// Don't know how we could get here without it being an error.
|
||||
|
||||
return "unknownerror";
|
||||
}
|
||||
|
||||
byte Chess::validateMove(String move_string) {
|
||||
Apple2Idiot a2i;
|
||||
HTTPClient http;
|
||||
Serial.print("validateMove() "); Serial.println(move_string);
|
||||
char api_request[MAX_STR_LEN];
|
||||
sprintf(api_request, "%s/valid_move/%s%s", api_entry_point, game_string, move_string);
|
||||
Serial.print(" "); Serial.println(api_request);
|
||||
http.begin(api_request);
|
||||
int httpCode = http.GET(); //Make the request
|
||||
delay(10);
|
||||
if (httpCode > 0) { //Check for the returning code
|
||||
Serial.println(" Success on HTTP request");
|
||||
String payload = http.getString();
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
//Serial.println(payload);
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
StaticJsonDocument<400> doc;
|
||||
DeserializationError error = deserializeJson(doc, payload);
|
||||
if (error) {
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.f_str());
|
||||
return ERR;
|
||||
} else {
|
||||
Serial.println("----------------------");
|
||||
serializeJsonPretty(doc, Serial);
|
||||
Serial.println();
|
||||
Serial.println("----------------------");
|
||||
bool validMove = doc["validMove"];
|
||||
if (validMove) {
|
||||
// good move
|
||||
Serial.println(" Valid move!");
|
||||
return CHESS_VALID_MOVE;
|
||||
} else {
|
||||
Serial.println(" Invalid move!");
|
||||
return CHESS_INVALID_MOVE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Serial.println("Error on HTTP request");
|
||||
return ERR;
|
||||
}
|
||||
// Don't know how we could get here without it being an error.
|
||||
return ERR;
|
||||
}
|
||||
|
||||
void Chess::removeSubstr (char *string, char *sub) {
|
||||
char *match = string;
|
||||
int len = strlen(sub);
|
||||
while ((match = strstr(match, sub))) {
|
||||
*match = '\0';
|
||||
strcat(string, match+len);
|
||||
match++;
|
||||
}
|
||||
}
|
||||
|
||||
void Chess::getBoard() {
|
||||
Apple2Idiot a2i;
|
||||
HTTPClient http;
|
||||
Serial.println("getBoard() ");
|
||||
char api_request[MAX_STR_LEN];
|
||||
sprintf(api_request, "%s/board_string/%s", api_entry_point, game_string);
|
||||
Serial.print(" "); Serial.println(api_request);
|
||||
http.begin(api_request);
|
||||
int httpCode = http.GET(); //Make the request
|
||||
delay(10);
|
||||
if (httpCode > 0) { //Check for the returning code
|
||||
Serial.println(" Success on HTTP request");
|
||||
String payload = http.getString();
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
//Serial.println(payload);
|
||||
//Serial.println("++++++++++++++++++++++++");
|
||||
StaticJsonDocument<400> doc;
|
||||
DeserializationError error = deserializeJson(doc, payload);
|
||||
if (error) {
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.f_str());
|
||||
} else {
|
||||
//Serial.println("----------------------");
|
||||
//serializeJsonPretty(doc, Serial);
|
||||
//Serial.println();
|
||||
//Serial.println("----------------------");
|
||||
//Serial.println(" Break up the board...");
|
||||
//Serial.print(" BOARD:"); Serial.println((char *)doc["board"].as<char *>());
|
||||
char* pch = NULL;
|
||||
pch = strtok((char *)doc["board"].as<char *>(), "\n");
|
||||
//Serial.print(" pch:");Serial.println(pch);
|
||||
int row_count = 0;
|
||||
while (pch != NULL) {
|
||||
char board_line[30];
|
||||
strcpy(board_line, pch);
|
||||
removeSubstr(board_line, "[37m");
|
||||
removeSubstr(board_line, "[0m");
|
||||
removeSubstr(board_line, "\n");
|
||||
removeSubstr(board_line, "\e"); // remove escape (ASCII 27)
|
||||
removeSubstr(board_line, "\e"); // remove escape (ASCII 27)
|
||||
//Serial.print("(");Serial.print(row_count);Serial.print(")");
|
||||
//Serial.print(board_line); Serial.println("|");
|
||||
strcpy(game_board[row_count], board_line); // valid
|
||||
pch = strtok(NULL, "\n");
|
||||
row_count++;
|
||||
}
|
||||
Serial.println();
|
||||
for (int i=0; i<9; i++) {
|
||||
Serial.print("[");Serial.print(game_board[i]);Serial.println("]");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Serial.println("Error on HTTP request");
|
||||
}
|
||||
// Don't know how we could get here without it being an error.
|
||||
}
|
88
examples/30-dnd5eapi-cc65/a2i_dnd5eapi.cpp
Normal file
88
examples/30-dnd5eapi-cc65/a2i_dnd5eapi.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <Apple2Idiot.h>
|
||||
#include "dnd5eapi_commands.h"
|
||||
#include "a2i_dnd5eapi.h"
|
||||
|
||||
|
||||
void Dnd5eapi::init(Apple2Idiot *a2ip, HTTPClient *httpp) {
|
||||
a2i = a2ip;
|
||||
http = httpp;
|
||||
Serial.println("DND5EAPI()::init()");
|
||||
}
|
||||
|
||||
byte Dnd5eapi::handleCommand(byte command) {
|
||||
Serial.println("DND5EAPI() handleCommand");
|
||||
switch(command) {
|
||||
case COMMAND_SEARCH_MONSTER: {
|
||||
Serial.println("DND5EAPI() COMMAND_SEARCH_MONSTER");
|
||||
a2i->write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
Serial.println("DND5EAPI() searchMonster()");
|
||||
return searchMonster();
|
||||
}
|
||||
default: {
|
||||
Serial.print("DND5EAPI() COMMAND_NOT_FOUND: ");
|
||||
Serial.println(command);
|
||||
return COMMAND_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte Dnd5eapi::searchMonster() {
|
||||
|
||||
byte result = 0;
|
||||
Apple2Idiot a2i;
|
||||
HTTPClient http;
|
||||
|
||||
char api_request[MAX_STR_LEN];
|
||||
sprintf(api_request, "%s/?name=%s", api_entry_point, monster_search_string);
|
||||
Serial.print(" "); Serial.println(api_request);
|
||||
http.begin(api_request);
|
||||
|
||||
int httpCode = http.GET(); //Make the request
|
||||
Serial.print(" "); Serial.println("After GET()");
|
||||
delay(10);
|
||||
Serial.print(" httpCode:"); Serial.println(httpCode);
|
||||
|
||||
if (httpCode > 0) { //Check for the returning code
|
||||
String payload = http.getString();
|
||||
//Serial.println(httpCode);
|
||||
Serial.println("++++++++++++++++++++++++");
|
||||
Serial.println(payload);
|
||||
Serial.println("++++++++++++++++++++++++");
|
||||
StaticJsonDocument<200> filter;
|
||||
filter["count"] = true;
|
||||
filter["results"] = true;
|
||||
StaticJsonDocument<400> doc;
|
||||
DeserializationError error = deserializeJson(doc, payload, DeserializationOption::Filter(filter));
|
||||
//DeserializationError error = deserializeJson(doc, payload);
|
||||
if (error) {
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.f_str());
|
||||
} else {
|
||||
Serial.println("----------------------");
|
||||
serializeJsonPretty(doc, Serial);
|
||||
Serial.println("----------------------");
|
||||
serializeJsonPretty(doc["results"], Serial);
|
||||
Serial.println("----------------------");
|
||||
String result_count = doc["count"];
|
||||
String results = doc["results"];
|
||||
//int address_counter = a2i.write_string_to_shared_ram(latitude, SHARED_RAM_START_ADDRESS);
|
||||
//address_counter = a2i.write_string_to_shared_ram(longitude, address_counter + 1);
|
||||
//address_counter = a2i.write_string_to_shared_ram(timestamp, address_counter + 1);
|
||||
//address_counter = a2i.write_string_to_shared_ram(message, address_counter + 1);
|
||||
}
|
||||
result = ACK;
|
||||
}
|
||||
else {
|
||||
Serial.println("Error on HTTP request");
|
||||
result = ERR;
|
||||
}
|
||||
|
||||
http.end(); //Free the resources
|
||||
return result;
|
||||
}
|
||||
|
42
examples/30-dnd5eapi-cc65/a2i_dnd5eapi.h
Normal file
42
examples/30-dnd5eapi-cc65/a2i_dnd5eapi.h
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
#ifndef A2I_DND5EAPI_H
|
||||
#define A2I_DND5EAPI_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <A2I_commands.h>
|
||||
#include <Apple2Idiot.h>
|
||||
#include "dnd5eapi_commands.h"
|
||||
|
||||
class Dnd5eapi {
|
||||
|
||||
public:
|
||||
// This is "registered" with A2I_commands.h which is part of Apple2Idiot.h This
|
||||
// id is sent from the Apple to the ESP to tell the esp what app is currently
|
||||
// active. The main loop of the ESP sketch then knows to use this class to
|
||||
// respond to incoming commands from the Apple.
|
||||
byte appId = APP_DND5EAPI;
|
||||
|
||||
String monster_search_string = "crab";
|
||||
|
||||
void init(Apple2Idiot *a2ip, HTTPClient *httpp);
|
||||
byte handleCommand(byte command);
|
||||
byte searchMonster(byte command);
|
||||
byte fetch_dnd5eapi();
|
||||
|
||||
private:
|
||||
|
||||
Apple2Idiot *a2i;
|
||||
HTTPClient *http;
|
||||
|
||||
void removeSubstr (char *string, char *sub);
|
||||
const char api_entry_point[49] = "https://www.dnd5eapi.co/api/";
|
||||
/* Remember, flexible array won't work
|
||||
* in a class, so don't try to do this...
|
||||
* const char foo[] = "hello world";
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
92
examples/30-dnd5eapi-cc65/a2i_iss.cpp
Normal file
92
examples/30-dnd5eapi-cc65/a2i_iss.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <Apple2Idiot.h>
|
||||
#include "iss_commands.h"
|
||||
#include "a2i_iss.h"
|
||||
|
||||
|
||||
void Iss::init(Apple2Idiot *a2ip, HTTPClient *httpp) {
|
||||
a2i = a2ip;
|
||||
http = httpp;
|
||||
Serial.println("ISS()::init()");
|
||||
}
|
||||
|
||||
byte Iss::handleCommand(byte command) {
|
||||
Serial.println("ISS() handleCommand");
|
||||
switch(command) {
|
||||
case COMMAND_GET_ISS: {
|
||||
Serial.println("ISS() COMMAND_GET_ISS");
|
||||
a2i->write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
Serial.println("ISS() before fetch_iss()");
|
||||
return fetch_iss();
|
||||
}
|
||||
default: {
|
||||
Serial.print("ISS() COMMAND_NOT_FOUND: ");
|
||||
Serial.println(command);
|
||||
return COMMAND_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte Iss::fetch_iss() {
|
||||
|
||||
byte result = 0;
|
||||
Apple2Idiot a2i;
|
||||
HTTPClient http;
|
||||
|
||||
char api_request[MAX_STR_LEN];
|
||||
sprintf(api_request, "%s", api_entry_point);
|
||||
Serial.print(" "); Serial.println(api_request);
|
||||
http.begin(api_request);
|
||||
|
||||
int httpCode = http.GET(); //Make the request
|
||||
Serial.print(" "); Serial.println("After GET()");
|
||||
delay(10);
|
||||
Serial.print(" httpCode:"); Serial.println(httpCode);
|
||||
|
||||
if (httpCode > 0) { //Check for the returning code
|
||||
String payload = http.getString();
|
||||
//Serial.println(httpCode);
|
||||
Serial.println("++++++++++++++++++++++++");
|
||||
Serial.println(payload);
|
||||
Serial.println("++++++++++++++++++++++++");
|
||||
StaticJsonDocument<200> filter;
|
||||
filter["iss_position"]["latitude"] = true;
|
||||
filter["iss_position"]["longitude"] = true;
|
||||
filter["timestamp"] = true;
|
||||
filter["message"]["humidity"] = true;
|
||||
StaticJsonDocument<400> doc;
|
||||
DeserializationError error = deserializeJson(doc, payload, DeserializationOption::Filter(filter));
|
||||
//DeserializationError error = deserializeJson(doc, payload);
|
||||
if (error) {
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.f_str());
|
||||
} else {
|
||||
Serial.println("----------------------");
|
||||
serializeJsonPretty(doc, Serial);
|
||||
Serial.println("----------------------");
|
||||
serializeJsonPretty(doc["iss_position"], Serial);
|
||||
Serial.println("----------------------");
|
||||
String latitude = doc["iss_position"]["latitude"];
|
||||
String longitude = doc["iss_position"]["longitude"];
|
||||
String timestamp = doc["timestamp"];
|
||||
String message = doc["messasge"];
|
||||
int address_counter = a2i.write_string_to_shared_ram(latitude, SHARED_RAM_START_ADDRESS);
|
||||
address_counter = a2i.write_string_to_shared_ram(longitude, address_counter + 1);
|
||||
address_counter = a2i.write_string_to_shared_ram(timestamp, address_counter + 1);
|
||||
address_counter = a2i.write_string_to_shared_ram(message, address_counter + 1);
|
||||
}
|
||||
result = ACK;
|
||||
}
|
||||
else {
|
||||
Serial.println("Error on HTTP request");
|
||||
result = ERR;
|
||||
}
|
||||
|
||||
http.end(); //Free the resources
|
||||
return result;
|
||||
}
|
||||
|
43
examples/30-dnd5eapi-cc65/a2i_iss.h
Normal file
43
examples/30-dnd5eapi-cc65/a2i_iss.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef A2I_ISS_H
|
||||
#define A2I_ISS_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <A2I_commands.h>
|
||||
#include <Apple2Idiot.h>
|
||||
#include "iss_commands.h"
|
||||
|
||||
class Iss {
|
||||
|
||||
public:
|
||||
// This is "registered" with A2I_commands.h which is part of Apple2Idiot.h This
|
||||
// id is sent from the Apple to the ESP to tell the esp what app is currently
|
||||
// active. The main loop of the ESP sketch then knows to use this class to
|
||||
// respond to incoming commands from the Apple.
|
||||
byte appId = APP_ISS;
|
||||
|
||||
void init(Apple2Idiot *a2ip, HTTPClient *httpp);
|
||||
//char* getGameStatus(char* game_status);
|
||||
//byte makeMove(String move_string);
|
||||
byte handleCommand(byte command);
|
||||
byte fetch_iss();
|
||||
//byte validateMove(String move_string);
|
||||
//char* getAIMove();
|
||||
//void getBoard();
|
||||
|
||||
private:
|
||||
|
||||
Apple2Idiot *a2i;
|
||||
HTTPClient *http;
|
||||
|
||||
void removeSubstr (char *string, char *sub);
|
||||
const char api_entry_point[49] = "http://api.open-notify.org/iss-now.json";
|
||||
/* Remember, flexible array won't work
|
||||
* in a class, so don't try to do this...
|
||||
* const char foo[] = "hello world";
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
119
examples/30-dnd5eapi-cc65/a2i_weather.cpp
Normal file
119
examples/30-dnd5eapi-cc65/a2i_weather.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <Apple2Idiot.h>
|
||||
#include "weather_commands.h"
|
||||
#include "a2i_weather.h"
|
||||
#include "credentials.h"
|
||||
|
||||
|
||||
void Weather::init(Apple2Idiot *a2ip, HTTPClient *httpp) {
|
||||
a2i = a2ip;
|
||||
http = httpp;
|
||||
Serial.println("WEATHER()::init()");
|
||||
}
|
||||
|
||||
byte Weather::handleCommand(byte command) {
|
||||
Serial.println("WEATHER() handleCommand");
|
||||
switch(command) {
|
||||
case COMMAND_FETCH_WEATHER: {
|
||||
Serial.println("WEATHER() COMMAND_FETCH_WEATHER");
|
||||
a2i->write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
Serial.println("WEATHER() before fetch_weather()");
|
||||
return fetch_weather();
|
||||
}
|
||||
case COMMAND_SET_COUNTRY: {
|
||||
Serial.println("WEATHER() COMMAND_SET_COUNTRY");
|
||||
a2i->write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
country_code = a2i->read_string_from_ram(SHARED_RAM_START_ADDRESS);
|
||||
Serial.println("Received CountryCode: ["+country_code+"]");
|
||||
a2i->write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
a2i->write_data(ESP_COMMAND_ADDRESS, EOT); // notify Apple IIe we are done processing command byte
|
||||
return ACK;
|
||||
//break;
|
||||
}
|
||||
case COMMAND_SET_CITY: {
|
||||
//a2i->write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
Serial.print("WEATHER() COMMAND_SET_CITY");
|
||||
a2i->write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
|
||||
city_name = a2i->read_string_from_ram(SHARED_RAM_START_ADDRESS);
|
||||
Serial.println("Received CityName: ["+city_name+"]");
|
||||
a2i->write_data(APPLE_COMMAND_ADDRESS, ACK);
|
||||
a2i->write_data(ESP_COMMAND_ADDRESS, EOT); // notify Apple IIe we are done processing command byte
|
||||
return ACK;
|
||||
}
|
||||
default: {
|
||||
Serial.print("WEATHER() COMMAND_NOT_FOUND: ");
|
||||
Serial.println(command);
|
||||
return COMMAND_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte Weather::fetch_weather() {
|
||||
|
||||
byte result = 0;
|
||||
Apple2Idiot a2i;
|
||||
HTTPClient http;
|
||||
|
||||
char api_request[MAX_STR_LEN];
|
||||
sprintf(api_request, "%sq=%s,%s&APPID=%s", api_entry_point, city_name, country_code, WEATHER_ACCESS_TOKEN);
|
||||
//sprintf(api_request, "http://api.openweathermap.org/data/2.5/weather?q=TUCSON,US&APPID=0ab97bbbea58592d7c9d64067a34d2d0");
|
||||
Serial.print(" "); Serial.println(api_request);
|
||||
http.begin(api_request);
|
||||
|
||||
int httpCode = http.GET(); //Make the request
|
||||
Serial.print(" "); Serial.println("After GET()");
|
||||
delay(10);
|
||||
|
||||
if (httpCode > 0) { //Check for the returning code
|
||||
String payload = http.getString();
|
||||
//Serial.println(httpCode);
|
||||
Serial.println("++++++++++++++++++++++++");
|
||||
Serial.println(payload);
|
||||
Serial.println("++++++++++++++++++++++++");
|
||||
StaticJsonDocument<200> filter;
|
||||
filter["weather"][0]["main"] = true;
|
||||
filter["weather"][0]["description"] = true;
|
||||
filter["main"]["humidity"] = true;
|
||||
filter["main"]["temp"] = true;
|
||||
filter["wind"]["speed"] = true;
|
||||
filter["wind"]["deg"] = true;
|
||||
StaticJsonDocument<400> doc;
|
||||
DeserializationError error = deserializeJson(doc, payload, DeserializationOption::Filter(filter));
|
||||
//DeserializationError error = deserializeJson(doc, payload);
|
||||
if (error) {
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.f_str());
|
||||
} else {
|
||||
Serial.println("----------------------");
|
||||
serializeJsonPretty(doc, Serial);
|
||||
Serial.println("----------------------");
|
||||
serializeJsonPretty(doc["wind"], Serial);
|
||||
Serial.println("----------------------");
|
||||
String temp = doc["main"]["temp"];
|
||||
String humidity = doc["main"]["humidity"];
|
||||
String wind_speed = doc["wind"]["speed"];
|
||||
String wind_deg = doc["wind"]["deg"];
|
||||
String weather_description1 = doc["weather"][0]["main"];
|
||||
String weather_description2 = doc["weather"][0]["description"];
|
||||
int address_counter = a2i.write_string_to_shared_ram(temp, SHARED_RAM_START_ADDRESS);
|
||||
address_counter = a2i.write_string_to_shared_ram(humidity, address_counter + 1);
|
||||
address_counter = a2i.write_string_to_shared_ram(wind_speed, address_counter + 1);
|
||||
address_counter = a2i.write_string_to_shared_ram(wind_deg, address_counter + 1);
|
||||
address_counter = a2i.write_string_to_shared_ram(weather_description1, address_counter + 1);
|
||||
address_counter = a2i.write_string_to_shared_ram(weather_description2, address_counter + 1);
|
||||
}
|
||||
result = ACK;
|
||||
}
|
||||
else {
|
||||
Serial.println("Error on HTTP request");
|
||||
result = ERR;
|
||||
}
|
||||
|
||||
http.end(); //Free the resources
|
||||
return result;
|
||||
}
|
||||
|
47
examples/30-dnd5eapi-cc65/a2i_weather.h
Normal file
47
examples/30-dnd5eapi-cc65/a2i_weather.h
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef A2I_WEATHER_H
|
||||
#define A2I_WEATHER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <A2I_commands.h>
|
||||
#include <Apple2Idiot.h>
|
||||
#include "weather_commands.h"
|
||||
#include "credentials.h"
|
||||
|
||||
class Weather {
|
||||
|
||||
public:
|
||||
// This is "registered" with A2I_commands.h which is part of Apple2Idiot.h This
|
||||
// id is sent from the Apple to the ESP to tell the esp what app is currently
|
||||
// active. The main loop of the ESP sketch then knows to use this class to
|
||||
// respond to incoming commands from the Apple.
|
||||
byte appId = APP_WEATHER;
|
||||
|
||||
String country_code = "US";
|
||||
String city_name = "Tucson";
|
||||
|
||||
void init(Apple2Idiot *a2ip, HTTPClient *httpp);
|
||||
//char* getGameStatus(char* game_status);
|
||||
//byte makeMove(String move_string);
|
||||
byte handleCommand(byte command);
|
||||
byte fetch_weather();
|
||||
//byte validateMove(String move_string);
|
||||
//char* getAIMove();
|
||||
//void getBoard();
|
||||
|
||||
private:
|
||||
|
||||
Apple2Idiot *a2i;
|
||||
HTTPClient *http;
|
||||
|
||||
void removeSubstr (char *string, char *sub);
|
||||
const char api_entry_point[49] = "http://api.openweathermap.org/data/2.5/weather?";
|
||||
/* Remember, flexible array won't work
|
||||
* in a class, so don't try to do this...
|
||||
* const char foo[] = "hello world";
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
12
examples/30-dnd5eapi-cc65/credentials.h.sample
Normal file
12
examples/30-dnd5eapi-cc65/credentials.h.sample
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef CREDENTIALS_H
|
||||
#define CREDENTIALS_H
|
||||
|
||||
#include "credentials.h"
|
||||
// copy credentials.h.sample to credentials.h and edit
|
||||
// so it contains your passwords and tokens.
|
||||
|
||||
#define WIFI_SSID "XXXXXXXXXXXXXXX";
|
||||
#define WIFI_PASSWORD "XXXXXXXXXXXXXXX";
|
||||
#define WEATHER_ACCESS_TOKEN "XXXXXXXXXXXXXXX"
|
||||
|
||||
#endif
|
9
examples/30-dnd5eapi-cc65/dnd5eapi_commands.h
Normal file
9
examples/30-dnd5eapi-cc65/dnd5eapi_commands.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef A2I_DND_COMMANDS_H
|
||||
#define A2I_DND_COMMANDS_H
|
||||
|
||||
/* Apple II <-> ESP Commands */
|
||||
#define COMMAND_SEARCH_MONSTER 20
|
||||
|
||||
/* Responses */
|
||||
|
||||
#endif
|
12
examples/30-dnd5eapi-cc65/iss-tracker/.gitignore
vendored
Normal file
12
examples/30-dnd5eapi-cc65/iss-tracker/.gitignore
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
iss.xex
|
||||
json_test
|
||||
iss.s
|
||||
iss.o
|
||||
nsio.s
|
||||
nsio.o
|
||||
faux_json.s
|
||||
faux_json.o
|
||||
app_key.s
|
||||
app_key.o
|
||||
colors.s
|
||||
colors.o
|
353
examples/30-dnd5eapi-cc65/iss-tracker/apple2/Makefile
Normal file
353
examples/30-dnd5eapi-cc65/iss-tracker/apple2/Makefile
Normal file
@ -0,0 +1,353 @@
|
||||
###############################################################################
|
||||
### Generic Makefile for cc65 projects - full version with abstract options ###
|
||||
### V1.3.0(w) 2010 - 2013 Oliver Schmidt & Patryk "Silver Dream !" Łogiewa ###
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
### In order to override defaults - values can be assigned to the variables ###
|
||||
###############################################################################
|
||||
|
||||
# Space or comma separated list of cc65 supported target platforms to build for.
|
||||
# Default: c64 (lowercase!)
|
||||
TARGETS := apple2
|
||||
|
||||
# Name of the final, single-file executable.
|
||||
# Default: name of the current dir with target name appended
|
||||
PROGRAM := iss
|
||||
|
||||
# Path(s) to additional libraries required for linking the program
|
||||
# Use only if you don't want to place copies of the libraries in SRCDIR
|
||||
# Default: none
|
||||
LIBS :=
|
||||
|
||||
# Custom linker issuration file
|
||||
# Use only if you don't want to place it in SRCDIR
|
||||
# Default: none
|
||||
CONFIG :=
|
||||
|
||||
# Additional C compiler flags and options.
|
||||
# Default: none
|
||||
CFLAGS = -Os --static-locals -DBUILD_APPLE2
|
||||
|
||||
# Additional assembler flags and options.
|
||||
# Default: none
|
||||
ASFLAGS =
|
||||
|
||||
# Additional linker flags and options.
|
||||
# Default: none
|
||||
LDFLAGS = --start-addr 0x4000 --ld-args -D,__HIMEM__=0xBF00 apple2-iobuf-0800.o
|
||||
|
||||
# Path to the directory containing C and ASM sources.
|
||||
# Default: src
|
||||
SRCDIR :=
|
||||
|
||||
# Path to the directory where object files are to be stored (inside respective target subdirectories).
|
||||
# Default: obj
|
||||
OBJDIR :=
|
||||
|
||||
# Command used to run the emulator.
|
||||
# Default: depending on target platform. For default (c64) target: x64 -kernal kernal -VICIIdsize -autoload
|
||||
EMUCMD :=
|
||||
|
||||
# Optional commands used before starting the emulation process, and after finishing it.
|
||||
# Default: none
|
||||
#PREEMUCMD := osascript -e "tell application \"System Events\" to set isRunning to (name of processes) contains \"X11.bin\"" -e "if isRunning is true then tell application \"X11\" to activate"
|
||||
#PREEMUCMD := osascript -e "tell application \"X11\" to activate"
|
||||
#POSTEMUCMD := osascript -e "tell application \"System Events\" to tell process \"X11\" to set visible to false"
|
||||
#POSTEMUCMD := osascript -e "tell application \"Terminal\" to activate"
|
||||
PREEMUCMD :=
|
||||
POSTEMUCMD :=
|
||||
|
||||
# On Windows machines VICE emulators may not be available in the PATH by default.
|
||||
# In such case, please set the variable below to point to directory containing
|
||||
# VICE emulators.
|
||||
#VICE_HOME := "C:\Program Files\WinVICE-2.2-x86\"
|
||||
VICE_HOME :=
|
||||
|
||||
# Options state file name. You should not need to change this, but for those
|
||||
# rare cases when you feel you really need to name it differently - here you are
|
||||
STATEFILE := Makefile.options
|
||||
|
||||
###################################################################################
|
||||
#### DO NOT EDIT BELOW THIS LINE, UNLESS YOU REALLY KNOW WHAT YOU ARE DOING! ####
|
||||
###################################################################################
|
||||
|
||||
###################################################################################
|
||||
### Mapping abstract options to the actual compiler, assembler and linker flags ###
|
||||
### Predefined compiler, assembler and linker flags, used with abstract options ###
|
||||
### valid for 2.14.x. Consult the documentation of your cc65 version before use ###
|
||||
###################################################################################
|
||||
|
||||
# Compiler flags used to tell the compiler to optimise for SPEED
|
||||
define _optspeed_
|
||||
CFLAGS += -Oris
|
||||
endef
|
||||
|
||||
# Compiler flags used to tell the compiler to optimise for SIZE
|
||||
define _optsize_
|
||||
CFLAGS += -Or
|
||||
endef
|
||||
|
||||
# Compiler and assembler flags for generating listings
|
||||
define _listing_
|
||||
CFLAGS += --listing $$(@:.o=.lst)
|
||||
ASFLAGS += --listing $$(@:.o=.lst)
|
||||
REMOVES += $(addsuffix .lst,$(basename $(OBJECTS)))
|
||||
endef
|
||||
|
||||
# Linker flags for generating map file
|
||||
define _mapfile_
|
||||
LDFLAGS += --mapfile $$@.map
|
||||
REMOVES += $(PROGRAM).map
|
||||
endef
|
||||
|
||||
# Linker flags for generating VICE label file
|
||||
define _labelfile_
|
||||
LDFLAGS += -Ln $$@.lbl
|
||||
REMOVES += $(PROGRAM).lbl
|
||||
endef
|
||||
|
||||
# Linker flags for generating a debug file
|
||||
define _debugfile_
|
||||
LDFLAGS += -Wl --dbgfile,$$@.dbg
|
||||
REMOVES += $(PROGRAM).dbg
|
||||
endef
|
||||
|
||||
###############################################################################
|
||||
### Defaults to be used if nothing defined in the editable sections above ###
|
||||
###############################################################################
|
||||
|
||||
# Presume the C64 target like the cl65 compile & link utility does.
|
||||
# Set TARGETS to override.
|
||||
ifeq ($(TARGETS),)
|
||||
TARGETS := c64
|
||||
endif
|
||||
|
||||
# Presume we're in a project directory so name the program like the current
|
||||
# directory. Set PROGRAM to override.
|
||||
ifeq ($(PROGRAM),)
|
||||
PROGRAM := $(notdir $(CURDIR))
|
||||
endif
|
||||
|
||||
# Presume the C and asm source files to be located in the subdirectory 'src'.
|
||||
# Set SRCDIR to override.
|
||||
ifeq ($(SRCDIR),)
|
||||
SRCDIR := src
|
||||
endif
|
||||
|
||||
# Presume the object and dependency files to be located in the subdirectory
|
||||
# 'obj' (which will be created). Set OBJDIR to override.
|
||||
ifeq ($(OBJDIR),)
|
||||
OBJDIR := obj
|
||||
endif
|
||||
TARGETOBJDIR := $(OBJDIR)/$(TARGETS)
|
||||
|
||||
# On Windows it is mandatory to have CC65_HOME set. So do not unnecessarily
|
||||
# rely on cl65 being added to the PATH in this scenario.
|
||||
ifdef CC65_HOME
|
||||
CC := $(CC65_HOME)/bin/cl65
|
||||
else
|
||||
CC := cl65
|
||||
endif
|
||||
|
||||
# Default emulator commands and options for particular targets.
|
||||
# Set EMUCMD to override.
|
||||
c64_EMUCMD := $(VICE_HOME)xscpu64 -VICIIdsize -autostart
|
||||
c128_EMUCMD := $(VICE_HOME)x128 -kernal kernal -VICIIdsize -autoload
|
||||
vic20_EMUCMD := $(VICE_HOME)xvic -kernal kernal -VICdsize -autoload
|
||||
pet_EMUCMD := $(VICE_HOME)xpet -Crtcdsize -autoload
|
||||
plus4_EMUCMD := $(VICE_HOME)xplus4 -TEDdsize -autoload
|
||||
# So far there is no x16 emulator in VICE (why??) so we have to use xplus4 with -memsize option
|
||||
c16_EMUCMD := $(VICE_HOME)xplus4 -ramsize 16 -TEDdsize -autoload
|
||||
cbm510_EMUCMD := $(VICE_HOME)xcbm2 -model 510 -VICIIdsize -autoload
|
||||
cbm610_EMUCMD := $(VICE_HOME)xcbm2 -model 610 -Crtcdsize -autoload
|
||||
atari_EMUCMD := atari800 -windowed -xl -pal -nopatchall -run
|
||||
|
||||
ifeq ($(EMUCMD),)
|
||||
EMUCMD = $($(CC65TARGET)_EMUCMD)
|
||||
endif
|
||||
|
||||
###############################################################################
|
||||
### The magic begins ###
|
||||
###############################################################################
|
||||
|
||||
# The "Native Win32" GNU Make contains quite some workarounds to get along with
|
||||
# cmd.exe as shell. However it does not provide means to determine that it does
|
||||
# actually activate those workarounds. Especially does $(SHELL) NOT contain the
|
||||
# value 'cmd.exe'. So the usual way to determine if cmd.exe is being used is to
|
||||
# execute the command 'echo' without any parameters. Only cmd.exe will return a
|
||||
# non-empy string - saying 'ECHO is on/off'.
|
||||
#
|
||||
# Many "Native Win32" prorams accept '/' as directory delimiter just fine. How-
|
||||
# ever the internal commands of cmd.exe generally require '\' to be used.
|
||||
#
|
||||
# cmd.exe has an internal command 'mkdir' that doesn't understand nor require a
|
||||
# '-p' to create parent directories as needed.
|
||||
#
|
||||
# cmd.exe has an internal command 'del' that reports a syntax error if executed
|
||||
# without any file so make sure to call it only if there's an actual argument.
|
||||
ifeq ($(shell echo),)
|
||||
MKDIR = mkdir -p $1
|
||||
RMDIR = rmdir $1
|
||||
RMFILES = $(RM) $1
|
||||
else
|
||||
MKDIR = mkdir $(subst /,\,$1)
|
||||
RMDIR = rmdir $(subst /,\,$1)
|
||||
RMFILES = $(if $1,del /f $(subst /,\,$1))
|
||||
endif
|
||||
COMMA := ,
|
||||
SPACE := $(N/A) $(N/A)
|
||||
define NEWLINE
|
||||
|
||||
|
||||
endef
|
||||
# Note: Do not remove any of the two empty lines above !
|
||||
|
||||
TARGETLIST := $(subst $(COMMA),$(SPACE),$(TARGETS))
|
||||
|
||||
ifeq ($(words $(TARGETLIST)),1)
|
||||
|
||||
# Set PROGRAM to something like 'myprog.c64'.
|
||||
override PROGRAM := $(PROGRAM)
|
||||
|
||||
# Set SOURCES to something like 'src/foo.c src/bar.s'.
|
||||
# Use of assembler files with names ending differently than .s is deprecated!
|
||||
SOURCES := $(wildcard $(SRCDIR)/*.c)
|
||||
SOURCES += $(wildcard $(SRCDIR)/*.s)
|
||||
SOURCES += $(wildcard $(SRCDIR)/*.asm)
|
||||
SOURCES += $(wildcard $(SRCDIR)/*.a65)
|
||||
|
||||
# Add to SOURCES something like 'src/c64/me.c src/c64/too.s'.
|
||||
# Use of assembler files with names ending differently than .s is deprecated!
|
||||
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.c)
|
||||
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.s)
|
||||
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.asm)
|
||||
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.a65)
|
||||
|
||||
# Set OBJECTS to something like 'obj/c64/foo.o obj/c64/bar.o'.
|
||||
OBJECTS := $(addsuffix .o,$(basename $(addprefix $(TARGETOBJDIR)/,$(notdir $(SOURCES)))))
|
||||
|
||||
# Set DEPENDS to something like 'obj/c64/foo.d obj/c64/bar.d'.
|
||||
DEPENDS := $(OBJECTS:.o=.d)
|
||||
|
||||
# Add to LIBS something like 'src/foo.lib src/c64/bar.lib'.
|
||||
LIBS += $(wildcard $(SRCDIR)/*.lib)
|
||||
LIBS += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.lib)
|
||||
|
||||
# Add to CONFIG something like 'src/c64/bar.cfg src/foo.cfg'.
|
||||
CONFIG += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.cfg)
|
||||
CONFIG += $(wildcard $(SRCDIR)/*.cfg)
|
||||
|
||||
# Select CONFIG file to use. Target specific isss have higher priority.
|
||||
ifneq ($(word 2,$(CONFIG)),)
|
||||
CONFIG := $(firstword $(CONFIG))
|
||||
$(info Using iss file $(CONFIG) for linking)
|
||||
endif
|
||||
|
||||
.SUFFIXES:
|
||||
.PHONY: all test clean zap love
|
||||
|
||||
all: $(PROGRAM)
|
||||
|
||||
-include $(DEPENDS)
|
||||
-include $(STATEFILE)
|
||||
|
||||
# If OPTIONS are given on the command line then save them to STATEFILE
|
||||
# if (and only if) they have actually changed. But if OPTIONS are not
|
||||
# given on the command line then load them from STATEFILE. Have object
|
||||
# files depend on STATEFILE only if it actually exists.
|
||||
ifeq ($(origin OPTIONS),command line)
|
||||
ifneq ($(OPTIONS),$(_OPTIONS_))
|
||||
ifeq ($(OPTIONS),)
|
||||
$(info Removing OPTIONS)
|
||||
$(shell $(RM) $(STATEFILE))
|
||||
$(eval $(STATEFILE):)
|
||||
else
|
||||
$(info Saving OPTIONS=$(OPTIONS))
|
||||
$(shell echo _OPTIONS_=$(OPTIONS) > $(STATEFILE))
|
||||
endif
|
||||
$(eval $(OBJECTS): $(STATEFILE))
|
||||
endif
|
||||
else
|
||||
ifeq ($(origin _OPTIONS_),file)
|
||||
$(info Using saved OPTIONS=$(_OPTIONS_))
|
||||
OPTIONS = $(_OPTIONS_)
|
||||
$(eval $(OBJECTS): $(STATEFILE))
|
||||
endif
|
||||
endif
|
||||
|
||||
# Transform the abstract OPTIONS to the actual cc65 options.
|
||||
$(foreach o,$(subst $(COMMA),$(SPACE),$(OPTIONS)),$(eval $(_$o_)))
|
||||
|
||||
# Strip potential variant suffix from the actual cc65 target.
|
||||
CC65TARGET := $(firstword $(subst .,$(SPACE),$(TARGETLIST)))
|
||||
|
||||
# The remaining targets.
|
||||
$(TARGETOBJDIR):
|
||||
$(call MKDIR,$@)
|
||||
|
||||
vpath %.c $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
|
||||
|
||||
$(TARGETOBJDIR)/%.o: %.c | $(TARGETOBJDIR)
|
||||
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(CFLAGS) -o $@ $<
|
||||
|
||||
vpath %.s $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
|
||||
|
||||
$(TARGETOBJDIR)/%.o: %.s | $(TARGETOBJDIR)
|
||||
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
|
||||
|
||||
vpath %.asm $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
|
||||
|
||||
$(TARGETOBJDIR)/%.o: %.asm | $(TARGETOBJDIR)
|
||||
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
|
||||
|
||||
vpath %.a65 $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
|
||||
|
||||
$(TARGETOBJDIR)/%.o: %.a65 | $(TARGETOBJDIR)
|
||||
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
|
||||
|
||||
$(PROGRAM): $(CONFIG) $(OBJECTS) $(LIBS)
|
||||
$(CC) -t $(CC65TARGET) $(LDFLAGS) -o $@ $(patsubst %.cfg,-C %.cfg,$^)
|
||||
|
||||
test: $(PROGRAM)
|
||||
$(PREEMUCMD)
|
||||
$(EMUCMD) $<
|
||||
$(POSTEMUCMD)
|
||||
|
||||
dist: $(PROGRAM)
|
||||
cp dist.apple2/bootable.po dist.apple2/dist.po
|
||||
java -jar dist.apple2/ac.jar -p dist.apple2/dist.po iss.system sys <dist.apple2/iss.system
|
||||
java -jar dist.apple2/ac.jar -as dist.apple2/dist.po iss bin <iss
|
||||
java -jar dist.apple2/ac.jar -p dist.apple2/dist.po MAP.HGR bin <gfx/MAP.HGR
|
||||
cp dist.apple2/dist.po /run/media/equant/BMOW/equant/
|
||||
|
||||
clean:
|
||||
$(call RMFILES,$(OBJECTS))
|
||||
$(call RMFILES,$(DEPENDS))
|
||||
$(call RMFILES,$(REMOVES))
|
||||
$(call RMFILES,$(PROGRAM))
|
||||
$(call RMFILES,*.map)
|
||||
|
||||
else # $(words $(TARGETLIST)),1
|
||||
|
||||
all test clean:
|
||||
$(foreach t,$(TARGETLIST),$(MAKE) TARGETS=$t $@$(NEWLINE))
|
||||
|
||||
endif # $(words $(TARGETLIST)),1
|
||||
|
||||
OBJDIRLIST := $(wildcard $(OBJDIR)/*)
|
||||
|
||||
zap:
|
||||
$(foreach o,$(OBJDIRLIST),-$(call RMFILES,$o/*.o $o/*.d $o/*.lst)$(NEWLINE))
|
||||
$(foreach o,$(OBJDIRLIST),-$(call RMDIR,$o)$(NEWLINE))
|
||||
-$(call RMDIR,$(OBJDIR))
|
||||
-$(call RMFILES,$(basename $(PROGRAM)).* $(STATEFILE))
|
||||
|
||||
love:
|
||||
@echo "Not war, eh?"
|
||||
|
||||
###################################################################
|
||||
### Place your additional targets in the additional Makefiles ###
|
||||
### in the same directory - their names have to end with ".mk"! ###
|
||||
###################################################################
|
||||
-include *.mk
|
352
examples/30-dnd5eapi-cc65/iss-tracker/apple2/Makefile.original
Normal file
352
examples/30-dnd5eapi-cc65/iss-tracker/apple2/Makefile.original
Normal file
@ -0,0 +1,352 @@
|
||||
###############################################################################
|
||||
### Generic Makefile for cc65 projects - full version with abstract options ###
|
||||
### V1.3.0(w) 2010 - 2013 Oliver Schmidt & Patryk "Silver Dream !" Łogiewa ###
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
### In order to override defaults - values can be assigned to the variables ###
|
||||
###############################################################################
|
||||
|
||||
# Space or comma separated list of cc65 supported target platforms to build for.
|
||||
# Default: c64 (lowercase!)
|
||||
TARGETS := apple2 apple.ip65
|
||||
|
||||
# Name of the final, single-file executable.
|
||||
# Default: name of the current dir with target name appended
|
||||
PROGRAM := iss
|
||||
|
||||
# Path(s) to additional libraries required for linking the program
|
||||
# Use only if you don't want to place copies of the libraries in SRCDIR
|
||||
# Default: none
|
||||
LIBS :=
|
||||
|
||||
# Custom linker issuration file
|
||||
# Use only if you don't want to place it in SRCDIR
|
||||
# Default: none
|
||||
CONFIG :=
|
||||
|
||||
# Additional C compiler flags and options.
|
||||
# Default: none
|
||||
CFLAGS = -Os --static-locals -DBUILD_APPLE2
|
||||
|
||||
# Additional assembler flags and options.
|
||||
# Default: none
|
||||
ASFLAGS =
|
||||
|
||||
# Additional linker flags and options.
|
||||
# Default: none
|
||||
LDFLAGS = --start-addr 0x4000 --ld-args -D,__HIMEM__=0xBF00 apple2-iobuf-0800.o
|
||||
|
||||
# Path to the directory containing C and ASM sources.
|
||||
# Default: src
|
||||
SRCDIR :=
|
||||
|
||||
# Path to the directory where object files are to be stored (inside respective target subdirectories).
|
||||
# Default: obj
|
||||
OBJDIR :=
|
||||
|
||||
# Command used to run the emulator.
|
||||
# Default: depending on target platform. For default (c64) target: x64 -kernal kernal -VICIIdsize -autoload
|
||||
EMUCMD :=
|
||||
|
||||
# Optional commands used before starting the emulation process, and after finishing it.
|
||||
# Default: none
|
||||
#PREEMUCMD := osascript -e "tell application \"System Events\" to set isRunning to (name of processes) contains \"X11.bin\"" -e "if isRunning is true then tell application \"X11\" to activate"
|
||||
#PREEMUCMD := osascript -e "tell application \"X11\" to activate"
|
||||
#POSTEMUCMD := osascript -e "tell application \"System Events\" to tell process \"X11\" to set visible to false"
|
||||
#POSTEMUCMD := osascript -e "tell application \"Terminal\" to activate"
|
||||
PREEMUCMD :=
|
||||
POSTEMUCMD :=
|
||||
|
||||
# On Windows machines VICE emulators may not be available in the PATH by default.
|
||||
# In such case, please set the variable below to point to directory containing
|
||||
# VICE emulators.
|
||||
#VICE_HOME := "C:\Program Files\WinVICE-2.2-x86\"
|
||||
VICE_HOME :=
|
||||
|
||||
# Options state file name. You should not need to change this, but for those
|
||||
# rare cases when you feel you really need to name it differently - here you are
|
||||
STATEFILE := Makefile.options
|
||||
|
||||
###################################################################################
|
||||
#### DO NOT EDIT BELOW THIS LINE, UNLESS YOU REALLY KNOW WHAT YOU ARE DOING! ####
|
||||
###################################################################################
|
||||
|
||||
###################################################################################
|
||||
### Mapping abstract options to the actual compiler, assembler and linker flags ###
|
||||
### Predefined compiler, assembler and linker flags, used with abstract options ###
|
||||
### valid for 2.14.x. Consult the documentation of your cc65 version before use ###
|
||||
###################################################################################
|
||||
|
||||
# Compiler flags used to tell the compiler to optimise for SPEED
|
||||
define _optspeed_
|
||||
CFLAGS += -Oris
|
||||
endef
|
||||
|
||||
# Compiler flags used to tell the compiler to optimise for SIZE
|
||||
define _optsize_
|
||||
CFLAGS += -Or
|
||||
endef
|
||||
|
||||
# Compiler and assembler flags for generating listings
|
||||
define _listing_
|
||||
CFLAGS += --listing $$(@:.o=.lst)
|
||||
ASFLAGS += --listing $$(@:.o=.lst)
|
||||
REMOVES += $(addsuffix .lst,$(basename $(OBJECTS)))
|
||||
endef
|
||||
|
||||
# Linker flags for generating map file
|
||||
define _mapfile_
|
||||
LDFLAGS += --mapfile $$@.map
|
||||
REMOVES += $(PROGRAM).map
|
||||
endef
|
||||
|
||||
# Linker flags for generating VICE label file
|
||||
define _labelfile_
|
||||
LDFLAGS += -Ln $$@.lbl
|
||||
REMOVES += $(PROGRAM).lbl
|
||||
endef
|
||||
|
||||
# Linker flags for generating a debug file
|
||||
define _debugfile_
|
||||
LDFLAGS += -Wl --dbgfile,$$@.dbg
|
||||
REMOVES += $(PROGRAM).dbg
|
||||
endef
|
||||
|
||||
###############################################################################
|
||||
### Defaults to be used if nothing defined in the editable sections above ###
|
||||
###############################################################################
|
||||
|
||||
# Presume the C64 target like the cl65 compile & link utility does.
|
||||
# Set TARGETS to override.
|
||||
ifeq ($(TARGETS),)
|
||||
TARGETS := c64
|
||||
endif
|
||||
|
||||
# Presume we're in a project directory so name the program like the current
|
||||
# directory. Set PROGRAM to override.
|
||||
ifeq ($(PROGRAM),)
|
||||
PROGRAM := $(notdir $(CURDIR))
|
||||
endif
|
||||
|
||||
# Presume the C and asm source files to be located in the subdirectory 'src'.
|
||||
# Set SRCDIR to override.
|
||||
ifeq ($(SRCDIR),)
|
||||
SRCDIR := src
|
||||
endif
|
||||
|
||||
# Presume the object and dependency files to be located in the subdirectory
|
||||
# 'obj' (which will be created). Set OBJDIR to override.
|
||||
ifeq ($(OBJDIR),)
|
||||
OBJDIR := obj
|
||||
endif
|
||||
TARGETOBJDIR := $(OBJDIR)/$(TARGETS)
|
||||
|
||||
# On Windows it is mandatory to have CC65_HOME set. So do not unnecessarily
|
||||
# rely on cl65 being added to the PATH in this scenario.
|
||||
ifdef CC65_HOME
|
||||
CC := $(CC65_HOME)/bin/cl65
|
||||
else
|
||||
CC := cl65
|
||||
endif
|
||||
|
||||
# Default emulator commands and options for particular targets.
|
||||
# Set EMUCMD to override.
|
||||
c64_EMUCMD := $(VICE_HOME)xscpu64 -VICIIdsize -autostart
|
||||
c128_EMUCMD := $(VICE_HOME)x128 -kernal kernal -VICIIdsize -autoload
|
||||
vic20_EMUCMD := $(VICE_HOME)xvic -kernal kernal -VICdsize -autoload
|
||||
pet_EMUCMD := $(VICE_HOME)xpet -Crtcdsize -autoload
|
||||
plus4_EMUCMD := $(VICE_HOME)xplus4 -TEDdsize -autoload
|
||||
# So far there is no x16 emulator in VICE (why??) so we have to use xplus4 with -memsize option
|
||||
c16_EMUCMD := $(VICE_HOME)xplus4 -ramsize 16 -TEDdsize -autoload
|
||||
cbm510_EMUCMD := $(VICE_HOME)xcbm2 -model 510 -VICIIdsize -autoload
|
||||
cbm610_EMUCMD := $(VICE_HOME)xcbm2 -model 610 -Crtcdsize -autoload
|
||||
atari_EMUCMD := atari800 -windowed -xl -pal -nopatchall -run
|
||||
|
||||
ifeq ($(EMUCMD),)
|
||||
EMUCMD = $($(CC65TARGET)_EMUCMD)
|
||||
endif
|
||||
|
||||
###############################################################################
|
||||
### The magic begins ###
|
||||
###############################################################################
|
||||
|
||||
# The "Native Win32" GNU Make contains quite some workarounds to get along with
|
||||
# cmd.exe as shell. However it does not provide means to determine that it does
|
||||
# actually activate those workarounds. Especially does $(SHELL) NOT contain the
|
||||
# value 'cmd.exe'. So the usual way to determine if cmd.exe is being used is to
|
||||
# execute the command 'echo' without any parameters. Only cmd.exe will return a
|
||||
# non-empy string - saying 'ECHO is on/off'.
|
||||
#
|
||||
# Many "Native Win32" prorams accept '/' as directory delimiter just fine. How-
|
||||
# ever the internal commands of cmd.exe generally require '\' to be used.
|
||||
#
|
||||
# cmd.exe has an internal command 'mkdir' that doesn't understand nor require a
|
||||
# '-p' to create parent directories as needed.
|
||||
#
|
||||
# cmd.exe has an internal command 'del' that reports a syntax error if executed
|
||||
# without any file so make sure to call it only if there's an actual argument.
|
||||
ifeq ($(shell echo),)
|
||||
MKDIR = mkdir -p $1
|
||||
RMDIR = rmdir $1
|
||||
RMFILES = $(RM) $1
|
||||
else
|
||||
MKDIR = mkdir $(subst /,\,$1)
|
||||
RMDIR = rmdir $(subst /,\,$1)
|
||||
RMFILES = $(if $1,del /f $(subst /,\,$1))
|
||||
endif
|
||||
COMMA := ,
|
||||
SPACE := $(N/A) $(N/A)
|
||||
define NEWLINE
|
||||
|
||||
|
||||
endef
|
||||
# Note: Do not remove any of the two empty lines above !
|
||||
|
||||
TARGETLIST := $(subst $(COMMA),$(SPACE),$(TARGETS))
|
||||
|
||||
ifeq ($(words $(TARGETLIST)),1)
|
||||
|
||||
# Set PROGRAM to something like 'myprog.c64'.
|
||||
override PROGRAM := $(PROGRAM)
|
||||
|
||||
# Set SOURCES to something like 'src/foo.c src/bar.s'.
|
||||
# Use of assembler files with names ending differently than .s is deprecated!
|
||||
SOURCES := $(wildcard $(SRCDIR)/*.c)
|
||||
SOURCES += $(wildcard $(SRCDIR)/*.s)
|
||||
SOURCES += $(wildcard $(SRCDIR)/*.asm)
|
||||
SOURCES += $(wildcard $(SRCDIR)/*.a65)
|
||||
|
||||
# Add to SOURCES something like 'src/c64/me.c src/c64/too.s'.
|
||||
# Use of assembler files with names ending differently than .s is deprecated!
|
||||
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.c)
|
||||
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.s)
|
||||
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.asm)
|
||||
SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.a65)
|
||||
|
||||
# Set OBJECTS to something like 'obj/c64/foo.o obj/c64/bar.o'.
|
||||
OBJECTS := $(addsuffix .o,$(basename $(addprefix $(TARGETOBJDIR)/,$(notdir $(SOURCES)))))
|
||||
|
||||
# Set DEPENDS to something like 'obj/c64/foo.d obj/c64/bar.d'.
|
||||
DEPENDS := $(OBJECTS:.o=.d)
|
||||
|
||||
# Add to LIBS something like 'src/foo.lib src/c64/bar.lib'.
|
||||
LIBS += $(wildcard $(SRCDIR)/*.lib)
|
||||
LIBS += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.lib)
|
||||
|
||||
# Add to CONFIG something like 'src/c64/bar.cfg src/foo.cfg'.
|
||||
CONFIG += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.cfg)
|
||||
CONFIG += $(wildcard $(SRCDIR)/*.cfg)
|
||||
|
||||
# Select CONFIG file to use. Target specific isss have higher priority.
|
||||
ifneq ($(word 2,$(CONFIG)),)
|
||||
CONFIG := $(firstword $(CONFIG))
|
||||
$(info Using iss file $(CONFIG) for linking)
|
||||
endif
|
||||
|
||||
.SUFFIXES:
|
||||
.PHONY: all test clean zap love
|
||||
|
||||
all: $(PROGRAM)
|
||||
|
||||
-include $(DEPENDS)
|
||||
-include $(STATEFILE)
|
||||
|
||||
# If OPTIONS are given on the command line then save them to STATEFILE
|
||||
# if (and only if) they have actually changed. But if OPTIONS are not
|
||||
# given on the command line then load them from STATEFILE. Have object
|
||||
# files depend on STATEFILE only if it actually exists.
|
||||
ifeq ($(origin OPTIONS),command line)
|
||||
ifneq ($(OPTIONS),$(_OPTIONS_))
|
||||
ifeq ($(OPTIONS),)
|
||||
$(info Removing OPTIONS)
|
||||
$(shell $(RM) $(STATEFILE))
|
||||
$(eval $(STATEFILE):)
|
||||
else
|
||||
$(info Saving OPTIONS=$(OPTIONS))
|
||||
$(shell echo _OPTIONS_=$(OPTIONS) > $(STATEFILE))
|
||||
endif
|
||||
$(eval $(OBJECTS): $(STATEFILE))
|
||||
endif
|
||||
else
|
||||
ifeq ($(origin _OPTIONS_),file)
|
||||
$(info Using saved OPTIONS=$(_OPTIONS_))
|
||||
OPTIONS = $(_OPTIONS_)
|
||||
$(eval $(OBJECTS): $(STATEFILE))
|
||||
endif
|
||||
endif
|
||||
|
||||
# Transform the abstract OPTIONS to the actual cc65 options.
|
||||
$(foreach o,$(subst $(COMMA),$(SPACE),$(OPTIONS)),$(eval $(_$o_)))
|
||||
|
||||
# Strip potential variant suffix from the actual cc65 target.
|
||||
CC65TARGET := $(firstword $(subst .,$(SPACE),$(TARGETLIST)))
|
||||
|
||||
# The remaining targets.
|
||||
$(TARGETOBJDIR):
|
||||
$(call MKDIR,$@)
|
||||
|
||||
vpath %.c $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
|
||||
|
||||
$(TARGETOBJDIR)/%.o: %.c | $(TARGETOBJDIR)
|
||||
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(CFLAGS) -o $@ $<
|
||||
|
||||
vpath %.s $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
|
||||
|
||||
$(TARGETOBJDIR)/%.o: %.s | $(TARGETOBJDIR)
|
||||
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
|
||||
|
||||
vpath %.asm $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
|
||||
|
||||
$(TARGETOBJDIR)/%.o: %.asm | $(TARGETOBJDIR)
|
||||
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
|
||||
|
||||
vpath %.a65 $(SRCDIR)/$(TARGETLIST) $(SRCDIR)
|
||||
|
||||
$(TARGETOBJDIR)/%.o: %.a65 | $(TARGETOBJDIR)
|
||||
$(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $<
|
||||
|
||||
$(PROGRAM): $(CONFIG) $(OBJECTS) $(LIBS)
|
||||
$(CC) -t $(CC65TARGET) $(LDFLAGS) -o $@ $(patsubst %.cfg,-C %.cfg,$^)
|
||||
|
||||
test: $(PROGRAM)
|
||||
$(PREEMUCMD)
|
||||
$(EMUCMD) $<
|
||||
$(POSTEMUCMD)
|
||||
|
||||
dist: $(PROGRAM)
|
||||
cp dist.apple2/bootable.po dist.apple2/dist.po
|
||||
java -jar dist.apple2/ac.jar -p dist.apple2/dist.po iss.system sys <dist.apple2/iss.system
|
||||
java -jar dist.apple2/ac.jar -as dist.apple2/dist.po iss bin <iss
|
||||
java -jar dist.apple2/ac.jar -p dist.apple2/dist.po MAP.HGR bin <gfx/MAP.HGR
|
||||
|
||||
clean:
|
||||
$(call RMFILES,$(OBJECTS))
|
||||
$(call RMFILES,$(DEPENDS))
|
||||
$(call RMFILES,$(REMOVES))
|
||||
$(call RMFILES,$(PROGRAM))
|
||||
$(call RMFILES,*.map)
|
||||
|
||||
else # $(words $(TARGETLIST)),1
|
||||
|
||||
all test clean:
|
||||
$(foreach t,$(TARGETLIST),$(MAKE) TARGETS=$t $@$(NEWLINE))
|
||||
|
||||
endif # $(words $(TARGETLIST)),1
|
||||
|
||||
OBJDIRLIST := $(wildcard $(OBJDIR)/*)
|
||||
|
||||
zap:
|
||||
$(foreach o,$(OBJDIRLIST),-$(call RMFILES,$o/*.o $o/*.d $o/*.lst)$(NEWLINE))
|
||||
$(foreach o,$(OBJDIRLIST),-$(call RMDIR,$o)$(NEWLINE))
|
||||
-$(call RMDIR,$(OBJDIR))
|
||||
-$(call RMFILES,$(basename $(PROGRAM)).* $(STATEFILE))
|
||||
|
||||
love:
|
||||
@echo "Not war, eh?"
|
||||
|
||||
###################################################################
|
||||
### Place your additional targets in the additional Makefiles ###
|
||||
### in the same directory - their names have to end with ".mk"! ###
|
||||
###################################################################
|
||||
-include *.mk
|
BIN
examples/30-dnd5eapi-cc65/iss-tracker/apple2/apple2/ac.jar
Normal file
BIN
examples/30-dnd5eapi-cc65/iss-tracker/apple2/apple2/ac.jar
Normal file
Binary file not shown.
BIN
examples/30-dnd5eapi-cc65/iss-tracker/apple2/apple2/bootable.po
Normal file
BIN
examples/30-dnd5eapi-cc65/iss-tracker/apple2/apple2/bootable.po
Normal file
Binary file not shown.
BIN
examples/30-dnd5eapi-cc65/iss-tracker/apple2/apple2/dist.po
Normal file
BIN
examples/30-dnd5eapi-cc65/iss-tracker/apple2/apple2/dist.po
Normal file
Binary file not shown.
BIN
examples/30-dnd5eapi-cc65/iss-tracker/apple2/apple2/iss.system
Normal file
BIN
examples/30-dnd5eapi-cc65/iss-tracker/apple2/apple2/iss.system
Normal file
Binary file not shown.
BIN
examples/30-dnd5eapi-cc65/iss-tracker/apple2/dist.apple2/ac.jar
Normal file
BIN
examples/30-dnd5eapi-cc65/iss-tracker/apple2/dist.apple2/ac.jar
Normal file
Binary file not shown.
Binary file not shown.
BIN
examples/30-dnd5eapi-cc65/iss-tracker/apple2/dist.apple2/dist.po
Normal file
BIN
examples/30-dnd5eapi-cc65/iss-tracker/apple2/dist.apple2/dist.po
Normal file
Binary file not shown.
Binary file not shown.
BIN
examples/30-dnd5eapi-cc65/iss-tracker/apple2/gfx/MAP.HGR
Normal file
BIN
examples/30-dnd5eapi-cc65/iss-tracker/apple2/gfx/MAP.HGR
Normal file
Binary file not shown.
BIN
examples/30-dnd5eapi-cc65/iss-tracker/apple2/gfx/iss-apple2.png
Normal file
BIN
examples/30-dnd5eapi-cc65/iss-tracker/apple2/gfx/iss-apple2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
BIN
examples/30-dnd5eapi-cc65/iss-tracker/apple2/iss
Normal file
BIN
examples/30-dnd5eapi-cc65/iss-tracker/apple2/iss
Normal file
Binary file not shown.
@ -0,0 +1,4 @@
|
||||
obj/apple2/apple2idiot.o: src/apple2idiot.c src/apple2idiot.h
|
||||
|
||||
src/apple2idiot.c src/apple2idiot.h:
|
||||
|
@ -0,0 +1,4 @@
|
||||
obj/apple2/main.o: src/main.c src/map.h src/satellite.h src/osd.h src/apple2idiot.h
|
||||
|
||||
src/main.c src/map.h src/satellite.h src/osd.h src/apple2idiot.h:
|
||||
|
@ -0,0 +1,4 @@
|
||||
obj/apple2/map.o: src/map.c
|
||||
|
||||
src/map.c:
|
||||
|
@ -0,0 +1,4 @@
|
||||
obj/apple2/osd.o: src/osd.c
|
||||
|
||||
src/osd.c:
|
||||
|
@ -0,0 +1,4 @@
|
||||
obj/apple2/satellite.o: src/satellite.c src/satellite.h src/apple2idiot.h
|
||||
|
||||
src/satellite.c src/satellite.h src/apple2idiot.h:
|
||||
|
@ -0,0 +1,4 @@
|
||||
obj/apple2/sp.o: src/sp.c src/sp.h
|
||||
|
||||
src/sp.c src/sp.h:
|
||||
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,412 @@
|
||||
#ifndef _IP65_H
|
||||
#define _IP65_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// Ethernet driver initialization parameter values
|
||||
//
|
||||
#if defined(__APPLE2__)
|
||||
#define ETH_INIT_DEFAULT 3 // Apple II slot number
|
||||
#elif defined(__ATARI__)
|
||||
#define ETH_INIT_DEFAULT 8 // ATARI PBI device ID
|
||||
#else
|
||||
#define ETH_INIT_DEFAULT 0 // Unused
|
||||
#endif
|
||||
|
||||
// Initialize the IP stack
|
||||
//
|
||||
// This calls the individual protocol & driver initializations, so this is
|
||||
// the only *_init routine that must be called by a user application,
|
||||
// except for dhcp_init which must also be called if the application
|
||||
// is using DHCP rather than hardcoded IP configuration.
|
||||
//
|
||||
// Inputs: eth_init: Ethernet driver initialization parameter
|
||||
// Output: true if there was an error, false otherwise
|
||||
//
|
||||
bool __fastcall__ ip65_init(uint8_t eth_init);
|
||||
|
||||
// Access to Ethernet configuration
|
||||
//
|
||||
// Access to the two items below is only valid after ip65_init returned false.
|
||||
//
|
||||
extern uint8_t cfg_mac[6]; // MAC address of local machine
|
||||
extern char eth_name[]; // Zero terminated string containing Ethernet driver name
|
||||
|
||||
// Error codes
|
||||
//
|
||||
#define IP65_ERROR_PORT_IN_USE 0x80
|
||||
#define IP65_ERROR_TIMEOUT_ON_RECEIVE 0x81
|
||||
#define IP65_ERROR_TRANSMIT_FAILED 0x82
|
||||
#define IP65_ERROR_TRANSMISSION_REJECTED_BY_PEER 0x83
|
||||
#define IP65_ERROR_NAME_TOO_LONG 0x84
|
||||
#define IP65_ERROR_DEVICE_FAILURE 0x85
|
||||
#define IP65_ERROR_ABORTED_BY_USER 0x86
|
||||
#define IP65_ERROR_LISTENER_NOT_AVAILABLE 0x87
|
||||
#define IP65_ERROR_CONNECTION_RESET_BY_PEER 0x89
|
||||
#define IP65_ERROR_CONNECTION_CLOSED 0x8A
|
||||
#define IP65_ERROR_MALFORMED_URL 0xA0
|
||||
#define IP65_ERROR_DNS_LOOKUP_FAILED 0xA1
|
||||
|
||||
// Last error code
|
||||
//
|
||||
extern uint8_t ip65_error;
|
||||
|
||||
// Convert error code into a string describing the error
|
||||
//
|
||||
// The pointer returned is a static string, which mustn't be modified.
|
||||
//
|
||||
// Inputs: err_code: Error code
|
||||
// Output: Zero terminated string describing the error
|
||||
//
|
||||
char* __fastcall__ ip65_strerror(uint8_t err_code);
|
||||
|
||||
// Main IP polling loop
|
||||
//
|
||||
// This routine should be periodically called by an application at any time
|
||||
// that an inbound packet needs to be handled.
|
||||
// It is 'non-blocking', i.e. it will return if there is no packet waiting to be
|
||||
// handled. Any inbound packet will be handed off to the appropriate handler.
|
||||
//
|
||||
// Inputs: None
|
||||
// Output: true if no packet was waiting or packet handling caused error, false otherwise
|
||||
//
|
||||
bool ip65_process(void);
|
||||
|
||||
// Generate a 'random' 16 bit word
|
||||
//
|
||||
// Entropy comes from the last ethernet frame, counters, and timer.
|
||||
//
|
||||
// Inputs: None
|
||||
// Output: Pseudo-random 16 bit number
|
||||
//
|
||||
uint16_t ip65_random_word(void);
|
||||
|
||||
// Convert 4 octets (IP address, netmask) into a string representing a dotted quad
|
||||
//
|
||||
// The string is returned in a statically allocated buffer, which subsequent calls
|
||||
// will overwrite.
|
||||
//
|
||||
// Inputs: quad: IP address
|
||||
// Output: Zero terminated string containing dotted quad (e.g. "192.168.1.0")
|
||||
//
|
||||
char* __fastcall__ dotted_quad(uint32_t quad);
|
||||
|
||||
// Convert a string representing a dotted quad (IP address, netmask) into 4 octets
|
||||
//
|
||||
// Inputs: quad: Zero terminated string containing dotted quad (e.g. "192.168.1.0"),
|
||||
// to simplify URL parsing, a ':' or '/' can also terminate the string.
|
||||
// Output: IP address, 0 on error
|
||||
//
|
||||
uint32_t __fastcall__ parse_dotted_quad(char* quad);
|
||||
|
||||
// Minimal DHCP client implementation
|
||||
//
|
||||
// IP addresses are requested from a DHCP server (aka 'leased') but are not renewed
|
||||
// or released. Although this is not correct behaviour according to the DHCP RFC,
|
||||
// this works fine in practice in a typical home network environment.
|
||||
//
|
||||
// Inputs: None (although ip65_init should be called first)
|
||||
// Output: false if IP config has been sucesfully obtained and cfg_ip, cfg_netmask,
|
||||
// cfg_gateway and cfg_dns will be set per response from dhcp server.
|
||||
// dhcp_server will be set to address of server that provided configuration.
|
||||
// true if there was an error
|
||||
//
|
||||
bool dhcp_init(void);
|
||||
|
||||
// Access to IP configuration
|
||||
//
|
||||
// The five items below will be overwritten if dhcp_init is called.
|
||||
//
|
||||
extern uint32_t cfg_ip; // IP address of local machine
|
||||
extern uint32_t cfg_netmask; // Netmask of local network
|
||||
extern uint32_t cfg_gateway; // IP address of router on local network
|
||||
extern uint32_t cfg_dns; // IP address of DNS server to use
|
||||
extern uint32_t dhcp_server; // Address of DHCP server that config was obtained from
|
||||
|
||||
// Resolve a string containing a hostname (or a dotted quad) to an IP address
|
||||
//
|
||||
// Inputs: hostname: Zero terminated string containing either a DNS hostname
|
||||
// (e.g. "host.example.com") or an address in "dotted quad"
|
||||
// format (e.g. "192.168.1.0")
|
||||
// Output: IP address of the hostname, 0 on error
|
||||
//
|
||||
uint32_t __fastcall__ dns_resolve(const char* hostname);
|
||||
|
||||
// Send a ping (ICMP echo request) to a remote host, and wait for a response
|
||||
//
|
||||
// Inputs: dest: Destination IP address
|
||||
// Output: 0 if no response, otherwise time (in miliseconds) for host to respond
|
||||
//
|
||||
uint16_t __fastcall__ icmp_ping(uint32_t dest);
|
||||
|
||||
// Add a UDP listener
|
||||
//
|
||||
// Inputs: port: UDP port to listen on
|
||||
// callback: Vector to call when UDP packet arrives on specified port
|
||||
// Output: true if too may listeners already installed, false otherwise
|
||||
//
|
||||
bool __fastcall__ udp_add_listener(uint16_t port, void (*callback)(void));
|
||||
|
||||
// Remove a UDP listener
|
||||
//
|
||||
// Inputs: port: UDP port to stop listening on
|
||||
// Output: false if handler found and removed,
|
||||
// true if handler for specified port not found
|
||||
//
|
||||
bool __fastcall__ udp_remove_listener(uint16_t port);
|
||||
|
||||
// Access to received UDP packet
|
||||
//
|
||||
// Access to the four items below is only valid in the context of a callback
|
||||
// added with udp_add_listener.
|
||||
//
|
||||
extern uint8_t udp_recv_buf[1476]; // Buffer with data received
|
||||
uint16_t udp_recv_len(void); // Length of data received
|
||||
uint32_t udp_recv_src(void); // Source IP address
|
||||
uint16_t udp_recv_src_port(void); // Source port
|
||||
|
||||
// Send a UDP packet
|
||||
//
|
||||
// If the correct MAC address can't be found in the ARP cache then
|
||||
// an ARP request is sent - and the UDP packet is NOT sent. The caller
|
||||
// should wait a while calling ip65_process (to allow time for an ARP
|
||||
// response to arrive) and then call upd_send again. This behavior
|
||||
// makes sense as a UDP packet may get lost in transit at any time
|
||||
// so the caller should to be prepared to resend it after a while
|
||||
// anyway.
|
||||
//
|
||||
// Inputs: buf: Pointer to buffer containing data to be sent
|
||||
// len: Length of data to send (exclusive of any headers)
|
||||
// dest: Destination IP address
|
||||
// dest_port: Destination port
|
||||
// src_port: Source port
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool __fastcall__ udp_send(const uint8_t* buf, uint16_t len, uint32_t dest,
|
||||
uint16_t dest_port, uint16_t src_port);
|
||||
|
||||
// Listen for an inbound TCP connection
|
||||
//
|
||||
// This is a 'blocking' call, i.e. it will not return until a connection has been made.
|
||||
//
|
||||
// Inputs: port: TCP port to listen on
|
||||
// callback: Vector to call when data arrives on this connection
|
||||
// buf: Pointer to buffer with data received
|
||||
// len: -1 on close, otherwise length of data received
|
||||
// Output: IP address of the connected client, 0 on error
|
||||
//
|
||||
uint32_t __fastcall__ tcp_listen(uint16_t port,
|
||||
void __fastcall__ (*callback)(const uint8_t* buf,
|
||||
int16_t len));
|
||||
|
||||
// Make outbound TCP connection
|
||||
//
|
||||
// Inputs: dest: Destination IP address
|
||||
// dest_port: Destination port
|
||||
// callback: Vector to call when data arrives on this connection
|
||||
// buf: Pointer to buffer with data received
|
||||
// len: -1 on close, otherwise length of data received
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool __fastcall__ tcp_connect(uint32_t dest, uint16_t dest_port,
|
||||
void __fastcall__ (*callback)(const uint8_t* buf,
|
||||
int16_t len));
|
||||
|
||||
// Close the current TCP connection
|
||||
//
|
||||
// Inputs: None
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool tcp_close(void);
|
||||
|
||||
// Send data on the current TCP connection
|
||||
//
|
||||
// Inputs: buf: Pointer to buffer containing data to be sent
|
||||
// len: Length of data to send (up to 1460 bytes)
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool __fastcall__ tcp_send(const uint8_t* buf, uint16_t len);
|
||||
|
||||
// Send an empty ACK packet on the current TCP connection
|
||||
//
|
||||
// Inputs: None
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool tcp_send_keep_alive(void);
|
||||
|
||||
// Query an SNTP server for current UTC time
|
||||
//
|
||||
// Inputs: SNTP server IP address
|
||||
// Output: The number of seconds since 00:00 on Jan 1 1900 (UTC), 0 on error
|
||||
//
|
||||
uint32_t __fastcall__ sntp_get_time(uint32_t server);
|
||||
|
||||
// Download a file from a TFTP server and provide data to user supplied vector
|
||||
//
|
||||
// Inputs: server: IP address of server to receive file from
|
||||
// name: Zero terminated string containing the name of file to download
|
||||
// callback: Vector to call once for each 512 byte packet received
|
||||
// buf: Pointer to buffer containing data received
|
||||
// len: 512 if buffer is full, otherwise number of bytes
|
||||
// in the buffer
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool __fastcall__ tftp_download(uint32_t server, const char* name,
|
||||
void __fastcall__ (*callback)(const uint8_t* buf,
|
||||
uint16_t len));
|
||||
|
||||
// Download a file from a TFTP server and provide data to specified memory location
|
||||
//
|
||||
// Inputs: server: IP address of server to receive file from
|
||||
// name: Zero terminated string containing the name of file to download
|
||||
// buf: Pointer to buffer containing data received
|
||||
// Output: Length of data received, 0 on error
|
||||
//
|
||||
uint16_t __fastcall__ tftp_download_to_memory(uint32_t server, const char* name,
|
||||
const uint8_t* buf);
|
||||
|
||||
// Upload a file to a TFTP server with data retrieved from user supplied vector
|
||||
//
|
||||
// Inputs: server: IP address of server to send file to
|
||||
// name: Zero terminated string containing the name of file to upload
|
||||
// callback: Vector to call once for each 512 byte packet to be sent
|
||||
// buf: Pointer to buffer containing data to be sent
|
||||
// Output: 512 if buffer is full, otherwise number of bytes
|
||||
// in the buffer
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool __fastcall__ tftp_upload(uint32_t server, const char* name,
|
||||
uint16_t __fastcall__ (*callback)(const uint8_t* buf));
|
||||
|
||||
// Upload a file to a TFTP server with data retrieved from specified memory location
|
||||
//
|
||||
// Inputs: server: IP address of server to send file to
|
||||
// name: Zero terminated string containing the name of file to upload
|
||||
// buf: Pointer to buffer containing data to be sent
|
||||
// len: Length of data to be sent
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool __fastcall__ tftp_upload_from_memory(uint32_t server, const char* name,
|
||||
const uint8_t* buf, uint16_t len);
|
||||
|
||||
// Parse an HTTP URL into a form that makes it easy to retrieve the specified resource
|
||||
//
|
||||
// On success the variables url_ip, url_port and url_selector (see below) are valid.
|
||||
//
|
||||
// Inputs: url: Zero (or ctrl char) terminated string containing the URL
|
||||
// resolve: Resolve host in URL
|
||||
// Output: true if an error occured, false otherwise
|
||||
//
|
||||
bool __fastcall__ url_parse(const char* url, bool resolve);
|
||||
|
||||
// Access to parsed HTTP URL
|
||||
//
|
||||
// Access to the four items below is only valid after url_parse returned false.
|
||||
//
|
||||
extern char* url_host; // Zero terminated string containing host in URL + "\r\n\r\n"
|
||||
extern uint32_t url_ip; // IP address of host in URL (only if 'resolve' is true)
|
||||
extern uint16_t url_port; // Port number of URL
|
||||
extern char* url_selector; // Zero terminated string containing selector part of URL
|
||||
|
||||
// Download a resource specified by an HTTP URL
|
||||
//
|
||||
// The URL mustn't be longer than 1400 chars. The buffer is temporarily used to hold the
|
||||
// generated HTTP request so it should have a length of at least 1460 bytes. On success
|
||||
// the resource is zero terminated.
|
||||
//
|
||||
// Inputs: url: Zero (or ctrl char) terminated string containing the URL
|
||||
// buf: Pointer to a buffer that the resource will be downloaded into
|
||||
// len: Length of buffer
|
||||
// Output: Length of resource downloaded, 0 on error
|
||||
//
|
||||
uint16_t __fastcall__ url_download(const char* url, const uint8_t* buf, uint16_t len);
|
||||
|
||||
// Start an HTTP server
|
||||
//
|
||||
// This routine will stay in an endless loop that is broken only if user press the abort key.
|
||||
//
|
||||
// Inputs: port: TCP port to listen on
|
||||
// callback: Vector to call for each inbound HTTP request
|
||||
// client: IP address of the client that sent the request
|
||||
// method: Zero terminated string containing the HTTP method
|
||||
// path: Zero terminated string containing the HTTP path
|
||||
// Output: None
|
||||
//
|
||||
void __fastcall__ httpd_start(uint16_t port,
|
||||
void __fastcall__ (*callback)(uint32_t client,
|
||||
const char* method,
|
||||
const char* path));
|
||||
|
||||
// HTTP response types
|
||||
//
|
||||
#define HTTPD_RESPONSE_NOHEADER 0 // No HTTP response header
|
||||
#define HTTPD_RESPONSE_200_TEXT 1 // HTTP Code: 200 OK, Content Type: 'text/text'
|
||||
#define HTTPD_RESPONSE_200_HTML 2 // HTTP Code: 200 OK, Content Type: 'text/html'
|
||||
#define HTTPD_RESPONSE_200_DATA 3 // HTTP Code: 200 OK, Content Type: 'application/octet-stream'
|
||||
#define HTTPD_RESPONSE_404 4 // HTTP Code: 404 Not Found
|
||||
#define HTTPD_RESPONSE_500 5 // HTTP Code: 500 System Error
|
||||
|
||||
// Send HTTP response
|
||||
//
|
||||
// Calling httpd_send_response is only valid in the context of a httpd_start callback.
|
||||
// For the response types HTTPD_RESPONSE_404 and HTTPD_RESPONSE_500 'buf' is ignored.
|
||||
// With the response type HTTPD_RESPONSE_NOHEADER it's possible to add more content to
|
||||
// an already sent HTTP response.
|
||||
//
|
||||
// Inputs: response_type: Value describing HTTP code and content type in response header
|
||||
// buf: Pointer to buffer with HTTP response content
|
||||
// len: Length of buffer with HTTP response content
|
||||
// Output: None
|
||||
//
|
||||
void __fastcall__ httpd_send_response(uint8_t response_type,
|
||||
const uint8_t* buf, uint16_t len);
|
||||
|
||||
// Retrieve the value of a variable defined in the previously received HTTP request
|
||||
//
|
||||
// Calling http_get_value is only valid in the context of a httpd_start callback.
|
||||
// Only the first letter in a variable name is significant. E.g. if a querystring contains
|
||||
// the variables 'a','alpha' and 'alabama', then only the first one will be retrievable.
|
||||
//
|
||||
// Inputs: name: Variable to retrieve
|
||||
// Output: Variable value (zero terminated string) if variable exists, null otherwise.
|
||||
//
|
||||
char* __fastcall__ http_get_value(char name);
|
||||
|
||||
// Get number of milliseconds since initialization
|
||||
//
|
||||
// Inputs: None
|
||||
// Output: Current number of milliseconds
|
||||
//
|
||||
uint16_t timer_read(void);
|
||||
|
||||
// Check if specified period of time has passed yet
|
||||
//
|
||||
// Inputs: time: Number of milliseconds we are willing to wait for
|
||||
// Output: true if timeout occured, false otherwise
|
||||
//
|
||||
bool __fastcall__ timer_timeout(uint16_t time);
|
||||
|
||||
// Check whether the abort key is being pressed
|
||||
//
|
||||
// Inputs: None
|
||||
// Output: true if abort key pressed, false otherwise
|
||||
//
|
||||
bool input_check_for_abort_key(void);
|
||||
|
||||
// Control abort key
|
||||
//
|
||||
// Control if the user can abort blocking functions with the abort key
|
||||
// (making them return IP65_ERROR_ABORTED_BY_USER). Initially the abort
|
||||
// key is enabled.
|
||||
//
|
||||
// Inputs: enable: false to disable the key, true to enable the key
|
||||
// Output: None
|
||||
//
|
||||
void __fastcall__ input_set_abort_key(bool enable);
|
||||
|
||||
// Access to actual abort key code
|
||||
//
|
||||
extern uint8_t abort_key;
|
||||
|
||||
#endif
|
@ -0,0 +1,84 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#include <conio.h>
|
||||
#include <tgi.h>
|
||||
#include <apple2.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "map.h"
|
||||
#include "satellite.h"
|
||||
#include "osd.h"
|
||||
#include "ip65.h"
|
||||
|
||||
unsigned char net = ETH_INIT_DEFAULT;
|
||||
char lon_s[16], lat_s[16];
|
||||
int lat, lon;
|
||||
long timer;
|
||||
unsigned long ts;
|
||||
|
||||
void error_exit(char *op)
|
||||
{
|
||||
printf("%s:%s\n",op,ip65_strerror(ip65_error));
|
||||
cgetc();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
int f;
|
||||
f = open("ethernet.slot",O_RDONLY);
|
||||
if (f!=-1)
|
||||
{
|
||||
read(f,&net,sizeof(net));
|
||||
close(f);
|
||||
net &= ~'0';
|
||||
}
|
||||
|
||||
if (ip65_init(net))
|
||||
error_exit("ip65_init");
|
||||
|
||||
if (dhcp_init())
|
||||
error_exit("dhcp_init");
|
||||
|
||||
tgi_install(tgi_static_stddrv);
|
||||
tgi_init();
|
||||
tgi_apple2_mix(true);
|
||||
tgi_clear();
|
||||
|
||||
while (1)
|
||||
{
|
||||
timer=524088;
|
||||
clrscr();
|
||||
satellite_fetch(&lon,&lat,lon_s,lat_s,&ts);
|
||||
map();
|
||||
osd(lon_s,lat_s,ts);
|
||||
satellite(lon,lat);
|
||||
|
||||
while (timer>0)
|
||||
{
|
||||
if (kbhit())
|
||||
switch(cgetc())
|
||||
{
|
||||
case 0x1b:
|
||||
return;
|
||||
case 0x0D:
|
||||
case 0x0A:
|
||||
timer=0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
timer--;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#ifndef MAP_H
|
||||
#define MAP_H
|
||||
|
||||
void map(void);
|
||||
|
||||
#endif /* MAP_H */
|
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#ifndef OSD_H
|
||||
#define OSD_H
|
||||
|
||||
void osd(char *lon, char *lat, unsigned long ts);
|
||||
|
||||
#endif /* OSD_H */
|
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#define CENTER_X 4
|
||||
#define CENTER_Y 4
|
||||
|
||||
#include <apple2.h>
|
||||
#include <tgi.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <conio.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include "satellite.h"
|
||||
#include "ip65.h"
|
||||
|
||||
const unsigned char _satellite[8] = {
|
||||
0x20, /* ..X.|.... */
|
||||
0x50, /* .X.X|.... */
|
||||
0xA4, /* X.X.|.X.. */
|
||||
0x58, /* .X.X|X... */
|
||||
0x1A, /* ...X|X.X. */
|
||||
0x05, /* ....|.X.X */
|
||||
0x0A, /* ....|X.X. */
|
||||
0x04, /* ....|.X.. */
|
||||
};
|
||||
|
||||
// TODO: These tables are broken, recalculate them!
|
||||
|
||||
unsigned char xpos[360] =
|
||||
{ 0,0,1,2,3,3,4,5,6,7,7,8,9,10,10,11,12,13,14,14,15,16,17,17,18,19,20,21,21,22,23,24,24,25,26,27,28,28,29,30,31,31,32,33,34,35,35,36,37,38,38,39,40,41,42,42,43,44,45,45,46,47,48,49,49,50,51,52,52,53,54,55,56,56,57,58,59,59,60,61,62,63,63,64,65,66,66,67,68,69,70,70,71,72,73,73,74,75,76,77,77,78,79,80,80,81,82,83,84,84,85,86,87,87,88,89,90,91,91,92,93,94,94,95,96,97,98,98,99,100,101,101,102,103,104,105,105,106,107,108,108,109,110,111,112,112,113,114,115,115,116,117,118,119,119,120,121,122,122,123,124,125,126,126,127,128,129,129,130,131,132,133,133,134,135,136,136,137,138,139,140,140,141,142,143,143,144,145,146,147,147,148,149,150,150,151,152,153,154,154,155,156,157,157,158,159,160,161,161,162,163,164,164,165,166,167,168,168,169,170,171,171,172,173,174,175,175,176,177,178,178,179,180,181,182,182,183,184,185,185,186,187,188,189,189,190,191,192,192,193,194,195,196,196,197,198,199,199,200,201,202,203,203,204,205,206,206,207,208,209,210,210,211,212,213,213,214,215,216,217,217,218,219,220,220,221,222,223,224,224,225,226,227,227,228,229,230,231,231,232,233,234,234,235,236,237,238,238,239,240,241,241,242,243,244,245,245,246,247,248,248,249,250,251,252,252,253,254,255,255,0,1,2,3,3,4,5,6,6,7,8,9,10,10,11,12,13,13,14,15,16,17,17,18,19,20,20,21,22,23, };
|
||||
|
||||
unsigned char ypos[360] =
|
||||
{ 0,0,0,1,1,2,2,3,3,4,4,4,5,5,6,6,7,7,8,8,8,9,9,10,10,11,11,12,12,12,13,13,14,14,15,15,16,16,16,17,17,18,18,19,19,20,20,20,21,21,22,22,23,23,24,24,24,25,25,26,26,27,27,28,28,28,29,29,30,30,31,31,32,32,32,33,33,34,34,35,35,36,36,36,37,37,38,38,39,39,40,40,40,41,41,42,42,43,43,44,44,44,45,45,46,46,47,47,48,48,48,49,49,50,50,51,51,52,52,52,53,53,54,54,55,55,56,56,56,57,57,58,58,59,59,60,60,60,61,61,62,62,63,63,64,64,64,65,65,66,66,67,67,68,68,68,69,69,70,70,71,71,72,72,72,73,73,74,74,75,75,76,76,76,77,77,78,78,79,79,80,80,80,81,81,82,82,83,83,84,84,84,85,85,86,86,87,87,88,88,88,89,89,90,90,91,91,92,92,92,93,93,94,94,95,95,96,96,96,97,97,98,98,99,99,100,100,100,101,101,102,102,103,103,104,104,104,105,105,106,106,107,107,108,108,108,109,109,110,110,111,111,112,112,112,113,113,114,114,115,115,116,116,116,117,117,118,118,119,119,120,120,120,121,121,122,122,123,123,124,124,124,125,125,126,126,127,127,128,128,128,129,129,130,130,131,131,132,132,132,133,133,134,134,135,135,136,136,136,137,137,138,138,139,139,140,140,140,141,141,142,142,143,143,144,144,144,145,145,146,146,147,147,148,148,148,149,149,150,150,151,151,152,152,152,153,153,154,154,155,155,156,156,156,157,157,158,158,159,159, };
|
||||
|
||||
const char url[]="HTTP://api.open-notify.org/iss-now.json";
|
||||
const char fmt[]="{\"iss_position\": {\"latitude\": \"%s \"longitude\": \"%s \"timestamp\": %ld, \"message\": \"success\"}";
|
||||
|
||||
char download[1024];
|
||||
|
||||
int post_proc(char *s)
|
||||
{
|
||||
char *c = strchr(s,'"');
|
||||
*c = 0;
|
||||
return atoi(s);
|
||||
}
|
||||
|
||||
bool satellite_fetch(int *lon, int *lat, char *lon_s, char *lat_s, unsigned long *ts)
|
||||
{
|
||||
char *bdy;
|
||||
|
||||
memset(lon_s,0,16);
|
||||
memset(lat_s,0,16);
|
||||
|
||||
if (!url_download(url,(uint8_t*)download,sizeof(download)))
|
||||
return false;
|
||||
|
||||
bdy=strstr(download,"\r\n\r\n");
|
||||
if (!bdy)
|
||||
return false;
|
||||
bdy += 4;
|
||||
|
||||
if (sscanf(bdy,fmt,lon_s,lat_s,ts)!=3)
|
||||
return false;
|
||||
|
||||
*lon = post_proc(lon_s);
|
||||
*lat = post_proc(lat_s);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void satellite(int lon, int lat)
|
||||
{
|
||||
unsigned char x = xpos[lon + 180] - CENTER_X;
|
||||
unsigned char y = ypos[lat + 180] - CENTER_Y;
|
||||
unsigned char i,j;
|
||||
int8_t b;
|
||||
|
||||
for (i=0;i<8;i++)
|
||||
{
|
||||
b=_satellite[i];
|
||||
for (j=0;j<16;j+=2)
|
||||
{
|
||||
if (b < 0)
|
||||
tgi_setcolor(TGI_COLOR_WHITE2);
|
||||
else
|
||||
tgi_setcolor(TGI_COLOR_BLACK2);
|
||||
tgi_setpixel(x+j,y+i);
|
||||
tgi_setpixel(x+j+1,y+i);
|
||||
b <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#ifndef SATELLITE_H
|
||||
#define SATELLITE_H
|
||||
|
||||
void satellite(int lon, int lat);
|
||||
bool satellite_fetch(int *lon, int *lat, char *lon_s, char *lat_s, unsigned long *ts);
|
||||
|
||||
#endif /* SATELLITE_H */
|
@ -0,0 +1,87 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <conio.h>
|
||||
#include <peekpoke.h>
|
||||
|
||||
//#include "globals.h"
|
||||
#include "apple2idiot.h"
|
||||
//#include "../../../../arduino-lib/Apple2Idiot/A2I_commands.h"
|
||||
|
||||
#define MAX_STR_LEN 250
|
||||
|
||||
#define CARD_ADDRESS 0xC200
|
||||
#define APPLE_COMMAND_ADDRESS 0xC201
|
||||
#define RAM_DATA_START_ADDRESS 0xC202
|
||||
#define ESP_TIMEOUT 5555
|
||||
#define ACK 6 // Acknowledge
|
||||
#define APP_ID = 202
|
||||
|
||||
unsigned int read_byte(unsigned int address) {
|
||||
unsigned int b = 0;
|
||||
b = PEEK(address);
|
||||
//printf("read_data(%u)", address);
|
||||
return b;
|
||||
}
|
||||
|
||||
unsigned char write_byte(unsigned int address, unsigned char byte_to_write) {
|
||||
//printf("%u <- %d, [%c]\n", address, byte_to_write, byte_to_write);
|
||||
POKE(address, byte_to_write);
|
||||
}
|
||||
|
||||
unsigned char write_byte_wait_for_ack(unsigned int address, unsigned char byte_to_write) {
|
||||
unsigned char received_esp_response = 0;
|
||||
int timeout_count = 0;
|
||||
unsigned char timeout_happened = 0;
|
||||
int delay_count = 0;
|
||||
unsigned char read_char;
|
||||
write_byte(address, byte_to_write);
|
||||
while ((received_esp_response==0) || (timeout_happened==0)) {
|
||||
timeout_count++;
|
||||
if (timeout_count > ESP_TIMEOUT) {
|
||||
timeout_happened = 1;
|
||||
return 0;
|
||||
}
|
||||
//read_char = read_byte(ESP_COMMAND_ADDRESS);
|
||||
read_char = read_byte(APPLE_COMMAND_ADDRESS);
|
||||
if (read_char == ACK) {
|
||||
received_esp_response = 1;
|
||||
return 1;
|
||||
}
|
||||
for (delay_count=0; delay_count < 1111; ++delay_count) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char* write_string_to_ram(unsigned int address, char* string_to_send) {
|
||||
unsigned char i;
|
||||
unsigned char size = strlen(string_to_send);
|
||||
//gotoxy(0,2);
|
||||
if (string_to_send[size-1] == '\n') {
|
||||
string_to_send[size-1] = '\0';
|
||||
}
|
||||
//printf("%u (%s)\n", address, string_to_send);
|
||||
for (i=0; i<size; i++) {
|
||||
write_byte(address+i, string_to_send[i]);
|
||||
}
|
||||
if (string_to_send[size-1] != '\0') {
|
||||
write_byte(address+i, '\0');
|
||||
}
|
||||
}
|
||||
|
||||
// HOW DO I PASS THE ADDRESS TO read_string_from_ram ???
|
||||
|
||||
void read_string_from_ram(unsigned int address, char *data, char length) {
|
||||
unsigned char c, i;
|
||||
//gotoxy(0,0);
|
||||
//printf("A: %u, L: %u\n", address, length);
|
||||
//cgetc();
|
||||
for (i=0; i<length; i++) {
|
||||
c = PEEK(address + i);
|
||||
//printf("PEEK[%u]: %c\n", i, c);
|
||||
data[i] = c;
|
||||
if (c == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
#ifndef _A2I_H
|
||||
#define _A2I_H
|
||||
|
||||
unsigned int read_byte(unsigned int address);
|
||||
unsigned char write_byte(unsigned int address, unsigned char byte_to_write);
|
||||
unsigned char* write_string_to_ram(unsigned int address, char* string_to_send);
|
||||
void read_string_from_ram(unsigned int address, char *data, char length);
|
||||
unsigned char write_byte_wait_for_ack(unsigned int address, unsigned char byte_to_write);
|
||||
|
||||
#endif
|
70
examples/30-dnd5eapi-cc65/iss-tracker/apple2/src/main.c
Normal file
70
examples/30-dnd5eapi-cc65/iss-tracker/apple2/src/main.c
Normal file
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#include <conio.h>
|
||||
#include <tgi.h>
|
||||
#include <apple2.h>
|
||||
#include <stdbool.h>
|
||||
#include "map.h"
|
||||
#include "satellite.h"
|
||||
#include "osd.h"
|
||||
//#include "sp.h"
|
||||
#include "apple2idiot.h"
|
||||
|
||||
#define CARD_ADDRESS 0xC200
|
||||
#define APPLE_COMMAND_ADDRESS 0xC201
|
||||
#define RAM_DATA_START_ADDRESS 0xC202
|
||||
#define ESP_TIMEOUT 5555
|
||||
#define ACK 6 // Acknowledge
|
||||
#define APP_ID = 202
|
||||
|
||||
//unsigned char net;
|
||||
char lon_s[16], lat_s[16];
|
||||
int lat, lon;
|
||||
long timer;
|
||||
unsigned long ts;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
//sp_init();
|
||||
//net = sp_find_network();
|
||||
tgi_install(tgi_static_stddrv);
|
||||
tgi_init();
|
||||
tgi_apple2_mix(true);
|
||||
tgi_clear();
|
||||
|
||||
write_byte(APPLE_COMMAND_ADDRESS, 202);
|
||||
|
||||
while (1)
|
||||
{
|
||||
timer=524088;
|
||||
clrscr();
|
||||
satellite_fetch(&lon,&lat,&lon_s,&lat_s,&ts);
|
||||
map();
|
||||
osd(lon_s,lat_s,ts);
|
||||
satellite(lon,lat);
|
||||
|
||||
while (timer>0)
|
||||
{
|
||||
if (kbhit())
|
||||
switch(cgetc())
|
||||
{
|
||||
case 0x1b:
|
||||
return;
|
||||
case 0x0D:
|
||||
case 0x0A:
|
||||
timer=0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
timer--;
|
||||
}
|
||||
}
|
||||
}
|
31
examples/30-dnd5eapi-cc65/iss-tracker/apple2/src/map.c
Normal file
31
examples/30-dnd5eapi-cc65/iss-tracker/apple2/src/map.c
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
#include <apple2.h>
|
||||
#include <6502.h>
|
||||
#include <peekpoke.h>
|
||||
#include <conio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
void map(void)
|
||||
{
|
||||
int f = open("MAP.HGR",O_RDONLY);
|
||||
|
||||
if (f==-1)
|
||||
{
|
||||
perror("map open");
|
||||
cgetc();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
read(f,(void *)0x2000,0x2000);
|
||||
close(f);
|
||||
}
|
14
examples/30-dnd5eapi-cc65/iss-tracker/apple2/src/map.h
Normal file
14
examples/30-dnd5eapi-cc65/iss-tracker/apple2/src/map.h
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#ifndef MAP_H
|
||||
#define MAP_H
|
||||
|
||||
void map(void);
|
||||
|
||||
#endif /* MAP_H */
|
18
examples/30-dnd5eapi-cc65/iss-tracker/apple2/src/osd.c
Normal file
18
examples/30-dnd5eapi-cc65/iss-tracker/apple2/src/osd.c
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#include <conio.h>
|
||||
#include <apple2.h>
|
||||
#include <time.h>
|
||||
|
||||
void osd(char *lon, char *lat,unsigned long ts)
|
||||
{
|
||||
cprintf(" ** CURRENT ISS POSITION **\r\n");
|
||||
cprintf(" LON: %-14s LAT: %-14s",lon,lat);
|
||||
cprintf(" AS OF: %s",ctime(&ts));
|
||||
}
|
14
examples/30-dnd5eapi-cc65/iss-tracker/apple2/src/osd.h
Normal file
14
examples/30-dnd5eapi-cc65/iss-tracker/apple2/src/osd.h
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#ifndef OSD_H
|
||||
#define OSD_H
|
||||
|
||||
void osd(char *lon, char *lat, unsigned long ts);
|
||||
|
||||
#endif /* OSD_H */
|
116
examples/30-dnd5eapi-cc65/iss-tracker/apple2/src/satellite.c
Normal file
116
examples/30-dnd5eapi-cc65/iss-tracker/apple2/src/satellite.c
Normal file
@ -0,0 +1,116 @@
|
||||
/**
|
||||
* ISS Tracker
|
||||
*
|
||||
* @author Thomas Cherryhomes
|
||||
* @email thom dot cherryhomes at gmail dot com
|
||||
* @license gpl v. 3, see LICENSE.md for details.
|
||||
*/
|
||||
|
||||
#define CENTER_X 4
|
||||
#define CENTER_Y 4
|
||||
|
||||
#define APPLE_COMMAND_ADDRESS 0xC201
|
||||
#define RAM_DATA_START_ADDRESS 0xC202
|
||||
|
||||
#include <apple2.h>
|
||||
#include <tgi.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <conio.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include "satellite.h"
|
||||
#include "apple2idiot.h"
|
||||
//#include "sp.h"
|
||||
|
||||
//extern unsigned char net; // Network device as found by sp_find_network()
|
||||
|
||||
const unsigned char _satellite[8] = {
|
||||
0x20, /* ..X.|.... */
|
||||
0x50, /* .X.X|.... */
|
||||
0xA4, /* X.X.|.X.. */
|
||||
0x58, /* .X.X|X... */
|
||||
0x1A, /* ...X|X.X. */
|
||||
0x05, /* ....|.X.X */
|
||||
0x0A, /* ....|X.X. */
|
||||
0x04, /* ....|.X.. */
|
||||
};
|
||||
|
||||
// TODO: These tables are broken, recalculate them!
|
||||
|
||||
unsigned char xpos[360] =
|
||||
{ 0,0,1,2,3,3,4,5,6,7,7,8,9,10,10,11,12,13,14,14,15,16,17,17,18,19,20,21,21,22,23,24,24,25,26,27,28,28,29,30,31,31,32,33,34,35,35,36,37,38,38,39,40,41,42,42,43,44,45,45,46,47,48,49,49,50,51,52,52,53,54,55,56,56,57,58,59,59,60,61,62,63,63,64,65,66,66,67,68,69,70,70,71,72,73,73,74,75,76,77,77,78,79,80,80,81,82,83,84,84,85,86,87,87,88,89,90,91,91,92,93,94,94,95,96,97,98,98,99,100,101,101,102,103,104,105,105,106,107,108,108,109,110,111,112,112,113,114,115,115,116,117,118,119,119,120,121,122,122,123,124,125,126,126,127,128,129,129,130,131,132,133,133,134,135,136,136,137,138,139,140,140,141,142,143,143,144,145,146,147,147,148,149,150,150,151,152,153,154,154,155,156,157,157,158,159,160,161,161,162,163,164,164,165,166,167,168,168,169,170,171,171,172,173,174,175,175,176,177,178,178,179,180,181,182,182,183,184,185,185,186,187,188,189,189,190,191,192,192,193,194,195,196,196,197,198,199,199,200,201,202,203,203,204,205,206,206,207,208,209,210,210,211,212,213,213,214,215,216,217,217,218,219,220,220,221,222,223,224,224,225,226,227,227,228,229,230,231,231,232,233,234,234,235,236,237,238,238,239,240,241,241,242,243,244,245,245,246,247,248,248,249,250,251,252,252,253,254,255,255,0,1,2,3,3,4,5,6,6,7,8,9,10,10,11,12,13,13,14,15,16,17,17,18,19,20,20,21,22,23, };
|
||||
|
||||
unsigned char ypos[360] =
|
||||
{ 0,0,0,1,1,2,2,3,3,4,4,4,5,5,6,6,7,7,8,8,8,9,9,10,10,11,11,12,12,12,13,13,14,14,15,15,16,16,16,17,17,18,18,19,19,20,20,20,21,21,22,22,23,23,24,24,24,25,25,26,26,27,27,28,28,28,29,29,30,30,31,31,32,32,32,33,33,34,34,35,35,36,36,36,37,37,38,38,39,39,40,40,40,41,41,42,42,43,43,44,44,44,45,45,46,46,47,47,48,48,48,49,49,50,50,51,51,52,52,52,53,53,54,54,55,55,56,56,56,57,57,58,58,59,59,60,60,60,61,61,62,62,63,63,64,64,64,65,65,66,66,67,67,68,68,68,69,69,70,70,71,71,72,72,72,73,73,74,74,75,75,76,76,76,77,77,78,78,79,79,80,80,80,81,81,82,82,83,83,84,84,84,85,85,86,86,87,87,88,88,88,89,89,90,90,91,91,92,92,92,93,93,94,94,95,95,96,96,96,97,97,98,98,99,99,100,100,100,101,101,102,102,103,103,104,104,104,105,105,106,106,107,107,108,108,108,109,109,110,110,111,111,112,112,112,113,113,114,114,115,115,116,116,116,117,117,118,118,119,119,120,120,120,121,121,122,122,123,123,124,124,124,125,125,126,126,127,127,128,128,128,129,129,130,130,131,131,132,132,132,133,133,134,134,135,135,136,136,136,137,137,138,138,139,139,140,140,140,141,141,142,142,143,143,144,144,144,145,145,146,146,147,147,148,148,148,149,149,150,150,151,151,152,152,152,153,153,154,154,155,155,156,156,156,157,157,158,158,159,159, };
|
||||
|
||||
const char url[]="N:HTTP://api.open-notify.org/iss-now.json";
|
||||
const char longitude_query[]="/iss_position/longitude";
|
||||
const char latitude_query[]="/iss_position/latitude";
|
||||
const char timestamp_query[]="/timestamp";
|
||||
|
||||
int post_proc(char *s)
|
||||
{
|
||||
char *c = strchr(s,'"');
|
||||
*c = 0;
|
||||
return atoi(s);
|
||||
}
|
||||
|
||||
bool satellite_fetch(int *lon, int *lat, char *lon_s, char *lat_s, unsigned long *ts)
|
||||
{
|
||||
//unsigned short len;
|
||||
char ts_s[16];
|
||||
unsigned int address_offset = 0;
|
||||
|
||||
//gotoxy(0,0);
|
||||
|
||||
memset(lon_s,0,16);
|
||||
memset(lat_s,0,16);
|
||||
|
||||
write_byte_wait_for_ack(APPLE_COMMAND_ADDRESS, 20);
|
||||
|
||||
address_offset = 0;
|
||||
read_string_from_ram(RAM_DATA_START_ADDRESS + address_offset, lat_s, 9);
|
||||
address_offset += strlen(lat_s) + 1;
|
||||
read_string_from_ram(RAM_DATA_START_ADDRESS + address_offset, lon_s, 9);
|
||||
address_offset += strlen(lon_s) + 1;
|
||||
read_string_from_ram(RAM_DATA_START_ADDRESS + address_offset, ts_s, 9);
|
||||
|
||||
*ts=atol(ts_s);
|
||||
|
||||
//clrscr();
|
||||
//cprintf(" ** CURRENT ISS POSITION **\r\n");
|
||||
//cprintf(" LON: %-14s LAT: %-14s",lon_s,lat_s);
|
||||
//cprintf(" TS: %-14s",ts_s);
|
||||
//cprintf(" AS OF: %s",ctime(ts));
|
||||
|
||||
*lon=atoi(lon_s);
|
||||
*lat=atoi(lat_s);
|
||||
*ts=atol(ts_s);
|
||||
|
||||
return true; // todo come back here and add error handling.
|
||||
}
|
||||
|
||||
void satellite(int lon, int lat)
|
||||
{
|
||||
unsigned char x = xpos[lon + 180] - CENTER_X;
|
||||
unsigned char y = ypos[lat + 180] - CENTER_Y;
|
||||
unsigned char i,j;
|
||||
int8_t b;
|
||||
for (i=0;i<8;i++)
|
||||
{
|
||||
b=_satellite[i];
|
||||
for (j=0;j<16;j+=2)
|
||||
{
|
||||
if (b < 0)
|
||||
tgi_setcolor(TGI_COLOR_WHITE2);
|
||||
else
|
||||
tgi_setcolor(TGI_COLOR_BLACK2);
|
||||
tgi_setpixel(x+j,y+i);
|
||||
tgi_setpixel(x+j+1,y+i);
|
||||
b <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user