merge troubles

This commit is contained in:
equant 2021-09-16 17:02:19 -07:00
commit 65168d2241
14 changed files with 1100 additions and 314 deletions

3
.gitignore vendored
View File

@ -3,5 +3,4 @@
*Output.txt
_FileInformation.txt
history
credentials.h

View File

@ -1,32 +1,35 @@
# apple2idiot
A general purpose ESP32 IOT board for the Apple IIe
A general purpose ESP32 Wifi and Bluetooth board for the Apple II family of computers (with expansion slots).
Things are in the early stages of development, but it is working. The card contains an ESP32 which gives the Apple II access to wifi and bluetooth. It does not provide a TCP stack. Think of this as being more like making your Apple II an IOT device.
This card is essentially an ESP32 module and a dual-port ram chip. The Apple computer and the ESP communicate via the dual-port ram. That means that the ESP32 doesn't acutally have access to read/write any of the Apple computer's data or address busses. I think that's ok. In fact, I think this card is so simple, and stupid, that lots of fun little things can be done with it, but it's not meant to "get your Apple on the internet".
As a user of the card, you write the software that runs on the ESP32 module, and the software that runs on the Apple computer. In the `examples/` folder are examples of how to do simple little things. Software on the apple just peeks/pokes commands and data to the ram chip, and the ESP responds however it's programmed to resppond.
## Some of the example programs that have been developed so far
* Send a message to Slack.
* Get current weather conditions for a city.
* Select Wifi AP.
* Dedicated rot13 string encoder.
## Status
### The Card
This is actively being developed (as of September 2021). The rev 0.1 board doesn't work without
some bodge wires
Rev 0.2 boards are going to be ordered sometime this month.
some bodge wires, and rev 0.2 boards are on their way from China.
### The Apple II Software
None of the Apple //e code is up yet because I don't have a way to transfer it
from my 5.25 floppies to here. But all of this is underway.
from my 5.25 floppies to here. I hope to fix this soon.
### The Card Software
### The Card Software/Firmware
The ESP32 can be programmed using whatever you want. For example, you can use the Arduino IDE/C++ or you can use Lua, or Espressif's environment. Example Arduino programs are in the repo under examples.
## Some of the example programs that have been developed so far
* Get current weather conditions for a city.
* Select Wifi AP.
* Dedicated rot13 string encoder.
The ESP32 can be programmed using whatever you want. For example, you can use
the Arduino IDE/C++ or you can use Lua, or Espressif's environment. Example
Arduino programs are in the repo under examples.
## What could be done with an Apple2Idiot card?

View File

@ -0,0 +1,348 @@
/*
Copyright (c) 2020 Brian Lough. All right reserved.
ArduinoSlack - An Arduino library to wrap the Slack API
MIT License
*/
#include "ArduinoSlack.h"
ArduinoSlack::ArduinoSlack(Client &client, const char *bearerToken)
{
this->client = &client;
this->_bearerToken = bearerToken;
}
int ArduinoSlack::makeGetRequest(const char *command, const char *body, const char *contentType)
{
client->flush();
client->setTimeout(SLACK_TIMEOUT);
if (!client->connect(SLACK_HOST, portNumber))
{
SLACK_SERIAL_LN(F("Connection failed"));
return false;
}
// give the esp a breather
yield();
// Send HTTP request
client->print(F("GET "));
client->print(command);
client->println(F(" HTTP/1.1"));
//Headers
client->print(F("Host: "));
client->println(SLACK_HOST);
client->println(F("Accept: application/json"));
client->print(F("Content-Type: "));
client->println(contentType);
client->print(F("Authorization: Bearer "));
client->println(_bearerToken);
client->println(F("Cache-Control: no-cache"));
client->print(F("Content-Length: "));
client->println(strlen(body));
client->println();
//send Data here?
client->print(body);
if (client->println() == 0)
{
SLACK_SERIAL_LN(F("Failed to send request"));
return false;
}
int statusCode = getHttpStatusCode();
skipHeaders();
return statusCode;
}
int ArduinoSlack::makePostRequest(const char *command, const char *body, const char *contentType)
{
client->flush();
client->setTimeout(SLACK_TIMEOUT);
if (!client->connect(SLACK_HOST, portNumber))
{
SLACK_SERIAL_LN(F("Connection failed"));
return false;
}
// give the esp a breather
yield();
// Send HTTP request
client->print(F("POST "));
client->print(command);
client->println(F(" HTTP/1.1"));
//Headers
client->print(F("Host: "));
client->println(SLACK_HOST);
client->println(F("Accept: application/json"));
client->print(F("Content-Type: "));
client->println(contentType);
client->print(F("Authorization: Bearer "));
client->println(_bearerToken);
client->println(F("Cache-Control: no-cache"));
client->print(F("Content-Length: "));
client->println(strlen(body));
client->println();
//send Data here?
client->print(body);
if (client->println() == 0)
{
SLACK_SERIAL_LN(F("Failed to send request"));
return false;
}
int statusCode = getHttpStatusCode();
skipHeaders();
return statusCode;
}
bool ArduinoSlack::setPresence(const char *presence)
{
char command[100];
sprintf(command, SLACK_USERS_SET_PRESENCE_ENDPOINT, presence);
SLACK_DEBUG_SERIAL_LN(command);
// Get from https://arduinojson.org/v6/assistant/
const size_t bufferSize = 1000;
bool okStatus = false;
if (makePostRequest(command, "", "text/plain") == 200)
{
// Allocate DynamicJsonDocument
DynamicJsonDocument doc(bufferSize);
// Parse JSON object
DeserializationError error = deserializeJson(doc, *client);
if (!error)
{
SLACK_DEBUG_SERIAL_LN(F("parsed Json Object: "));
#ifdef SLACK_ENABLE_DEBUG
serializeJson(doc, Serial);
#endif
okStatus = doc["ok"];
if (!okStatus)
{
if (doc.containsKey("error"))
{
const char *errorMsg = doc["error"];
SLACK_DEBUG_SERIAL(F("Got the following error: "));
SLACK_DEBUG_SERIAL_LN(errorMsg);
}
else
{
SLACK_DEBUG_SERIAL_LN(F("Unkown Error"));
}
}
}
else
{
SLACK_DEBUG_SERIAL(F("deserializeJson() failed with code "));
SLACK_DEBUG_SERIAL_LN(error.c_str());
}
}
closeClient();
return okStatus;
}
SlackConvoHist ArduinoSlack::conversationHistory(const char *channel, const char *limit)
{
SLACK_DEBUG_SERIAL_LN(F("--------------"));
SLACK_DEBUG_SERIAL_LN(F("conversationHistory()"));
char body[300];
sprintf(body, setConvoHistoryBody, channel, limit);
SLACK_DEBUG_SERIAL_LN(body);
// Get from https://arduinojson.org/v6/assistant/
const size_t bufferSize = profileBufferSize;
SlackConvoHist conversation;;
// This flag will get cleared if all goes well
conversation.error = true;
if (makePostRequest(SLACK_CONVERSATIONS_HISTORY_ENDPOINT, body) == 200)
{
// Allocate DynamicJsonDocument
DynamicJsonDocument doc(bufferSize);
// Parse JSON object
DeserializationError error = deserializeJson(doc, *client);
if (!error)
{
SLACK_DEBUG_SERIAL_LN(F("parsed Json Object: "));
#ifdef SLACK_ENABLE_DEBUG
serializeJson(doc, Serial);
#endif
JsonObject messageObj = doc["messages"];
conversation.messageObj = messageObj;
//message.text = (char *)messageObj["text"].as<char *>();
//message.username = (char *)messageObj["username"].as<char *>();
//message.bot_id = (char *)messageObj["bot_id"].as<char *>();
//message.type = (char *)messageObj["type"].as<char *>();
conversation.error = false;
}
else
{
SLACK_DEBUG_SERIAL(F("deserializeJson() failed with code "));
SLACK_DEBUG_SERIAL_LN(error.c_str());
}
}
closeClient();
return conversation;
}
SlackMessage ArduinoSlack::postMessage(const char *channel, const char *text)
{
char body[300];
sprintf(body, setMessageBody, channel, text);
SLACK_DEBUG_SERIAL_LN(body);
// Get from https://arduinojson.org/v6/assistant/
const size_t bufferSize = profileBufferSize;
SlackMessage message;
// This flag will get cleared if all goes well
message.error = true;
if (makePostRequest(SLACK_POST_MESSAGE_ENDPOINT, body) == 200)
{
// Allocate DynamicJsonDocument
DynamicJsonDocument doc(bufferSize);
// Parse JSON object
DeserializationError error = deserializeJson(doc, *client);
if (!error)
{
SLACK_DEBUG_SERIAL_LN(F("parsed Json Object: "));
#ifdef SLACK_ENABLE_DEBUG
serializeJson(doc, Serial);
#endif
JsonObject messageObj = doc["message"];
message.text = (char *)messageObj["text"].as<char *>();
message.username = (char *)messageObj["username"].as<char *>();
message.bot_id = (char *)messageObj["bot_id"].as<char *>();
message.type = (char *)messageObj["type"].as<char *>();
message.error = false;
}
else
{
SLACK_DEBUG_SERIAL(F("deserializeJson() failed with code "));
SLACK_DEBUG_SERIAL_LN(error.c_str());
}
}
closeClient();
return message;
}
SlackProfile ArduinoSlack::setCustomStatus(const char *text, const char *emoji, int expiration)
{
SLACK_DEBUG_SERIAL_LN(F("setCustomStatus()"));
char body[300];
sprintf(body, setEndpointBody, text, emoji, expiration);
SLACK_DEBUG_SERIAL_LN(body);
// Get from https://arduinojson.org/v6/assistant/
const size_t bufferSize = profileBufferSize;
SlackProfile profile;
// This flag will get cleared if all goes well
profile.error = true;
if (makePostRequest(SLACK_USERS_PROFILE_SET_ENDPOINT, body) == 200)
{
// Allocate DynamicJsonDocument
DynamicJsonDocument doc(bufferSize);
// Parse JSON object
DeserializationError error = deserializeJson(doc, *client);
if (!error)
{
SLACK_DEBUG_SERIAL_LN(F("parsed Json Object: "));
#ifdef SLACK_ENABLE_DEBUG
serializeJson(doc, Serial);
#endif
JsonObject profileObj = doc["profile"];
profile.displayName = (char *)profileObj["display_name"].as<char *>();
profile.statusText = (char *)profileObj["status_text"].as<char *>();
profile.statusEmoji = (char *)profileObj["status_emoji"].as<char *>();
profile.statusExpiration = profileObj["status_expiration"].as<int>();
profile.error = false;
}
else
{
SLACK_DEBUG_SERIAL(F("deserializeJson() failed with code "));
SLACK_DEBUG_SERIAL_LN(error.c_str());
}
}
closeClient();
return profile;
}
void ArduinoSlack::skipHeaders(bool tossUnexpectedForJSON)
{
// Skip HTTP headers
if (!client->find("\r\n\r\n"))
{
SLACK_SERIAL_LN(F("Invalid response"));
return;
}
if (tossUnexpectedForJSON)
{
// Was getting stray characters between the headers and the body
// This should toss them away
while (client->available() && client->peek() != '{')
{
char c = 0;
client->readBytes(&c, 1);
SLACK_DEBUG_SERIAL(F("Tossing an unexpected character: "));
SLACK_DEBUG_SERIAL_LN(c);
}
}
}
int ArduinoSlack::getHttpStatusCode()
{
// Check HTTP status
if (client->find("HTTP/1.1"))
{
int statusCode = client->parseInt();
SLACK_DEBUG_SERIAL(F("Status Code: "));
SLACK_DEBUG_SERIAL_LN(statusCode);
return statusCode;
}
return -1;
}
void ArduinoSlack::closeClient()
{
if (client->connected())
{
SLACK_DEBUG_SERIAL_LN(F("Closing client"));
client->stop();
}
}

View File

@ -0,0 +1,104 @@
/*
Copyright (c) 2020 Brian Lough. All right reserved.
ArduinoSlack - An Arduino library to wrap the Slack API
MIT License
*/
#ifndef ArduinoSlack_h
#define ArduinoSlack_h
#include <Arduino.h>
#include <ArduinoJson.h>
#include <Client.h>
#define SLACK_ENABLE_SERIAL
//un-mark following line to enable debug mode
#define SLACK_ENABLE_DEBUG
#ifdef SLACK_ENABLE_SERIAL
#define SLACK_SERIAL(STR) Serial.print(STR)
#define SLACK_SERIAL_LN(STR) Serial.println(STR)
#else
#define SLACK_SERIAL(STR)
#define SLACK_SERIAL_LN(STR)
#endif
#ifdef SLACK_ENABLE_DEBUG
#define SLACK_DEBUG_SERIAL(STR) Serial.print(STR)
#define SLACK_DEBUG_SERIAL_LN(STR) Serial.println(STR)
#else
#define SLACK_DEBUG_SERIAL(STR)
#define SLACK_DEBUG_SERIAL_LN(STR)
#endif
#define SLACK_HOST "slack.com"
// Fingerprint valid from Tue, 13 Apr 2021 00:00:00 GMT
#define SLACK_FINGERPRINT "C3 CC ED 77 87 19 6D E7 76 5E AA A7 3D 67 7E CA 95 D2 46 E2"
#define SLACK_TIMEOUT 2000
#define SLACK_PRESENCE_AWAY "away"
#define SLACK_PRESENCE_AUTO "auto"
#define SLACK_USERS_PROFILE_SET_ENDPOINT "/api/users.profile.set"
#define SLACK_USERS_SET_PRESENCE_ENDPOINT "/api/users.setPresence?presence=%s"
#define SLACK_POST_MESSAGE_ENDPOINT "/api/chat.postMessage"
#define SLACK_CONVERSATIONS_HISTORY_ENDPOINT "/api/conversations.history"
struct SlackProfile
{
char *displayName;
char *statusText;
char *statusEmoji;
int statusExpiration;
bool error;
};
struct SlackMessage
{
char *text;
char *username;
char *bot_id;
char *type;
char *ts;
bool error;
};
struct SlackConvoHist
{
JsonObject messageObj;
bool error;
};
class ArduinoSlack
{
public:
ArduinoSlack(Client &client, const char *bearerToken);
int makePostRequest(const char *command, const char *body, const char *contentType = "application/json");
SlackProfile setCustomStatus(const char *text, const char *emoji, int expiration = 0);
SlackMessage postMessage(const char *channel, const char *text);
SlackConvoHist conversationHistory(const char *channel, const char *limit);
bool setPresence(const char *presence);
int portNumber = 443;
int profileBufferSize = 10000;
Client *client;
private:
const char *_bearerToken;
int getHttpStatusCode();
void skipHeaders(bool tossUnexpectedForJSON = true);
void closeClient();
const char *setConvoHistoryBody =
R"({"channel": "%s", "limit": "%s"})";
const char *setMessageBody =
R"({"channel": "%s", "text": "%s"})";
const char *setEndpointBody =
R"({"profile": { "status_text": "%s","status_emoji": "%s","status_expiration": %d}})";
};
#endif

View File

@ -0,0 +1,25 @@
// Digi Cert Global Root Cert - as of 26/08/2020
// Useful for ESP32
// Usage: client.setCACert(slack_server_cert);
const char *slack_server_cert = "-----BEGIN CERTIFICATE-----\n"
"MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n"
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n"
"QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n"
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
"b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n"
"9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n"
"CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n"
"nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n"
"43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n"
"T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n"
"gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n"
"BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n"
"TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n"
"DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n"
"hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n"
"06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n"
"PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n"
"YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n"
"CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n"
"-----END CERTIFICATE-----\n";

View File

@ -0,0 +1,151 @@
/*******************************************************************
Sets a custom status on your slack account. It will toggle between
two every 30 seconds
You will need a bearer token, see readme for more details
Parts:
ESP32 D1 Mini style Dev board* - http://s.click.aliexpress.com/e/C6ds4my
* * = Affiliate
If you find what I do useful and would like to support me,
please consider becoming a sponsor on Github
https://github.com/sponsors/witnessmenow/
Written by Brian Lough
YouTube: https://www.youtube.com/brianlough
Tindie: https://www.tindie.com/stores/brianlough/
Twitter: https://twitter.com/witnessmenow
*******************************************************************/
// ----------------------------
// Standard Libraries
// ----------------------------
#include <WiFi.h>
#include <WiFiClientSecure.h>
// ----------------------------
// Additional Libraries - each one of these will need to be installed.
// ----------------------------
#include "ArduinoSlack.h"
// Library for connecting to the Slack API
// Install from Github
// https://github.com/witnessmenow/arduino-slack-api
#include <ArduinoJson.h>
// Library used for parsing Json from the API responses
// Search for "Arduino Json" in the Arduino Library manager
// https://github.com/bblanchon/ArduinoJson
#include "credentials.h"
// copy credentials.h.sample to credentials.h and edit
// so it contains your passwords and tokens.
//------- Replace the following! ------
//char ssid[] = "SSID"; // your network SSID (name)
//char password[] = "password"; // your network password
char ssid[] = WIFI_SSID; // your network SSID (name)
char password[] = WIFI_PASSWORD; // your network password
//#define SLACK_ACCESS_TOKEN "AAAAAAAAAABBBBBBBBBBBCCCCCCCCCCCDDDDDDDDDDD"
//------- ---------------------- ------
// including a "slack_server_cert" variable
// header is included as part of the ArduinoSlack libary
#include "ArduinoSlackCert.h"
WiFiClientSecure client;
ArduinoSlack slack(client, SLACK_ACCESS_TOKEN);
unsigned long delayBetweenRequests = 120000; // Time between requests
unsigned long requestDueTime; //time when request due
bool firstStatus = true;
void setup()
{
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
Serial.println("Wifi credentials:");
Serial.println(ssid);
Serial.println(password);
Serial.print("Connecting to wifi.");
// Wait for connection
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
client.setCACert(slack_server_cert);
// If you want to enable some extra debugging
// uncomment the "#define SLACK_ENABLE_DEBUG" in ArduinoSlack.h
}
void displayProfile(SlackProfile profile)
{
if (!profile.error)
{
Serial.println("--------- Profile ---------");
Serial.print("Display Name: ");
Serial.println(profile.displayName);
Serial.print("Status Text: ");
Serial.println(profile.statusText);
Serial.print("Status Emoji: ");
Serial.println(profile.statusEmoji);
Serial.print("Status Expiration: ");
Serial.println(profile.statusExpiration);
Serial.println("------------------------");
}
else
{
Serial.println("error getting profile");
}
}
void loop()
{
if (millis() > requestDueTime)
{
SlackProfile profile;
SlackMessage message;
if (firstStatus)
{
profile = slack.setCustomStatus("First status", ":apple:");
message = slack.postMessage("equant-test", "This is a test message... :apple2:");
}
else
{
profile = slack.setCustomStatus("And now the second status", ":apple2:");
message = slack.postMessage("equant-test", "This is a different message... :cactus:");
// There is an optional third parameter which takes a Unix timestamp for
// when this custom status expires:
// slack.setCustomStatus("I am the second status", ":v:", 1532627506);
}
firstStatus = !firstStatus;
displayProfile(profile);
requestDueTime = millis() + delayBetweenRequests;
}
}

133
examples/slack/slack.ino Normal file
View File

@ -0,0 +1,133 @@
/*
Use this program with the Apple2idIOT card and the basic programs RRAM, WRAM and CMDROT to read/write and rot13
a single string contained within the dual port ram on the card.
CA = 49664
AA = CA + 1
*/
// Load Wi-Fi library
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
#include <HTTPClient.h>
#include <Apple2Idiot.h>
#include "ArduinoSlack.h"
#include "credentials.h"
#include "ArduinoSlackCert.h"
// copy credentials.h.sample to credentials.h and edit
// so it contains your passwords and tokens.
Apple2Idiot a2i = Apple2Idiot();
WiFiClientSecure client;
ArduinoSlack slack(client, SLACK_ACCESS_TOKEN);
#define COMMAND_SET_CHANNEL 200
#define COMMAND_SEND_MESSAGE 201
#define COMMAND_GET_CHANNEL_MESSAGES 202
char wifi_ssid[] = WIFI_SSID; // your network SSID (name)
char wifi_password[] = WIFI_PASSWORD; // your network password
/*******************/
/* Misc */
/*******************/
const long readLoopInterval = 100; // millis
unsigned long lastReadLoopTime = 0;
byte lastAppleCommand = 0;
/*################################################
# Setup #
################################################*/
void setup() {
Serial.begin(115200);
a2i.init();
Serial.println("");
Serial.println("Starting wifi...");
Serial.print(" connecting to: ");
Serial.println(wifi_ssid);
WiFi.begin(wifi_ssid, wifi_password);
while (WiFi.status() != WL_CONNECTED) {
delay(600);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected successfully");
Serial.print("Got IP: ");
Serial.println(WiFi.localIP()); //Show ESP32 IP on serial
client.setCACert(slack_server_cert);
Serial.println("Setup done");
}
/*################################################
# Functions #
################################################*/
/*################################################
# Main #
################################################*/
//String channel_name = "equant-test";
String channel_name = "C02EAQECY5A";
String message = "";
SlackConvoHist conversation;
void loop() {
if ((millis() - lastReadLoopTime) > readLoopInterval) {
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){
byte result = 0;
Serial.print("Command Switch command_byte: ");
Serial.println(command_byte);
switch(command_byte) {
case COMMAND_GET_CHANNEL_MESSAGES:
Serial.println("COMMAND_GET_CHANNEL_MESSAGES");
a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
char cc[250];
channel_name.toCharArray(cc, 250);
conversation = slack.conversationHistory(cc, "2");
serializeJsonPretty(conversation.messageObj, Serial);
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
a2i.write_data(ESP_COMMAND_ADDRESS, EOT); // notify Apple IIe we are done processing command byte
break;
case COMMAND_SET_CHANNEL:
Serial.println("COMMAND_SET_CHANNEL");
a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
channel_name = a2i.read_string_from_ram(SHARED_RAM_START_ADDRESS);
Serial.println("Received: ["+channel_name+"]");
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
a2i.write_data(ESP_COMMAND_ADDRESS, EOT); // notify Apple IIe we are done processing command byte
break;
case COMMAND_SEND_MESSAGE:
Serial.println("COMMAND_SEND_MESSAGE:");
SlackMessage slackMessage;
a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
message = a2i.read_string_from_ram(SHARED_RAM_START_ADDRESS);
char m[250];
message.toCharArray(m, 250);
char c[250];
channel_name.toCharArray(c, 250);
slackMessage = slack.postMessage(c, m);
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
a2i.write_data(ESP_COMMAND_ADDRESS, result); // notify Apple IIe we are done processing command byte
break;
}
lastAppleCommand = command_byte;
}
lastReadLoopTime = millis();
}
}

177
examples/weather/; Normal file
View File

@ -0,0 +1,177 @@
/*
Use this program with the Apple2idIOT card and the basic programs RRAM, WRAM and CMDROT to read/write and rot13
a single string contained within the dual port ram on the card.
CA = 49664
AA = CA + 1
*/
// Load Wi-Fi library
#include <WiFi.h>
#include <Apple2Idiot.h>
#include <ArduinoJson.h>
#include <HTTPClient.h>
Apple2Idiot a2i = Apple2Idiot();
#define COMMAND_SET_COUNTRY 200
#define COMMAND_SET_CITY 201
#define COMMAND_FETCH_WEATHER 205
const char* wifi_ssid = "GSO";
const char* wifi_password = "xerxes27";
/*******************/
/* Weather Service */
/*******************/
const String weather_service_api_key= "0ab97bbbea58592d7c9d64067a34d2d0";
const String weather_url = "http://api.openweathermap.org/data/2.5/weather?";
/*******************/
/* Misc */
/*******************/
const long readLoopInterval = 100; // millis
unsigned long lastReadLoopTime = 0;
byte lastAppleCommand = 0;
/*################################################
# Setup #
################################################*/
void setup() {
Serial.begin(115200);
a2i.init();
Serial.println("");
Serial.println("Starting wifi...");
Serial.print(" connecting to: ");
Serial.println(wifi_ssid);
WiFi.begin(wifi_ssid, wifi_password);
while (WiFi.status() != WL_CONNECTED) {
delay(600);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected successfully");
Serial.print("Got IP: ");
Serial.println(WiFi.localIP()); //Show ESP32 IP on serial
Serial.println("Setup done");
}
/*################################################
# Functions #
################################################*/
byte fetch_weather(char* city_name) {
byte result = 0;
HTTPClient http;
const String request_url = weather_url + "q=Tucson,us&APPID=" + weather_service_api_key;
Serial.println(request_url);
http.begin(request_url);
int httpCode = http.GET(); //Make the request
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 {
//const char* main = doc["main"];
Serial.println("----------------------");
serializeJsonPretty(doc, Serial);
Serial.println("----------------------");
serializeJsonPretty(doc["wind"], Serial);
Serial.println("----------------------");
//int temp = doc["main"]["temp"];
//int humidity = doc["main"]["humidity"];
//float wind_speed = doc["wind"]["speed"];
//int wind_deg = doc["wind"]["deg"];
//String weather_description = doc["weather"][0]["description"];
//a2i.write_data(0, round(temp-273.15));
//a2i.write_data(1, round(humidity));
//a2i.write_data(2, round(wind_deg/10)); // divide by twn because 360 is too big for 8 bits
//a2i.write_data(3, round(wind_speed));
String temp = doc["main"]["temp"];
String humidity = doc["main"]["humidity"];
String wind_speed = doc["wind"]["speed"];
String wind_deg = doc["wind"]["deg"];
String weather_description = 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);
}
result = ACK;
}
else {
Serial.println("Error on HTTP request");
result = ERR;
}
http.end(); //Free the resources
return result;
}
/*################################################
# Main #
################################################*/
void loop() {
if ((millis() - lastReadLoopTime) > readLoopInterval) {
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){
byte result = 0;
Serial.print("Command Switch command_byte: ");
Serial.println(command_byte);
switch(command_byte) {
case COMMAND_SET_COUNTRY:
//a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
//int access_point_n = a2i.read_data(SHARED_RAM_START_ADDRESS) - 1;
//String password_as_String = a2i.read_string_from_ram(SHARED_RAM_START_ADDRESS+1);
//a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
break;
case COMMAND_SET_CITY:
//a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
//int access_point_n = a2i.read_data(SHARED_RAM_START_ADDRESS) - 1;
//String password_as_String = a2i.read_string_from_ram(SHARED_RAM_START_ADDRESS+1);
//a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
break;
case COMMAND_FETCH_WEATHER:
a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
result = fetch_weather("Tucson");
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
a2i.write_data(ESP_COMMAND_ADDRESS, result); // notify Apple IIe we are done processing command byte
break;
}
lastAppleCommand = command_byte;
}
lastReadLoopTime = millis();
}
}

View File

@ -1,194 +1,44 @@
/*
Use this program with the Apple2idIOT card and the basic programs RRAM, WRAM and CMDROT to read/write and rot13
a single string contained within the dual port ram on the card.
CA = 49664
AA = CA + 1
*/
#define DEBUG true
// Load Wi-Fi library
#include <WiFi.h>
#include <Apple2Idiot.h>
#include <ArduinoJson.h>
#include <HTTPClient.h>
/**********************/
/* Default WiFi */
/**********************/
Apple2Idiot a2i = Apple2Idiot();
// Replace with your network credentials
const char* wifi_ssid = "ella";
const char* wifi_password = "";
#define COMMAND_SET_COUNTRY 200
#define COMMAND_SET_CITY 201
#define COMMAND_FETCH_WEATHER 205
/**************/
/* ESP32 Pins */
/**************/
const char* wifi_ssid = "GSO";
const char* wifi_password = "xerxes27";
/* DATA BUS (numbers mean GPIO port) */
#define D0R 12
#define D1R 13
#define D2R 14
#define D3R 15
#define D4R 16
#define D5R 17
#define D6R 18
#define D7R 19
byte data_pins[] = {D7R, D6R, D5R, D4R, D3R, D2R, D1R, D0R};
#define DATA_BUS_SIZE 8
/*******************/
/* Weather Service */
/*******************/
/* Address Bus */
#define A0R 21
#define A1R 22
#define A2R 23
#define A3R 25
#define A4R 26
#define A5R 27
#define A6R 32
#define A7R 33
byte address_pins[] = {A0R, A1R, A2R, A3R, A4R, A5R, A6R, A7R};
#define ADDRESS_BUS_SIZE 8
#define ESP_COMMAND_ADDRESS 0
#define APPLE_COMMAND_ADDRESS 1
#define SHARED_RAM_START_ADDRESS 2
#define RAM_BUSY 666
#define MAX_STR_LEN 44 // arbitrary length.
const String weather_service_api_key= "0ab97bbbea58592d7c9d64067a34d2d0";
const String weather_url = "http://api.openweathermap.org/data/2.5/weather?";
#define COMMAND_GENERIC 0b10000000
#define COMMAND_SCAN_WIFI 111
#define COMMAND_CONNECT 112
String country_code = "US";
String city_name = "Tucson";
/* IDT7132S dual port ram chip enable */
#define RW_PIN 5
#define RW_WRITE LOW
#define RW_READ HIGH
#define INPUT_35 35
#define INPUT_34 34
#define ETX 3 // ASCII "End of Text" (ETX) character
#define ACK 0b00000110 // Acknowledge
#define EOT 0b00000100 // End of transmit
/*********/
/* Misc. */
/*********/
/*******************/
/* Misc */
/*******************/
const long readLoopInterval = 100; // millis
unsigned long lastReadLoopTime = 0;
byte ram[256];
volatile byte ram_busy=0;
byte lastAppleCommand = 0;
/*################################################
# Functions #
################################################*/
void unbusy_ram() {
set_address(ESP_COMMAND_ADDRESS);
ram_busy = false;
}
boolean set_address(int address) {
if (ram_busy) {
Serial.println("BUSY");
return false;
}
ram_busy = true;
for (byte i=0; i<ADDRESS_BUS_SIZE; i++) {
byte state = bitRead(address, i);
digitalWrite(address_pins[i], state);
}
return true;
}
byte read_data(int address) {
byte data_bus_read = 0;
if (set_address(address)) {
digitalWrite(RW_PIN, RW_READ); // Should already be set to RW_READ, but just in case.
for (byte i=0; i<DATA_BUS_SIZE; i++) {
byte pin_state = digitalRead(data_pins[i]);
data_bus_read += pin_state * pow(2,i);
}
ram_busy = false;
unbusy_ram();
return data_bus_read;
} else {
return RAM_BUSY;
}
}
boolean write_data(byte address, byte byte_to_write) {
Serial.print("WRITE: ");
Serial.print(byte_to_write);
Serial.print(" -> ");
Serial.println(address);
if (set_address(address)) {
//set_address(address);
Serial.print(" D:");
for (byte i=0; i<DATA_BUS_SIZE; i++) {
byte bit_to_write = (byte_to_write >> i) & 0b00000001;
pinMode(data_pins[i], OUTPUT);
digitalWrite(data_pins[i], bit_to_write);
Serial.print(bit_to_write);
}
Serial.println();
digitalWrite(RW_PIN, RW_WRITE);
delay(1);
digitalWrite(RW_PIN, RW_READ);
for (byte i=0; i<DATA_BUS_SIZE; i++) {
pinMode(data_pins[i], INPUT);
}
unbusy_ram();
return true;
} else {
return false;
}
}
unsigned int write_string_to_shared_ram(String string_to_send, unsigned int address) {
//if (string_to_send.length() > 15 - 1) { // - 1 because of null character at end of string.
write_data(ESP_COMMAND_ADDRESS, 12);
unsigned int c = 0;
for (c=0; c < string_to_send.length(); c++) {
Serial.print("A(");
Serial.print(c);
Serial.print("): ");
Serial.println(string_to_send[c]);
write_data(address+c, string_to_send[c]);
}
write_data(address+c, ETX);
//write_data(15, COMMAND_FROM_ESP + command_message + COMMAND_NO_DATA_WAITING);
write_data(ESP_COMMAND_ADDRESS, 27);
return address+c;
}
String read_string_from_ram(int address) {
byte c = 0;
int i = 0;
String read_string = "";
while ( (i<MAX_STR_LEN) && (c!=ETX) ) {
c = read_data(address+i);
read_string = read_string + char(c);
i++;
}
Serial.print("READ STRING:");
Serial.println(read_string);
return read_string;
}
void read_ram(int size_to_read=256);
void read_ram(int size_to_read) {
for (int i=0; i < size_to_read; i++) {
unsigned int foo = read_data(i);
ram[i] = foo;
Serial.print(i);
Serial.print(" ");
Serial.println(foo);
}
}
/*################################################
# Setup #
################################################*/
@ -196,27 +46,7 @@ void read_ram(int size_to_read) {
void setup() {
Serial.begin(115200);
/* Configure ESP32 Pins */
pinMode(A0R, OUTPUT); digitalWrite(A0R, LOW);
pinMode(A1R, OUTPUT); digitalWrite(A1R, LOW);
pinMode(A2R, OUTPUT); digitalWrite(A2R, LOW);
pinMode(A3R, OUTPUT); digitalWrite(A3R, LOW);
pinMode(A4R, OUTPUT); digitalWrite(A4R, LOW);
pinMode(A5R, OUTPUT); digitalWrite(A5R, LOW);
pinMode(A6R, OUTPUT); digitalWrite(A6R, LOW);
pinMode(A7R, OUTPUT); digitalWrite(A7R, LOW);
pinMode(D0R, INPUT);
pinMode(D1R, INPUT);
pinMode(D2R, INPUT);
pinMode(D3R, INPUT);
pinMode(D4R, INPUT);
pinMode(D5R, INPUT);
pinMode(D6R, INPUT);
pinMode(D7R, INPUT);
pinMode(RW_PIN, OUTPUT); digitalWrite(RW_PIN, RW_READ);
pinMode(INPUT_34, INPUT);
pinMode(INPUT_35, INPUT);
a2i.init();
Serial.println("");
Serial.println("Starting wifi...");
@ -225,7 +55,7 @@ void setup() {
WiFi.begin(wifi_ssid, wifi_password);
while (WiFi.status() != WL_CONNECTED) {
delay(900);
delay(600);
Serial.print(".");
}
@ -234,117 +64,115 @@ void setup() {
Serial.print("Got IP: ");
Serial.println(WiFi.localIP()); //Show ESP32 IP on serial
// Set WiFi to station mode and disconnect from an AP if it was previously connected
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(10);
write_string_to_shared_ram("Starting Up!", SHARED_RAM_START_ADDRESS);
write_data(ESP_COMMAND_ADDRESS, ACK);
write_data(APPLE_COMMAND_ADDRESS, ACK);
Serial.println("Setup done");
}
/*################################################
# Functions #
################################################*/
byte fetch_weather() {
byte result = 0;
HTTPClient http;
//const String request_url = weather_url + "q=Tucson,us&APPID=" + weather_service_api_key;
const String request_url = weather_url + "q=" + city_name + "," + country_code + "&APPID=" + weather_service_api_key;
Serial.println(request_url);
http.begin(request_url);
int httpCode = http.GET(); //Make the request
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;
}
/*################################################
# Main #
################################################*/
void scan_wifi() {
Serial.println("scan start");
// WiFi.scanNetworks will return the number of networks found
int n = WiFi.scanNetworks();
Serial.println("scan done");
int address_counter = SHARED_RAM_START_ADDRESS + 1;
if (n == 0) {
Serial.println("no networks found");
write_data(0, address_counter);
} else {
Serial.print(n);
Serial.println(" networks found");
write_data(n, address_counter);
for (int i = 0; i < n; ++i) {
// Print SSID and RSSI for each network found
Serial.print(i + 1);
Serial.print(": ");
Serial.print(WiFi.SSID(i));
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
Serial.print(")");
Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN)?" ":"*");
delay(10);
address_counter = write_string_to_shared_ram(WiFi.SSID(i), address_counter + 1);
//address_counter = write_string_to_shared_ram(String(WiFi.RSSI(i)), address_counter + 1);
//address_counter = write_string_to_shared_ram(WiFi.encryptionType(i), address_counter + 1);
}
}
write_data(ESP_COMMAND_ADDRESS, EOT);
Serial.println("");
}
void store_ip_to_ram(byte offset) {
IPAddress ip_address = WiFi.localIP();
//for (int i=0; i < ADDRESS_BUS_SIZE; i++) {
for (int i=0; i < 4; i++) {
write_data(i+offset, ip_address[i]);
}
}
const char* wifi_ssid = "";
const char* wifi_password = "";
void loop() {
if ((millis() - lastReadLoopTime) > readLoopInterval) {
byte command_byte = read_data(APPLE_COMMAND_ADDRESS);
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){
byte result = 0;
Serial.print("Command Switch command_byte: ");
Serial.println(command_byte);
switch(command_byte) {
case COMMAND_SCAN_WIFI:
write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
//String read_string = read_string_from_ram(SHARED_RAM_START_ADDRESS);
//write_string_to_shared_ram(rot13(read_string), SHARED_RAM_START_ADDRESS);
scan_wifi();
write_data(APPLE_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
case COMMAND_SET_COUNTRY:
Serial.println("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: ["+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
break;
}
switch(command_byte) {
case COMMAND_CONNECT:
write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
int access_point_n = read_data(SHARED_RAM_START_ADDRESS);
String ssid_as_String = WiFi.SSID(access_point_n);
String password_as_String = read_string_from_ram(SHARED_RAM_START_ADDRESS+1);
wifi_password = password_as_String.c_str();
wifi_ssid = ssid_as_String.c_str();
//wifi_password = read_string_from_ram(SHARED_RAM_START_ADDRESS+1);
//wifi_ssid = WiFi.SSID(access_point_n);
//WiFi.begin(wifi_ssid, wifi_password);
Serial.print("password:");
Serial.println(password_as_String);
Serial.print("password:(");
Serial.print(wifi_password);
Serial.println(")");
//WiFi.begin(wifi_ssid, wifi_password);
WiFi.begin("GSO", "xerxes27");
while (WiFi.status() != WL_CONNECTED) {
delay(300);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected successfully");
Serial.print("Got IP: ");
Serial.println(WiFi.localIP()); //Show ESP32 IP on serial
store_ip_to_ram(SHARED_RAM_START_ADDRESS);
write_data(APPLE_COMMAND_ADDRESS, ACK);
case COMMAND_SET_CITY:
Serial.println("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: ["+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
break;
case COMMAND_FETCH_WEATHER:
Serial.println("COMMAND_FETCH_WEATHER");
a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
result = fetch_weather();
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK);
a2i.write_data(ESP_COMMAND_ADDRESS, result); // notify Apple IIe we are done processing command byte
break;
}
lastAppleCommand = command_byte;
write_data(ESP_COMMAND_ADDRESS, EOT); // notify Apple IIe we are done processing command byte
}
lastReadLoopTime = millis();
}

View File

@ -79,14 +79,12 @@ void loop() {
Serial.print("Command Switch command_byte: ");
Serial.println(command_byte);
switch(command_byte) {
case COMMAND_SCAN_WIFI:
case COMMAND_WIFI_SCAN:
a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
scan_wifi();
a2i.write_data(APPLE_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
break;
}
switch(command_byte) {
case COMMAND_CONNECT:
case COMMAND_WIFI_CONNECT:
a2i.write_data(ESP_COMMAND_ADDRESS, ACK); // notify Apple IIe we are processing command byte
int access_point_n = a2i.read_data(SHARED_RAM_START_ADDRESS) - 1;
String ssid_as_String = WiFi.SSID(access_point_n);

View File

@ -43,7 +43,7 @@ void Apple2Idiot::unbusy_ram() {
boolean Apple2Idiot::set_address(int address) {
if (ram_busy) {
Serial.println("BUSY");
//Serial.println("BUSY");
return false;
}
ram_busy = true;
@ -78,14 +78,14 @@ boolean Apple2Idiot::write_data(byte address, byte byte_to_write) {
Serial.println(address);
if (set_address(address)) {
//set_address(address);
Serial.print(" D:");
//Serial.print(" D:");
for (byte i=0; i<DATA_BUS_SIZE; i++) {
byte bit_to_write = (byte_to_write >> i) & 0b00000001;
pinMode(data_pins[i], OUTPUT);
digitalWrite(data_pins[i], bit_to_write);
Serial.print(bit_to_write);
//Serial.print(bit_to_write);
}
Serial.println();
//Serial.println();
digitalWrite(RW_PIN, RW_WRITE);
delay(1);
digitalWrite(RW_PIN, RW_READ);
@ -123,7 +123,9 @@ String Apple2Idiot::read_string_from_ram(int address) {
String read_string = "";
while ( (i<MAX_STR_LEN) && (c!=ETX) ) {
c = read_data(address+i);
read_string = read_string + char(c);
if (c!=ETX) {
read_string = read_string + char(c);
}
i++;
}
Serial.print("READ STRING:");

View File

@ -23,15 +23,31 @@
#define A6R 32
#define A7R 33
#define ADDRESS_BUS_SIZE 8
#define ESP_COMMAND_ADDRESS 0
#define APPLE_COMMAND_ADDRESS 1
#define SHARED_RAM_START_ADDRESS 2
#define RAM_BUSY 666
#define MAX_STR_LEN 44 // arbitrary length.
#define MAX_STR_LEN 250 // arbitrary length.
#define COMMAND_GENERIC 0b10000000
#define COMMAND_SCAN_WIFI 111
#define COMMAND_CONNECT 112
//
// Commands and messages that are communicated between the ESP and the Apple
// via the dual-port ram.
//
// Commands >=200 are "non-reserved", and are meant
// to be defined within scipts that use this library.
// So anything in this library should be below 200.
//
// If the values of these defines are changed, then they will need to be
// updated within the code that runs on the Apple as well.
//#define COMMAND_GENERIC 0b10000000
#define COMMAND_WIFI_SCAN 111
#define COMMAND_WIFI_CONNECT 112
#define ACK 0b00000110 // Acknowledge
#define EOT 0b00000100 // End of transmit
#define ERR 0b00000101 // Error
#define MORE_TO_SEND 0b00000111
/* IDT7132S dual port ram chip enable */
#define RW_PIN 5
@ -39,8 +55,6 @@
#define RW_READ HIGH
#define ETX 3 // ASCII "End of Text" (ETX) character
#define ACK 0b00000110 // Acknowledge
#define EOT 0b00000100 // End of transmit
#define INPUT_35 35
#define INPUT_34 34

View File

@ -13,6 +13,10 @@ DONE: Add diode to +5V.
DONE: Move ESP32 towards keyboard to accomodate USB
Software reset of ESP32
## Potential Trivial Features
+ Gives each computer a unique ID (MAC address)
+ Prodos driver for NPT time.
## Thanks