Skip to content

Commit

Permalink
Merge pull request #257 from OpenSprinkler/support/os33
Browse files Browse the repository at this point in the history
Support/os33
  • Loading branch information
rayshobby committed Nov 4, 2023
2 parents 0e1985d + 9d8f8b0 commit 613efae
Show file tree
Hide file tree
Showing 23 changed files with 136 additions and 3,071 deletions.
1,600 changes: 0 additions & 1,600 deletions Arduino.mk

This file was deleted.

87 changes: 0 additions & 87 deletions Common.mk

This file was deleted.

85 changes: 75 additions & 10 deletions OpenSprinkler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,13 +500,73 @@ byte OpenSprinkler::start_network() {

byte OpenSprinkler::start_ether() {
#if defined(ESP8266)
if(hw_rev<2) return 0; // ethernet capability is only available after hw_rev 2
if(hw_rev<2) return 0; // ethernet capability is only available when hw_rev>=2
eth.isW5500 = (hw_rev==2)?false:true; // os 3.2 uses enc28j60 and 3.3 uses w5500

SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
SPI.setFrequency(4000000);

if(eth.isW5500) {
DEBUG_PRINTLN(F("detect existence of W5500"));
/* this is copied from w5500.cpp wizchip_sw_reset
* perform a software reset and see if we get a correct response
* without this, eth.begin will crash if W5500 is not connected
* ideally wizchip_sw_reset should return a value but since it doesn't
* we have to extract it code here
* */
static const uint8_t AccessModeRead = (0x00 << 2);
static const uint8_t AccessModeWrite = (0x01 << 2);
static const uint8_t BlockSelectCReg = (0x00 << 3);
pinMode(PIN_ETHER_CS, OUTPUT);
// ==> setMR(MR_RST)
digitalWrite(PIN_ETHER_CS, LOW);
SPI.transfer((0x00 & 0xFF00) >> 8);
SPI.transfer((0x00 & 0x00FF) >> 0);
SPI.transfer(BlockSelectCReg | AccessModeWrite);
SPI.transfer(0x80);
digitalWrite(PIN_ETHER_CS, HIGH);

// ==> ret = getMR()
uint8_t ret;
digitalWrite(PIN_ETHER_CS, LOW);
SPI.transfer((0x00 & 0xFF00) >> 8);
SPI.transfer((0x00 & 0x00FF) >> 0);
SPI.transfer(BlockSelectCReg | AccessModeRead);
ret = SPI.transfer(0);
digitalWrite(PIN_ETHER_CS, HIGH);
if(ret!=0) return 0; // ret is expected to be 0
} else {
/* this is copied from enc28j60.cpp geterevid
* check to see if the hardware revision number if expected
* */
DEBUG_PRINTLN(F("detect existence of ENC28J60"));
#define MAADRX_BANK 0x03
#define EREVID 0x12
#define ECON1 0x1f

// ==> setregbank(MAADRX_BANK);
pinMode(PIN_ETHER_CS, OUTPUT);
uint8_t r;
digitalWrite(PIN_ETHER_CS, LOW);
SPI.transfer(0x00 | (ECON1 & 0x1f));
r = SPI.transfer(0);
digitalWrite(PIN_ETHER_CS, HIGH);

digitalWrite(PIN_ETHER_CS, LOW);
SPI.transfer(0x40 | (ECON1 & 0x1f));
SPI.transfer((r & 0xfc) | (MAADRX_BANK & 0x03));
digitalWrite(PIN_ETHER_CS, HIGH);

// ==> r = readreg(EREVID);
digitalWrite(PIN_ETHER_CS, LOW);
SPI.transfer(0x00 | (EREVID & 0x1f));
r = SPI.transfer(0);
digitalWrite(PIN_ETHER_CS, HIGH);
if(r==0 || r==255) return 0; // r is expected to be a non-255 revision number
}

load_hardware_mac((uint8_t*)tmp_buffer, true);
if (iopts[IOPT_USE_DHCP]==0) { // config static IP before calling eth.begin
IPAddress staticip(iopts+IOPT_STATIC_IP1);
Expand All @@ -518,7 +578,8 @@ byte OpenSprinkler::start_ether() {
eth.setDefault();
if(!eth.begin((uint8_t*)tmp_buffer)) return 0;
lcd_print_line_clear_pgm(PSTR("Start wired link"), 1);

lcd_print_line_clear_pgm(eth.isW5500 ? PSTR(" (w5500) ") : PSTR(" (enc28j60) "), 2);

ulong timeout = millis()+30000; // 30 seconds time out
while (!eth.connected()) {
DEBUG_PRINT(".");
Expand Down Expand Up @@ -783,8 +844,12 @@ void OpenSprinkler::begin() {
PIN_SENSOR1 = V1_PIN_SENSOR1;
PIN_SENSOR2 = V1_PIN_SENSOR2;
} else {
// revision 2
hw_rev = 2;
// revision 2 and 3
if(detect_i2c(EEPROM_I2CADDR)) { // revision 3 has a I2C EEPROM
hw_rev = 3;
} else {
hw_rev = 2;
}
mainio->i2c_write(NXP_CONFIG_REG, V2_IO_CONFIG);
mainio->i2c_write(NXP_OUTPUT_REG, V2_IO_OUTPUT);

Expand Down Expand Up @@ -1060,7 +1125,7 @@ void OpenSprinkler::latch_setzoneoutput_v2(byte sid, byte A, byte K) {
*
*/
void OpenSprinkler::latch_open(byte sid) {
if(hw_rev==2) {
if(hw_rev>=2) {
DEBUG_PRINTLN(F("latch_open_v2"));
latch_disable_alloutputs_v2(); // disable all output pins
latch_boost(); // generate boost voltage
Expand All @@ -1083,7 +1148,7 @@ void OpenSprinkler::latch_open(byte sid) {
}

void OpenSprinkler::latch_close(byte sid) {
if(hw_rev==2) {
if(hw_rev>=2) {
DEBUG_PRINTLN(F("latch_close_v2"));
latch_disable_alloutputs_v2(); // disable all output pins
latch_boost(); // generate boost voltage
Expand Down Expand Up @@ -1250,7 +1315,7 @@ void OpenSprinkler::apply_all_station_bits() {
void OpenSprinkler::detect_binarysensor_status(ulong curr_time) {
// sensor_type: 0 if normally closed, 1 if normally open
if(iopts[IOPT_SENSOR1_TYPE]==SENSOR_TYPE_RAIN || iopts[IOPT_SENSOR1_TYPE]==SENSOR_TYPE_SOIL) {
if(hw_rev==2) pinModeExt(PIN_SENSOR1, INPUT_PULLUP); // this seems necessary for OS 3.2
if(hw_rev>=2) pinModeExt(PIN_SENSOR1, INPUT_PULLUP); // this seems necessary for OS 3.2
byte val = digitalReadExt(PIN_SENSOR1);
status.sensor1 = (val == iopts[IOPT_SENSOR1_OPTION]) ? 0 : 1;
if(status.sensor1) {
Expand Down Expand Up @@ -1280,7 +1345,7 @@ void OpenSprinkler::detect_binarysensor_status(ulong curr_time) {
// ESP8266 is guaranteed to have sensor 2
#if defined(ESP8266) || defined(PIN_SENSOR2)
if(iopts[IOPT_SENSOR2_TYPE]==SENSOR_TYPE_RAIN || iopts[IOPT_SENSOR2_TYPE]==SENSOR_TYPE_SOIL) {
if(hw_rev==2) pinModeExt(PIN_SENSOR2, INPUT_PULLUP); // this seems necessary for OS 3.2
if(hw_rev>=2) pinModeExt(PIN_SENSOR2, INPUT_PULLUP); // this seems necessary for OS 3.2
byte val = digitalReadExt(PIN_SENSOR2);
status.sensor2 = (val == iopts[IOPT_SENSOR2_OPTION]) ? 0 : 1;
if(status.sensor2) {
Expand Down Expand Up @@ -1315,7 +1380,7 @@ byte OpenSprinkler::detect_programswitch_status(ulong curr_time) {
byte ret = 0;
if(iopts[IOPT_SENSOR1_TYPE]==SENSOR_TYPE_PSWITCH) {
static byte sensor1_hist = 0;
if(hw_rev==2) pinModeExt(PIN_SENSOR1, INPUT_PULLUP); // this seems necessary for OS 3.2
if(hw_rev>=2) pinModeExt(PIN_SENSOR1, INPUT_PULLUP); // this seems necessary for OS 3.2
status.sensor1 = (digitalReadExt(PIN_SENSOR1) != iopts[IOPT_SENSOR1_OPTION]); // is switch activated?
sensor1_hist = (sensor1_hist<<1) | status.sensor1;
// basic noise filtering: only trigger if sensor matches pattern:
Expand All @@ -1327,7 +1392,7 @@ byte OpenSprinkler::detect_programswitch_status(ulong curr_time) {
#if defined(ESP8266) || defined(PIN_SENSOR2)
if(iopts[IOPT_SENSOR2_TYPE]==SENSOR_TYPE_PSWITCH) {
static byte sensor2_hist = 0;
if(hw_rev==2) pinModeExt(PIN_SENSOR2, INPUT_PULLUP); // this seems necessary for OS 3.2
if(hw_rev>=2) pinModeExt(PIN_SENSOR2, INPUT_PULLUP); // this seems necessary for OS 3.2
status.sensor2 = (digitalReadExt(PIN_SENSOR2) != iopts[IOPT_SENSOR2_OPTION]); // is sensor activated?
sensor2_hist = (sensor2_hist<<1) | status.sensor2;
if((sensor2_hist&0b1111) == 0b0011) {
Expand Down
32 changes: 31 additions & 1 deletion OpenSprinkler.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include <FS.h>
#include <LittleFS.h>
#include <ENC28J60lwIP.h>
#include <W5500lwIP.h>
#include <RCSwitch.h>
#include <OpenThingsFramework.h>
#include <DNSServer.h>
Expand All @@ -66,7 +67,36 @@
#if defined(ESP8266)
extern ESP8266WebServer *update_server;
extern OTF::OpenThingsFramework *otf;
extern ENC28J60lwIP eth;
extern ENC28J60lwIP enc28j60;
extern Wiznet5500lwIP w5500;
struct lwipEth {
bool isW5500 = false;
inline boolean config(const IPAddress& local_ip, const IPAddress& arg1, const IPAddress& arg2, const IPAddress& arg3 = IPADDR_NONE, const IPAddress& dns2 = IPADDR_NONE) {
return (isW5500)?w5500.config(local_ip, arg1, arg2, arg3, dns2) : enc28j60.config(local_ip, arg1, arg2, arg3, dns2);
}
inline boolean begin(const uint8_t *macAddress = nullptr) {
return (isW5500)?w5500.begin(macAddress):enc28j60.begin(macAddress);
}
inline IPAddress localIP() {
return (isW5500)?w5500.localIP():enc28j60.localIP();
}
inline IPAddress subnetMask() {
return (isW5500)?w5500.subnetMask():enc28j60.subnetMask();
}
inline IPAddress gatewayIP() {
return (isW5500)?w5500.gatewayIP():enc28j60.gatewayIP();
}
inline void setDefault() {
(isW5500)?w5500.setDefault():enc28j60.setDefault();
}
inline bool connected() {
return (isW5500)?w5500.connected():enc28j60.connected();
}
inline wl_status_t status() {
return (isW5500)?w5500.status():enc28j60.status();
}
};
extern lwipEth eth;
#else
extern EthernetServer *m_server;
#endif
Expand Down
10 changes: 7 additions & 3 deletions README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@

This is a unified OpenSprinkler firmware for Arduino, and Linux-based OpenSprinklers such as OpenSprinkler Pi.

For OS (Arduino-based OpenSprinkler) 2.x:
https://openthings.freshdesk.com/support/solutions/articles/5000165132-how-to-compile-opensprinkler-firmware
Compilation instructions for OS (Arduino-based OpenSprinkler) 2.3 and 3.x:
* Install VS Code
* Launch VS Code, search and install the platformio extension.
* Download and unzip the OpenSprinkler firmware repository, open the folder in VS Code, at the bottom of the screen, click PlatformIO:Build. The firmware repository contains platformio.ini which has all the information needed for PlatformIO to build the firmware.
Additional details:
https://openthings.freshdesk.com/support/solutions/articles/5000165132

For OSPi/OSBO or other Linux-based OpenSprinkler:
https://openthings.freshdesk.com/support/solutions/articles/5000631599-installing-and-updating-the-unified-firmware
https://openthings.freshdesk.com/support/solutions/articles/5000631599

============================================
Questions and comments:
Expand Down
6 changes: 3 additions & 3 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ if [ "$1" == "demo" ]; then
echo "Installing required libraries..."
apt-get install -y libmosquitto-dev
echo "Compiling firmware..."
g++ -o OpenSprinkler -DDEMO -std=c++14 -m32 main.cpp OpenSprinkler.cpp program.cpp opensprinkler_server.cpp utils.cpp weather.cpp gpio.cpp etherport.cpp mqtt.cpp -lpthread -lmosquitto
g++ -o OpenSprinkler -DDEMO -std=c++14 main.cpp OpenSprinkler.cpp program.cpp opensprinkler_server.cpp utils.cpp weather.cpp gpio.cpp etherport.cpp mqtt.cpp -lpthread -lmosquitto
elif [ "$1" == "osbo" ]; then
echo "Installing required libraries..."
apt-get install -y libmosquitto-dev
echo "Compiling firmware..."
g++ -o OpenSprinkler -DOSBO main.cpp OpenSprinkler.cpp program.cpp opensprinkler_server.cpp utils.cpp weather.cpp gpio.cpp etherport.cpp mqtt.cpp -lpthread -lmosquitto
g++ -o OpenSprinkler -DOSBO -std=c++14 main.cpp OpenSprinkler.cpp program.cpp opensprinkler_server.cpp utils.cpp weather.cpp gpio.cpp etherport.cpp mqtt.cpp -lpthread -lmosquitto
else
echo "Installing required libraries..."
apt-get update
Expand All @@ -31,7 +31,7 @@ else
exit 0
fi
echo "Compiling firmware..."
g++ -o OpenSprinkler -DOSPI main.cpp OpenSprinkler.cpp program.cpp opensprinkler_server.cpp utils.cpp weather.cpp gpio.cpp etherport.cpp mqtt.cpp -lpthread -lmosquitto
g++ -o OpenSprinkler -DOSPI -std=c++14 main.cpp OpenSprinkler.cpp program.cpp opensprinkler_server.cpp utils.cpp weather.cpp gpio.cpp etherport.cpp mqtt.cpp -lpthread -lmosquitto
fi

if [ ! "$SILENT" = true ] && [ -f OpenSprinkler.launch ] && [ ! -f /etc/init.d/OpenSprinkler.sh ]; then
Expand Down
3 changes: 2 additions & 1 deletion defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ typedef unsigned long ulong;
// if this number is different from the one stored in non-volatile memory
// a device reset will be automatically triggered

#define OS_FW_MINOR 2 // Firmware minor version
#define OS_FW_MINOR 3 // Firmware minor version

/** Hardware version base numbers */
#define OS_HW_VERSION_BASE 0x00 // OpenSprinkler
Expand Down Expand Up @@ -332,6 +332,7 @@ enum {
#define LADR_I2CADDR 0x23 // latch driver I2C address
#define EXP_I2CADDR_BASE 0x24 // base of expander I2C address
#define LCD_I2CADDR 0x3C // 128x64 OLED display I2C address
#define EEPROM_I2CADDR 0x50 // 24C02 EEPROM I2C address

#define PIN_CURR_SENSE A0
#define PIN_FREE_LIST {} // no free GPIO pin at the moment
Expand Down
8 changes: 5 additions & 3 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
ESP8266WebServer *update_server = NULL;
OTF::OpenThingsFramework *otf = NULL;
DNSServer *dns = NULL;
ENC28J60lwIP eth(PIN_ETHER_CS); // ENC28J60 lwip for wired Ether
ENC28J60lwIP enc28j60(PIN_ETHER_CS); // ENC28J60 lwip for wired Ether
Wiznet5500lwIP w5500(PIN_ETHER_CS); // W5500 lwip for wired Ether
lwipEth eth;
bool useEth = false; // tracks whether we are using WiFi or wired Ether connection
static uint16_t led_blink_ms = LED_FAST_BLINK;
#else
Expand Down Expand Up @@ -89,7 +91,7 @@ uint32_t reboot_timer = 0;

void flow_poll() {
#if defined(ESP8266)
if(os.hw_rev == 2) pinModeExt(PIN_SENSOR1, INPUT_PULLUP); // this seems necessary for OS 3.2
if(os.hw_rev>=2) pinModeExt(PIN_SENSOR1, INPUT_PULLUP); // this seems necessary for OS 3.2
#endif
byte curr_flow_state = digitalReadExt(PIN_SENSOR1);
if(!(prev_flow_state==HIGH && curr_flow_state==LOW)) { // only record on falling edge
Expand Down Expand Up @@ -615,7 +617,7 @@ void do_loop()
if (curr_time != last_time) {

#if defined(ESP8266)
if(os.hw_rev==2) {
if(os.hw_rev>=2) {
pinModeExt(PIN_SENSOR1, INPUT_PULLUP); // this seems necessary for OS 3.2
pinModeExt(PIN_SENSOR2, INPUT_PULLUP);
}
Expand Down
Loading

0 comments on commit 613efae

Please sign in to comment.