Преглед на файлове

Merge branch 'master' of https://tree.clementinecomputing.com/clementinecomputing/popufare

clementinecomputing преди 6 години
родител
ревизия
6ddd5e7445

Файловите разлики са ограничени, защото са твърде много
+ 594 - 466
busunit/DIUv2/diu_main.c


+ 0 - 2
busunit/DIUv2/driver.c

@@ -153,7 +153,6 @@ int check_paddle_request() {
       send_message(hub_fd, &outgoing_msg);
       paddle_req_timeout = 0;
 
-      //setmenu(mt, paddle_ok_menu);
       snprintf(buf, LINE_BUFFER_SIZE, "paddle ok %i", paddle_req.result);
       ws_send(&g_mgr, buf);
 
@@ -166,7 +165,6 @@ int check_paddle_request() {
       paddle_req.request = 0;
       paddle_req_timeout = 0;
 
-      //setmenu(mt, paddle_fail_menu);
       ws_send(&g_mgr, "paddle fail");
 
       return 1;

+ 25 - 3
busunit/DIUv2/html/index-ORG.html

@@ -112,6 +112,20 @@
 
       </div>
 
+      <br>
+      <br>
+
+
+      <div class='pure-g row4'>
+
+        <div class='pure-u-1-3 col'> </div>
+        <div class='pure-u-1-3 col'> <button class='bdropinp bkeym' id='ui_configuration_volumetest'>Test</button> </div>
+        <div class='pure-u-1-3 col'>  </div>
+
+      </div>
+
+
+
     </div>
 
     <!-- ************************** -->
@@ -135,9 +149,17 @@
 
       <div class='pure-g row4'>
 
-        <div class='pure-u-1-3 col'> <button onmousedown='_beep();' class='bdropinp bkeyw' id='ui_diagnostic_custom0'>Custom 0</button> </div>
-        <div class='pure-u-1-3 col'> <button onmousedown='_beep();' class='bdropinp bkeyw' id='ui_diagnostic_custom1'>Custom 1</button> </div>
-        <div class='pure-u-1-3 col'> <button onmousedown='_beep();' class='bdropinp bkeyw' id='ui_diagnostic_custom2'>Custom 2</button> </div>
+        <div class='pure-u-1-3 col'> <button onmousedown='_beep();' class='bdropinp bkeyw' id='ui_diagnostic_custom0'>eth0 up</button> </div>
+        <div class='pure-u-1-3 col'> <button onmousedown='_beep();' class='bdropinp bkeyw' id='ui_diagnostic_custom1'>eth0 down</button> </div>
+        <div class='pure-u-1-3 col'> <button onmousedown='_beep();' class='bdropinp bkeyw' id='ui_diagnostic_custom2'>eth0 info</button> </div>
+
+      </div>
+
+      <div class='pure-g row4'>
+
+        <div class='pure-u-1-3 col'> <button onmousedown='_beep();' class='bdropinp bkeyw' id='ui_diagnostic_custom3'>speak test</button> </div>
+        <div class='pure-u-1-3 col'> <button onmousedown='_beep();' class='bdropinp bkeyw' id='ui_diagnostic_custom4'>nop</button> </div>
+        <div class='pure-u-1-3 col'> <button onmousedown='_beep();' class='bdropinp bkeyw' id='ui_diagnostic_custom5'>nop</button> </div>
 
       </div>
 

+ 58 - 22
busunit/DIUv2/html/js/diu_ui-ORG.js

@@ -27,8 +27,8 @@ var _fqADDRESS = _ADDRESS + ":" + _PORT;
 var BG_COLOR = "#f7f7f7";
 var TEXT_COLOR = "#444444";
 
-var DIU_UI_VERSION = "0.1.5";
-var DIU_UI_VERSION_DATE = "2019-11-27 13:09:00";
+var DIU_UI_VERSION = "0.1.7";
+var DIU_UI_VERSION_DATE = "2019-12-10";
 
 var g_snd = {
   "reject_fare" : "",
@@ -251,9 +251,20 @@ function _slider_change(name) {
   if (name == "configuration.volume") {
     var val = document.getElementById("ui_configuration_volume").value;
     _process_volume(val);
+
+    ivol = Math.floor(val*100.0);
+    _api_request("volume", {"volume":ivol},
+      function(inp) { console.log("volume api set ok:", inp); },
+      function(inp) { console.log("volume api set fail:", inp); });
   }
 }
 
+function _volume_test() {
+  _api_request("say", {"message":"testing 1, 2, 3"},
+    function(inp) { console.log("volume test ok:", inp); },
+    function(inp) { console.log("volume test fail:", inp); });
+}
+
 //------------
 
 function _clear_ui_driver() {
@@ -582,7 +593,7 @@ function _sp(str, align, pad) {
   else if (align == "right") {
     var pfx = "";
     for (var i=0; i<n; i++) { pfx += " "; }
-    str = prx + str;
+    str = pfx + str;
   }
 
   return str;
@@ -624,8 +635,19 @@ function _cb_status(inp) {
     html_a.push("Last Token Read (" + m["last_token"] + ")");
     html_a.push("GPS: " + has_gps + gps_str + "");
     html_a.push(" ");
-    html_a.push("Package   Version   Installed");
-    html_a.push(_sp("ui") + _sp(DIU_UI_VERSION) + _sp(DIU_UI_VERSION_DATE) + "");
+
+    // some site specific fiddling to display package information
+    //
+    html_a.push(_sp("Package") + _sp("Version", "left", 18) + _sp("Installed", "right", 12));
+    html_a.push(_sp("ui") + _sp(DIU_UI_VERSION, "left", 18) + _sp(DIU_UI_VERSION_DATE, "right", 12) + "");
+
+    for (var _ii=0; _ii<3; _ii++) {
+      var key = "pkg" + _ii;
+      if (key in g_ctx.diu_status) {
+        var aval = g_ctx.diu_status[key].split(" ");
+        html_a.push(_sp(aval[0]) + _sp(aval[1], "left", 18) + _sp(aval[2], "right", 12));
+      }
+    }
     html_a.push(" ");
 
     if ("IMEI" in m) { html_a.push("IMEI = " + m["IMEI"] + ""); }
@@ -637,9 +659,6 @@ function _cb_status(inp) {
       html_a[ii] = html_a[ii].replace(/ /g, '&nbsp;');
     }
 
-    //span_str = "<div style='float:left; width: 100%; margin: 0 auto; display:block; text-align:left;  background: #770000; color:#008800;'>";
-    //span_str = "<div style='float:left; width: 100%; text-align:left;  background: #770000; color:#008800;'>";
-    //var div_hdr = "<div style='float:left; width: 100%; text-align:left; '>";
     var div_hdr = "<div class='textrow'>";
     var str = div_hdr + html_a.join("</div><br>" + div_hdr ) + "</div>";
 
@@ -968,14 +987,12 @@ function _configuration() {
 }
 
 function _reset() {
-
   _switch_ui('ui_login');
   g_ctx.driver_login_state = "driver";
   _clear_ui_driver();
   _clear_ui_paddle();
 
   location.reload(true);
-
 }
 
 function _reboot() {
@@ -986,24 +1003,38 @@ function _reboot() {
 }
 
 function _custom0() {
-  _switch_ui('ui_login');
-  g_ctx.driver_login_state = "driver";
-  _clear_ui_driver();
-  _clear_ui_paddle();
+  _api_request("interfaceupdown", {"interface":"eth0", "state":"up"}, function(inp) { console.log("custom0 ok:", inp); }, function(inp) { console.log("custom0 error:", inp); });
 }
 
 function _custom1() {
-  _switch_ui('ui_login');
-  g_ctx.driver_login_state = "driver";
-  _clear_ui_driver();
-  _clear_ui_paddle();
+  _api_request("interfaceupdown", {"interface":"eth0", "state":"down"}, function(inp) { console.log("custom1 ok:", inp); }, function(inp) { console.log("custom1 error:", inp); });
+}
+
+function _update_diagnostic_window(_msg) {
+  var ele = document.getElementById("ui_diagnostic_view");
+  ele.innerHTML = _msg;
 }
 
 function _custom2() {
-  _switch_ui('ui_login');
-  g_ctx.driver_login_state = "driver";
-  _clear_ui_driver();
-  _clear_ui_paddle();
+  _api_request("interfaceinfo", {"interface":"eth0"}, _update_diagnostic_window, function(inp) { console.log("custom2 error:", inp); });
+}
+
+function _custom3() {
+  _api_request("say", {"message":"speech test"}, function(inp) { console.log("custom3 ok:", inp); }, function(inp) { console.log("custom3 error:", inp); });
+}
+
+function _custom4() {
+  //_switch_ui('ui_login');
+  //g_ctx.driver_login_state = "driver";
+  //_clear_ui_driver();
+  //_clear_ui_paddle();
+}
+
+function _custom5() {
+  //_switch_ui('ui_login');
+  //g_ctx.driver_login_state = "driver";
+  //_clear_ui_driver();
+  //_clear_ui_paddle();
 }
 
 //------------
@@ -1025,9 +1056,14 @@ function init() {
   document.getElementById('ui_diagnostic_custom1').onclick = _custom1;
   document.getElementById('ui_diagnostic_custom2').onclick = _custom2;
 
+  document.getElementById('ui_diagnostic_custom3').onclick = _custom3;
+  document.getElementById('ui_diagnostic_custom4').onclick = _custom4;
+  document.getElementById('ui_diagnostic_custom5').onclick = _custom5;
+
   // configuration
   //
   document.getElementById('ui_configuration_back').onclick = _mainscreen;
+  document.getElementById('ui_configuration_volumetest').onclick = _volume_test;
 
 
   // login

+ 25 - 6
busunit/PIU/piu_main.c

@@ -311,6 +311,17 @@ int main(int argc, char **argv) {
 
   int i, j;
 
+  long long int _usec_now, _usec_prv, _usec_del;
+  _usec_now = get_usec_time();
+  _usec_prv = _usec_now;
+  _usec_del = 60000000;
+
+  long long int _usec_ratelimit_now, _usec_ratelimit_prv, _usec_ratelimit_del;
+  _usec_ratelimit_now = get_usec_time();
+  _usec_ratelimit_prv = _usec_ratelimit_now;
+  _usec_ratelimit_del = 1000000;
+
+
   configure_signal_handlers(argv[0]);
   maintain_ipc_hub_connect(argv[0]);
 
@@ -335,12 +346,14 @@ int main(int argc, char **argv) {
 
     RESET_WATCHDOG();
 
+    //DEBUG
+    _usec_now = get_usec_time();
+    if ((_usec_now - _usec_prv) > _usec_del) {
+      printf("[%lli] piu_minder: heartbeat\n", get_usec_time());
+      _usec_prv = _usec_now;
+    }
+    //DEBUG
 
-    // DEBUG
-    //
-    printf("[%lli] piu_minder: heartbeat\n", get_usec_time());
-    //
-    // DEBUG
 
     maintain_ipc_hub_connect(argv[0]);
 
@@ -371,7 +384,13 @@ int main(int argc, char **argv) {
         }
       }
       else {
-        fprintf(stderr, "Cannot open serial port %s for PIU!\n", PASSENGER_UI_PORT);
+
+        _usec_ratelimit_now = get_usec_time();
+        if ((_usec_ratelimit_now - _usec_ratelimit_prv) > _usec_ratelimit_del) {
+          fprintf(stderr, "Cannot open serial port %s for PIU!\n", PASSENGER_UI_PORT);
+          _usec_ratelimit_prv = _usec_ratelimit_now;
+        }
+
       }
     }
 

+ 10 - 1
busunit/avls/avls_communication.c

@@ -208,6 +208,11 @@ int main(int argc, char **argv)
 
     struct message_record incoming_msg;
 
+    long long int _usec_now, _usec_prv, _usec_del;
+    _usec_del = 60000000;
+    _usec_now = get_usec_time();
+    _usec_prv = _usec_now;
+
     //------------------
 
     load_avls_config();
@@ -227,7 +232,11 @@ int main(int argc, char **argv)
         RESET_WATCHDOG();
 
         //DEBUG
-        printf("[%lli] avls: heartbeat\n", get_usec_time());
+        _usec_now = get_usec_time();
+        if ((_usec_now - _usec_prv) > _usec_del) {
+          printf("[%lli] avls: heartbeat\n", get_usec_time());
+          _usec_prv = _usec_now;
+        }
         //DEBUG
 
         if(hup_request_status)

+ 10 - 1
busunit/billdb/bill_communication.c

@@ -449,6 +449,11 @@ int main(int argc, char **argv)
     int input_idx = 0;
     int checked_idx = 0;
 
+    long long int _usec_now, _usec_prv, _usec_del;
+    _usec_del = 60000000;
+    _usec_now = get_usec_time();
+    _usec_prv = _usec_now;
+
     billdb_context ctx = {0};
 
 
@@ -494,7 +499,11 @@ int main(int argc, char **argv)
         RESET_WATCHDOG();
 
         //DEBUG
-        printf("[%lli] billdb: heartbeat\n", get_usec_time());
+        _usec_now = get_usec_time();
+        if ((_usec_now - _usec_prv) > _usec_del) {
+          printf("[%lli] billdb: heartbeat\n", get_usec_time());
+          _usec_prv = _usec_now;
+        }
         //DEBUG
 
         maintain_ipc_hub_connect(argv[0]);

+ 11 - 1
busunit/commhub/commserver.c

@@ -852,6 +852,11 @@ int main(int argc, char **argv)
     int rebuild;
     struct message_record msg;
 
+    long long int _usec_now, _usec_prv, _usec_del;
+    _usec_del = 60000000;
+    _usec_now = get_usec_time();
+    _usec_prv = _usec_now;
+
     //Install our signal handlers and watchdog
     configure_signal_handlers(argv[0]);
 
@@ -878,9 +883,14 @@ int main(int argc, char **argv)
     {
 
       //DEBUG
-      printf("[%lli] ipc_server: heartbeat\n", get_usec_time());
+      _usec_now = get_usec_time();
+      if ((_usec_now - _usec_prv) > _usec_del) {
+        printf("[%lli] ipc_server: heartbeat\n", get_usec_time());
+        _usec_prv = _usec_now;
+      }
       //DEBUG
 
+
         RESET_WATCHDOG();
         
         if(rebuild)	//if we have been flagged to rebuild our client fd list

+ 22 - 4
busunit/gps/gps_main.c

@@ -526,6 +526,16 @@ int main(int argc, char **argv) {
   time_t now;
   time_t last_stale_gps_check = 0;
 
+  long long int _usec_now, _usec_prv, _usec_del;
+  _usec_now = get_usec_time();
+  _usec_prv = _usec_now;
+  _usec_del = 60000000;
+
+  long long int _usec_ratelimit_now, _usec_ratelimit_prv, _usec_ratelimit_del;
+  _usec_ratelimit_now = get_usec_time();
+  _usec_ratelimit_del = 1000000;
+  _usec_ratelimit_prv = _usec_ratelimit_now - _usec_ratelimit_del;
+
   // Configure our signal handlers to deal with SIGINT, SIGTERM, etc... 
   // and make graceful exits while logging
   //
@@ -544,19 +554,27 @@ int main(int argc, char **argv) {
   //
   while( exit_request_status == EXIT_REQUEST_NONE ) {
 
+    RESET_WATCHDOG();
+
     //DEBUG
-    printf("[%lli] gps_minder: heartbeat\n", get_usec_time());
+    _usec_now = get_usec_time();
+    if ((_usec_now - _usec_prv) > _usec_del) {
+      printf("[%lli] gps_minder: heartbeat\n", get_usec_time());
+      _usec_prv = _usec_now;
+    }
     //DEBUG
 
-    RESET_WATCHDOG();
-
     maintain_ipc_hub_connect(argv[0]);
 
     if(gps_fd < 0) {
       gps_fd = open_rs232_device(GPS_PORT, GPS_DEFAULT_BAUD, RS232_LINE);
 
       if(gps_fd < 0) {
-        fprintf(stderr, "Cannot open serial port %s for GPS!\n", GPS_PORT);
+        _usec_ratelimit_now = get_usec_time();
+        if ((_usec_ratelimit_now - _usec_ratelimit_prv) > _usec_ratelimit_del) {
+          fprintf(stderr, "Cannot open serial port %s for GPS!\n", GPS_PORT);
+          _usec_ratelimit_prv = _usec_ratelimit_now;
+        }
       }
 
     }

+ 11 - 1
busunit/paddlemgr/paddlemgr.c

@@ -400,6 +400,11 @@ int main(int argc, char **argv)
 
   struct message_record incoming_msg;
 
+  long long int _usec_now, _usec_prv, _usec_del;
+  _usec_now = get_usec_time();
+  _usec_prv = _usec_now;
+  _usec_del = 60000000;
+
   configure_signal_handlers(argv[0]);
   maintain_ipc_hub_connect(argv[0]);
 
@@ -418,9 +423,14 @@ int main(int argc, char **argv)
     RESET_WATCHDOG();
 
     //DEBUG
-    printf("[%lli] paddlemgr: heartbeat\n", get_usec_time());
+    _usec_now = get_usec_time();
+    if ((_usec_now - _usec_prv) > _usec_del) {
+      printf("[%lli] paddlemgr: heartbeat\n", get_usec_time());
+      _usec_prv = _usec_now;
+    }
     //DEBUG
 
+
     maintain_ipc_hub_connect(argv[0]);
 
     nfds=0;

+ 11 - 1
busunit/passdb/pass_communication.c

@@ -1041,6 +1041,11 @@ int main(int argc, char **argv)
     int input_idx = 0;
     int checked_idx = 0;
 
+		long long int _usec_now, _usec_prv, _usec_del;
+		_usec_now = get_usec_time();
+		_usec_prv = _usec_now;
+		_usec_del = 60000000;
+
     passdb_context ctx = {0};
 
     passdb_context_alloc(&ctx);
@@ -1101,9 +1106,14 @@ int main(int argc, char **argv)
         RESET_WATCHDOG();
 
         //DEBUG
-        printf("[%lli] passdb: heartbeat\n", get_usec_time());
+        _usec_now = get_usec_time();
+        if ((_usec_now - _usec_prv) > _usec_del) {
+          printf("[%lli] passdb: heartbeat\n", get_usec_time());
+          _usec_prv = _usec_now;
+        }
         //DEBUG
 
+
         maintain_ipc_hub_connect(argv[0]);
 
         if( (now - last_piu_update) > 0)

+ 2 - 15
busunit/rootfs/boot/config.txt

@@ -18,8 +18,8 @@
 
 # uncomment to force a console size. By default it will be display's size minus
 # overscan.
-framebuffer_width=1280
-framebuffer_height=720
+framebuffer_width=640
+framebuffer_height=480
 
 # uncomment if hdmi display is not detected and composite is being output
 #hdmi_force_hotplug=1
@@ -56,25 +56,12 @@ framebuffer_height=720
 # Enable audio (loads snd_bcm2835)
 dtparam=audio=on
 
-#enable_uart=1
-#dtoverlay=pi3-disable-bt
-#dtoverlay=pi3-miniuart-bt
-#dtoverlay=pi3-disable-bt
-#dtoverlay=pi3-disable-wifi
-
 [pi4]
 # Enable DRM VC4 V3D driver on top of the dispmanx display stack
 dtoverlay=vc4-fkms-v3d
 max_framebuffers=2
 
 [all]
-#dtoverlay=vc4-fkms-v3d
-#enable_uart=1
-#dtoverlay=pi3-disable-bt
-#dtoverlay=pi3-disable-wifi
-#enable_uart=1
-#dtoverlay=pi3-disable-bt
-#dtoverlay=pi3-disable-wifi
 enable_uart=1
 dtoverlay=pi3-disable-bt
 dtoverlay=pi3-disable-wifi

+ 69 - 0
busunit/rootfs/boot/config.txt.resistive-touchscreen

@@ -0,0 +1,69 @@
+# For more options and information see
+# http://rpf.io/configtxt
+# Some settings may impact device functionality. See link above for details
+
+#display_rotate=2
+#lcd_rotate=2
+
+# uncomment if you get no picture on HDMI for a default "safe" mode
+#hdmi_safe=1
+
+# uncomment this if your display has a black border of unused pixels visible
+# and your display can output without overscan
+disable_overscan=1
+
+# uncomment the following to adjust overscan. Use positive numbers if console
+# goes off screen, and negative if there is too much border
+#overscan_left=16
+#overscan_right=16
+#overscan_top=16
+#overscan_bottom=16
+
+# uncomment to force a console size. By default it will be display's size minus
+# overscan.
+framebuffer_width=640
+framebuffer_height=480
+
+# uncomment if hdmi display is not detected and composite is being output
+#hdmi_force_hotplug=1
+
+# uncomment to force a specific HDMI mode (this will force VGA)
+#hdmi_group=1
+#hdmi_mode=1
+
+# uncomment to force a HDMI mode rather than DVI. This can make audio work in
+# DMT (computer monitor) modes
+#hdmi_drive=2
+
+# uncomment to increase signal to HDMI, if you have interference, blanking, or
+# no display
+#config_hdmi_boost=4
+
+# uncomment for composite PAL
+#sdtv_mode=2
+
+#uncomment to overclock the arm. 700 MHz is the default.
+#arm_freq=800
+
+# Uncomment some or all of these to enable the optional hardware interfaces
+dtparam=i2c_arm=on
+#dtparam=i2s=on
+dtparam=spi=on
+
+# Uncomment this to enable the lirc-rpi module
+#dtoverlay=lirc-rpi
+##dtoverlay=ads7846,penirq=25,speed=10000,penirq_pull=2,xohms=150,rotate=180
+dtoverlay=ads7846,penirq=25,speed=10000,penirq_pull=2,xohms=150
+
+# Additional overlays and parameters are documented /boot/overlays/README
+
+# Enable audio (loads snd_bcm2835)
+dtparam=audio=on
+
+[pi4]
+# Enable DRM VC4 V3D driver on top of the dispmanx display stack
+dtoverlay=vc4-fkms-v3d
+max_framebuffers=2
+
+[all]
+#dtoverlay=vc4-fkms-v3d

+ 25 - 0
busunit/scripts/say

@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# Copyright (c) 2019 Clementine Computing LLC.
+#
+# This file is part of PopuFare.
+#
+# PopuFare is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# PopuFare 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with PopuFare.  If not, see <https://www.gnu.org/licenses/>.
+#
+
+if [[ "$1" == "" ]] ; then
+  exit -1
+fi
+
+echo "$1" | espeak --stdin --stdout | aplay 2> /dev/null

+ 28 - 0
busunit/scripts/volumeset

@@ -0,0 +1,28 @@
+#!/bin/bash
+#
+# Copyright (c) 2019 Clementine Computing LLC.
+#
+# This file is part of PopuFare.
+#
+# PopuFare is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# PopuFare 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with PopuFare.  If not, see <https://www.gnu.org/licenses/>.
+#
+
+vol=100
+
+if [[ "$1" != "" ]] ; then
+  vol=`printf "%2d" "$1" 2> /dev/null`
+fi
+
+chan=`amixer controls | grep Volume | head -n1 | cut -f1 -d',' | cut -f2 -d'='`
+amixer cset numid=$chan -- ${vol}% > /dev/null

+ 19 - 2
experiment/production/Misc-Notes.md

@@ -70,7 +70,7 @@ Might need to kill `fbi` when starting the kiosk.
 ### Packages
 
 ```
-sudo apt install -y sox espeak mplayer ffmpeg
+sudo apt install -y sox espeak mplayer ffmpeg alsa-utils
 ```
 
 ### Sound
@@ -82,9 +82,26 @@ the first two seconds of the audio if nothing is being played
 through it.
 The 3.5mm jack seems to not have that issue.
 
+---
+
+The 3.5mm jack has a lot of noise on the line.
+The fix looks to be using a USB speaker.
+For now we'll go with the 3.5mm jack but this will
+eventually need replacement.
+
+### Monitor
+
+To get monitor resolution:
+
+```
+fbset -s
+```
 
 ### Other References
 
-*  [cmdline.txt](https://www.raspberrypi.org/documentation/configuration/cmdline-txt.md)
+* [raspberrypi.org: cmdline.txt](https://www.raspberrypi.org/documentation/configuration/cmdline-txt.md)
+* [raspberrypi.org: 'How do I find out the display resolution?'](https://www.raspberrypi.org/forums/viewtopic.php?t=19817)
+* [elinux.com: RPiconfig](https://elinux.org/RPiconfig)
+