diff --git a/MiSTer.vcxproj b/MiSTer.vcxproj
index 3d760b2..9cad680 100644
--- a/MiSTer.vcxproj
+++ b/MiSTer.vcxproj
@@ -40,6 +40,7 @@
+
@@ -64,6 +65,7 @@
+
diff --git a/MiSTer.vcxproj.filters b/MiSTer.vcxproj.filters
index 3ca656a..05f443b 100644
--- a/MiSTer.vcxproj.filters
+++ b/MiSTer.vcxproj.filters
@@ -77,6 +77,9 @@
Source Files
+
+ Source Files
+
@@ -169,6 +172,9 @@
Header Files
+
+ Header Files
+
diff --git a/battery.c b/battery.c
new file mode 100644
index 0000000..4aaf9bf
--- /dev/null
+++ b/battery.c
@@ -0,0 +1,212 @@
+/*
+
+ * battery.c
+ * display pi-top battery status
+ *
+ * Copyright 2016, 2017 rricharz
+ * MiSTer port. Copyright 2018 Sorgelig
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "battery.h"
+
+#define MAX_COUNT 20 // Maximum number of trials
+#define SLEEP_TIME 500 // time between two i2cget in microsec
+
+///////////////////////////////////////////////////////////////////////
+// I2C definitions
+
+#define I2C_SLAVE 0x0703
+#define I2C_SMBUS 0x0720 /* SMBus-level access */
+
+#define I2C_SMBUS_READ 1
+#define I2C_SMBUS_WRITE 0
+
+// SMBus transaction types
+
+#define I2C_SMBUS_QUICK 0
+#define I2C_SMBUS_BYTE 1
+#define I2C_SMBUS_BYTE_DATA 2
+#define I2C_SMBUS_WORD_DATA 3
+#define I2C_SMBUS_PROC_CALL 4
+#define I2C_SMBUS_BLOCK_DATA 5
+#define I2C_SMBUS_I2C_BLOCK_BROKEN 6
+#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
+#define I2C_SMBUS_I2C_BLOCK_DATA 8
+
+// SMBus messages
+
+#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */
+#define I2C_SMBUS_I2C_BLOCK_MAX 32 /* Not specified but we use same structure */
+
+// Structures used in the ioctl() calls
+
+union i2c_smbus_data
+{
+ uint8_t byte;
+ int8_t sbyte;
+ uint16_t word;
+ int16_t sword;
+ uint8_t block [I2C_SMBUS_BLOCK_MAX + 2]; // block [0] is used for length + one more for PEC
+};
+
+struct i2c_smbus_ioctl_data
+{
+ char read_write;
+ uint8_t command;
+ int size;
+ union i2c_smbus_data *data;
+};
+
+static int i2c_smbus_access (int fd, char rw, uint8_t command, int size, union i2c_smbus_data *data)
+{
+ struct i2c_smbus_ioctl_data args;
+
+ args.read_write = rw;
+ args.command = command;
+ args.size = size;
+ args.data = data;
+ return ioctl (fd, I2C_SMBUS, &args);
+}
+
+static int i2c_smbus_write_quick(int fd, uint8_t value)
+{
+ return i2c_smbus_access(fd, value, 0, I2C_SMBUS_QUICK, NULL);
+}
+
+///////////////////////////////////////////////////////////////////////
+
+static int i2c_handle = -1;
+
+static int smbus_open(int dev_address)
+{
+ // re-entry compatible
+ if(i2c_handle < 0)
+ {
+ int fd;
+ if ((fd = open ("/dev/i2c-1", O_RDWR)) < 0)
+ {
+ printf("Unable to open I2C device: %s\n", strerror(errno));
+ return 0;
+ }
+
+ if (ioctl (fd, I2C_SLAVE, dev_address) < 0)
+ {
+ printf("Unable to select I2C device: %s\n", strerror (errno));
+ close(fd);
+ return 0;
+ }
+
+ if (i2c_smbus_write_quick(fd, I2C_SMBUS_WRITE) < 0)
+ {
+ printf("Unable to detect SMBUS device: %s\n", strerror(errno));
+ close(fd);
+ return 0;
+ }
+
+ i2c_handle = fd;
+ }
+ return 1;
+}
+
+static void smbus_close()
+{
+ if(i2c_handle > 0) close(i2c_handle);
+ i2c_handle = -1;
+}
+
+static int smbus_get(int address, short *data)
+{
+ union i2c_smbus_data smbus_data;
+
+ if (i2c_smbus_access (i2c_handle, I2C_SMBUS_READ, address, I2C_SMBUS_WORD_DATA, &smbus_data)) return 0;
+
+ *data = smbus_data.sword;
+ return 1;
+}
+
+static int getReg(int reg, int min, int max)
+{
+ int count = 0;
+ short value = -1;
+ while ((value == -1) && (count++ < MAX_COUNT))
+ {
+ if (smbus_get(reg, &value))
+ {
+ if ((value > max) || (value < min)) value = -1; // out of limits
+ }
+ usleep(SLEEP_TIME);
+ }
+
+ return value;
+}
+
+int getBattery(int quick, struct battery_data_t *data)
+{
+ /*
+ data->capacity = 80;
+ data->load_current = -520;
+ data->time = 312;
+ data->current = 2510;
+ data->voltage = 16200;
+ data->cell[0] = 4101;
+ data->cell[1] = 4102;
+ data->cell[2] = 4103;
+ data->cell[3] = 4104;
+ return 1;
+ */
+ // don't try to check if no battery device is present
+ if (i2c_handle == -2) return 0;
+
+ if (!smbus_open(0x0b))
+ {
+ printf("No battery found.\n");
+ i2c_handle = -2;
+ return 0;
+ }
+
+ data->capacity = getReg(0x0D, 0, 100);
+ data->load_current = getReg(0x0A, -5000, 5000);
+ if (quick) return 1;
+
+ data->time = 0;
+ if (data->load_current > 0) data->time = getReg(0x13, 1, 999);
+ if (data->load_current < -1) data->time = getReg(0x12, 1, 960);
+
+ data->current = getReg(0x0F, 0, 5000);
+ data->voltage = getReg(0x09, 5000, 20000);
+ /*
+ data->cell[0] = getReg(0x3F, 1000, 5000);
+ data->cell[1] = getReg(0x3E, 1000, 5000);
+ data->cell[2] = getReg(0x3D, 1000, 5000);
+ data->cell[3] = getReg(0x3C, 1000, 5000);
+ */
+
+ return 1;
+}
diff --git a/battery.h b/battery.h
new file mode 100644
index 0000000..1519617
--- /dev/null
+++ b/battery.h
@@ -0,0 +1,16 @@
+#ifndef __BATTERY_H__
+#define __BATTERY_H__
+
+struct battery_data_t
+{
+ short load_current;
+ short capacity;
+ short current;
+ short time;
+ short voltage;
+ short cell[4];
+};
+
+int getBattery(int quick, struct battery_data_t *data);
+
+#endif
diff --git a/charrom.h b/charrom.h
index 53c7508..b454315 100644
--- a/charrom.h
+++ b/charrom.h
@@ -38,7 +38,7 @@ Middle Dot
*/
// *character font
-unsigned char charfont[128][8] =
+unsigned char charfont[][8] =
{
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 0 [0x0]
{ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55 }, // 1 [0x1]
@@ -70,8 +70,8 @@ unsigned char charfont[128][8] =
{ 0x00,0x00,0x00,0x0c,0x0c,0x00,0x00,0x00 }, // 27 [0x1b] middle dot
{ 0x68,0x78,0x6b,0x0f,0x6b,0x78,0x68,0x00 }, // 28 [0x1c] ethernet
{ 0x02,0x09,0x25,0x95,0x95,0x25,0x09,0x02 }, // 29 [0x1d] wifi
- { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 30 [0x1e]
- { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 31 [0x1f]
+ { 0x00,0x90,0xD8,0x7C,0x3E,0x1B,0x09,0x00 }, // 30 [0x1e] charge
+ { 0x7E,0x72,0x73,0x73,0x73,0x72,0x7E,0x00 }, // 31 [0x1f] battery
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // 32 [0x20]
{ 0x00,0x00,0x00,0x5F,0x5F,0x00,0x00,0x00 }, // 33 [0x21]
{ 0x00,0x03,0x03,0x00,0x03,0x03,0x00,0x00 }, // 34 [0x22]
@@ -167,7 +167,24 @@ unsigned char charfont[128][8] =
{ 0x00,0x00,0x00,0x7F,0x7F,0x00,0x00,0x00 }, // 124 [0x7c]
{ 0x00,0x41,0x41,0x77,0x3E,0x08,0x08,0x00 }, // 125 [0x7d]
{ 0x02,0x01,0x01,0x03,0x02,0x02,0x01,0x00 }, // 126 [0x7e]
- { 0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x00 } // 127 [0x7f]
+ { 0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x00 }, // 127 [0x7f]
+
+ //dotted frame
+ { 0x00,0x00,0x00,0xA8,0x00,0x08,0x00,0x08 }, // 128 [0x80] TL
+ { 0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08 }, // 129 [0x81] T/B
+ { 0x00,0x08,0x00,0xA8,0x00,0x00,0x00,0x00 }, // 130 [0x82] TR
+ { 0x00,0x00,0x00,0xAA,0x00,0x00,0x00,0x00 }, // 131 [0x83] L/R
+ { 0x00,0x08,0x00,0x0A,0x00,0x00,0x00,0x00 }, // 132 [0x84] BR
+ { 0x00,0x00,0x00,0x0A,0x00,0x08,0x00,0x08 }, // 133 [0x85] BL
+
+ //solid frame
+ { 0x00,0x00,0x00,0xF8,0x08,0x08,0x08,0x08 }, // 134 [0x86] TL
+ { 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08 }, // 135 [0x87] T/B
+ { 0x08,0x08,0x08,0xF8,0x00,0x00,0x00,0x00 }, // 136 [0x88] TR
+ { 0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00 }, // 137 [0x89] L/R
+ { 0x08,0x08,0x08,0x0F,0x00,0x00,0x00,0x00 }, // 138 [0x8A] BR
+ { 0x00,0x00,0x00,0x0F,0x08,0x08,0x08,0x08 }, // 139 [0x8B] BL
+
};
#endif
diff --git a/menu.c b/menu.c
index 560d07c..510e1b3 100644
--- a/menu.c
+++ b/menu.c
@@ -52,6 +52,7 @@ along with this program. If not, see .
#include "cfg.h"
#include "input.h"
#include "x86.h"
+#include "battery.h"
/*menu states*/
enum MENU
@@ -524,6 +525,91 @@ char* getNet()
return ifa ? host : 0;
}
+static long sysinfo_timer;
+void infowrite(int pos, char* txt)
+{
+ char str[40];
+ memset(str, 0x20, 29);
+ int len = strlen(txt);
+ if (len > 27) len = 27;
+ if(len) strncpy(str + 1+ ((27-len)/2), txt, len);
+ str[0] = 0x83;
+ str[28] = 0x83;
+ str[29] = 0;
+ OsdWrite(pos, str, 0, 0);
+}
+
+void printSysInfo()
+{
+ if (!sysinfo_timer || CheckTimer(sysinfo_timer))
+ {
+ sysinfo_timer = GetTimer(2000);
+ struct battery_data_t bat;
+ int hasbat = getBattery(0, &bat);
+ int n = 9;
+
+ char str[40];
+ OsdWrite(n++, "\x80\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x82", 0, 0);
+ if (!hasbat)
+ {
+ infowrite(n++, "");
+ }
+
+ memset(str, 0, sizeof(str));
+ char *net = getNet();
+ if (net)
+ {
+ str[strlen(str)] = 0x1b + netType;
+ strcat(str, " ");
+ }
+ strcat(str, net ? net : "No network");
+ infowrite(n++, str);
+
+ if (hasbat)
+ {
+ infowrite(n++, "");
+ sprintf(str, "\x1F ");
+ if (bat.capacity == -1) strcat(str, "n/a");
+ else sprintf(str + strlen(str), "%d%%", bat.capacity);
+ if (bat.current != -1) sprintf(str + strlen(str), " %dmAh", bat.current);
+ if (bat.voltage != -1) sprintf(str + strlen(str), " %d.%dV", bat.voltage / 1000, (bat.voltage / 100) % 10);
+
+ infowrite(n++, str);
+
+ str[0] = 0;
+ if (bat.load_current > 0)
+ {
+ sprintf(str + strlen(str), " \x12 %dmA", bat.load_current);
+ if (bat.time != -1)
+ {
+ if (bat.time < 90) sprintf(str + strlen(str), ", ETA: %dm", bat.time);
+ else sprintf(str + strlen(str), ", ETA: %dh%02dm", bat.time / 60, bat.time % 60);
+ }
+ }
+ else if (bat.load_current < -1)
+ {
+ sprintf(str + strlen(str), " \x13 %dmA", -bat.load_current);
+ if (bat.time != -1)
+ {
+ if (bat.time < 90) sprintf(str + strlen(str), ", ETA: %dm", bat.time);
+ else sprintf(str + strlen(str), ", ETA: %dh%02dm", bat.time / 60, bat.time % 60);
+ }
+ }
+ else
+ {
+ strcat(str, "Not charging");
+ }
+ infowrite(n++, str);
+ }
+ else
+ {
+ infowrite(n++, "");
+ infowrite(n++, "");
+ }
+ OsdWrite(n++, "\x85\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x84", 0, 0);
+ }
+}
+
void HandleUI(void)
{
switch (user_io_core_type())
@@ -621,15 +707,6 @@ void HandleUI(void)
case KEY_MINUS: // -/_
minus = true;
break;
-/*
- case 0x01: // 1: 1280x720 mode
- if (user_io_osd_is_visible) cfg.video_mode = 0;
- break;
-
- case 0x02: // 2: 1280x1024 mode
- if (user_io_osd_is_visible) cfg.video_mode = 1;
- break;
-*/
}
if (menu || select || up || down || left || right)
@@ -1146,21 +1223,18 @@ void HandleUI(void)
parentstate = MENU_8BIT_SYSTEM1;
if (OsdIsBig) OsdWrite(0, "", 0, 0);
OsdWrite(OsdIsBig ? 1 : 0, " Firmware & Core \x16", menusub == 0, 0);
- if(OsdIsBig) OsdWrite(2, "", 0, 0);
- OsdWrite(OsdIsBig ? 3 : 1, " Define joystick buttons", menusub == 1, 0);
- OsdWrite(OsdIsBig ? 4 : 2, "", 0, 0);
- if (OsdIsBig) OsdWrite(5, "", 0, 0);
- OsdWrite(OsdIsBig ? 6 : 3, m ? " Reset" : " Reset settings", menusub == 3, !has_menu());
+ OsdWrite(OsdIsBig ? 2 : 1, " Define joystick buttons \x16", menusub == 1, 0);
+ OsdWrite(OsdIsBig ? 3 : 2, "", 0, 0);
+ OsdWrite(OsdIsBig ? 4 : 3, m ? " Reset" : " Reset settings", menusub == 3, !has_menu());
if (m)
- OsdWrite(OsdIsBig ? 7 : 4, "", 0, 0);
+ OsdWrite(OsdIsBig ? 5 : 4, "", 0, 0);
else
- OsdWrite(OsdIsBig ? 7 : 4, " Save settings", menusub == 4, !has_menu()); // Minimig saves settings elsewhere
- if (OsdIsBig) OsdWrite(8, "", 0, 0);
- OsdWrite(OsdIsBig ? 9 : 5, " Cold reset", menusub == (5 - m), 0);
- if (OsdIsBig) OsdWrite(10, "", 0, 0);
- OsdWrite(OsdIsBig ? 11 : 6, " About", menusub == (6 - m), 0);
- if(OsdIsBig) for (int i = 12; i < OsdGetSize() - 1; i++) OsdWrite(i, "", 0, 0);
+ OsdWrite(OsdIsBig ? 5 : 4, " Save settings", menusub == 4, !has_menu()); // Minimig saves settings elsewhere
+ if (OsdIsBig) OsdWrite(6, "", 0, 0);
+ OsdWrite(OsdIsBig ? 7 : 5, " Cold reset", menusub == (5 - m), 0);
+ OsdWrite(OsdIsBig ? 8 : 6, " About", menusub == (6 - m), 0);
OsdWrite(OsdGetSize() - 1, STD_EXIT, menusub == (7 - m), 0);
+ sysinfo_timer = 0;
break;
case MENU_8BIT_SYSTEM2:
@@ -1274,6 +1348,8 @@ void HandleUI(void)
}
}
}
+
+ if (OsdIsBig) printSysInfo();
break;
case MENU_JOYDIGMAP:
@@ -3011,16 +3087,12 @@ void HandleUI(void)
}
}
OsdWrite(5, "", 0, 0);
- OsdWrite(6, " NOTE:", 0, 0);
- OsdWrite(7, " USB storage takes longer", 0, 0);
- OsdWrite(8, " time to initialize", 0, 0);
- OsdWrite(9, " upon cold boot.", 0, 0);
- OsdWrite(10, " Use OSD or USER button to", 0, 0);
- OsdWrite(11, " cancel USB waiting.", 0, 0);
- OsdWrite(12, "", 0, 0);
- OsdWrite(13, "", 0, 0);
- OsdWrite(14, " Remap keyboard", menusub == 1, 0);
- OsdWrite(15, " Define joystick buttons", menusub == 2, 0);
+ OsdWrite(6, " Remap keyboard \x16", menusub == 1, 0);
+ OsdWrite(7, " Define joystick buttons \x16", menusub == 2, 0);
+ OsdWrite(8, "", 0, 0);
+ OsdWrite(15, "", 0, 0);
+ sysinfo_timer = 0;
+
menustate = MENU_STORAGE;
}
else
@@ -3096,6 +3168,7 @@ void HandleUI(void)
break;
}
}
+ printSysInfo();
break;
case MENU_KBDMAP:
@@ -3223,23 +3296,15 @@ void HandleUI(void)
rtc_timer = GetTimer(1000);
char str[64] = { 0 };
sprintf(str, " MiSTer ");
- char *net = getNet();
- if (menustate == MENU_STORAGE)
+ time_t t = time(NULL);
+ struct tm tm = *localtime(&t);
+ if (tm.tm_year >= 117)
{
- strcat(str, net ? net : " no network");
- }
- else
- {
- time_t t = time(NULL);
- struct tm tm = *localtime(&t);
- if (tm.tm_year >= 117)
- {
- strftime(str + strlen(str), sizeof(str) - 1 - strlen(str), "%b %d %a %H:%M:%S", &tm);
- }
+ strftime(str + strlen(str), sizeof(str) - 1 - strlen(str), "%b %d %a %H:%M:%S", &tm);
}
- if (net) str[9] = 0x1b + netType;
+ if (getNet()) str[9] = 0x1b + netType;
OsdWrite(16, "", 1, 0);
OsdWrite(17, str, 1, 0);