Windows 10 Lean and the next generation of Raspberry PI like x86 devices
The latest news about a “Windows 10 Lean” version of Windows sounds exciting, but it is not enough. Why ?
The technology today is there to create the tiniest x86 device yet which can run Windows 10 on a device as small as a Raspberry PI Zero. Yes, not just the Raspberry PI size SOC but one as small as the Raspberry PI Zero. We already have TV Stick style x86 devices capable of running Windows 10 and it is not without reason to think that something smaller could be created. But why haven’t we gotten there yet ?
The problem is with how software is written
What is overlooked is the core of Windows which has been there for a long time. Yes, the WIN32 API. Today everything is all about cross platform and mobile and the technologies used for that make some sense, but tiny x86 devices are not about cross platform nor are they all about browsing the web. Such devices would have a use for the so called “Maker” market, robotics and IOT (Internet of Things). A totally different approach is required for such devices. The key to such markets is:
“smaller, faster, smaller, faster, smaller, faster”
and that is not about hardware, but software. This quote was by the late Bob Zale, the creator of the once famous Turbo Basic (Borland International bought it from him) and the great grand child of Turbo Basic, called Powerbasic. I had the privilege to interview Mr. Zale back in 2011 and you can read the article on Tech Republic’s website here:
https://www.techrepublic.com/blog/software-engineer/interview-with-powerbasic-founder-bob-zale/
You can also listen to the Dot.Net Rocks podcast of their interview with Bob Zale and also Ethan Winer (co-founder of Crescent Software) here:
https://www.dotnetrocks.com/default.aspx?showNum=20
What did Bob Zale mean by “smaller, faster” ? Having used his BASIC compilers for nearly 20 years now, I can attest to how fast they compile, how powerful they are and how small an executable they can create. Powerbasic is one of the software industries best kept secrets. The only way to describe Powerbasic is that is it BASIC, with the raw power of C. This is not your grandfathers old interpreted BASIC, but it is a lean and powerful development system. It leverages the raw power of the WIN32 API, something I am well aware of myself. Having coded directly to the WIN32 API for nearly 2 decades now, it still amazes me the raw power there and the blazingly fast performance one can get from it. The beauty of BASIC when it comes to the WIN32 API is that the code is readable and understandable. For example here is a simple example which I created which emulates a Caption Bar inside a real custom control. The control is compiled into a DLL which can be used with any application, even ones written in C.
' ------------------------------------------------------------------------ ' Custom Class ControlClass Constants and Types ' ------------------------------------------------------------------------ %ControlClassExtraData = 6 ' # of Extra Data Items (Long) for All Custom Window Classes ' Data Items will be indexed from 1 in GetControlData function ' ------------------------------------------------------------------------ $ControlClassName = "CAPCTRL32" ' ------------------------------------------------------------------------ %WM_MYCOLOR = %WM_CTLCOLORSTATIC ' ------------------------------------------------------------------------ ' Custom Control Library Declares ' ------------------------------------------------------------------------ DECLARE FUNCTION GetControlLong(BYVAL hWnd AS LONG, BYVAL N&) AS LONG DECLARE SUB SetControlLong(BYVAL hWnd AS LONG, BYVAL N&, BYVAL V&) ' ------------------------------------------------------------------------ ' Custom Control Control Class Declares ' ------------------------------------------------------------------------ DECLARE SUB RegisterControlClass() DECLARE SUB ControlClassPaint(BYVAL hWnd AS LONG) DECLARE SUB ControlClassDraw(BYVAL hWnd AS LONG) DECLARE SUB BuildBitmap(BYVAL hWnd AS LONG, BYVAL CFlag&) ' ------------------------------------------------------------------------ %CP_CUSTOM_MESSAGE = %WM_USER+100 %CP_GETSTATE = %WM_USER+101 ' ------------------------------------------------------------------------ ' DLL Entrance - LibMain ' ------------------------------------------------------------------------ FUNCTION LIBMAIN(BYVAL hInstance AS LONG, _ BYVAL fwdReason AS LONG, _ BYVAL lpvReserved AS LONG) EXPORT AS LONG SELECT CASE fwdReason CASE %DLL_PROCESS_ATTACH ' =1 - Where DLL starts RegisterControlClass CASE %DLL_THREAD_ATTACH CASE %DLL_THREAD_DETACH CASE %DLL_PROCESS_DETACH ' =0 - Where DLL exits CASE ELSE END SELECT LIBMAIN=1 END FUNCTION ' ------------------------------------------------------------------------ ' Custom Control ControlClass Functions / Subs ' ------------------------------------------------------------------------ SUB RegisterControlClass() LOCAL windowclass AS WndClassEx LOCAL szClassName AS ASCIIZ * 80 szClassName = $ControlClassName+CHR$(0) windowclass.cbSize = SIZEOF(windowclass) windowclass.style = %CS_HREDRAW OR %CS_VREDRAW OR %CS_PARENTDC OR %CS_DBLCLKS windowclass.lpfnWndProc = CODEPTR(ControlClassWndProc) windowclass.cbClsExtra = 0 windowclass.cbWndExtra = %ControlClassExtraData*4 windowclass.hInstance = GetModuleHandle(BYVAL %NULL) windowclass.hIcon = %NULL windowclass.hCursor = LoadCursor( %NULL, BYVAL %IDC_ARROW ) windowclass.hbrBackground = GetStockObject( %WHITE_BRUSH ) windowclass.lpszMenuName = %NULL windowclass.lpszClassName = VARPTR( szClassName ) windowclass.hIconSm = %NULL RegisterClassEx windowclass END SUB ' ------------------------------------------------------------------------ SUB DefTrueSize(BYVAL hWnd&, AY&, ACY&) LOCAL AWS&, AH& AWS&=GetWindowLong(hWnd&, %GWL_EXSTYLE) AND %WS_EX_TOOLWINDOW IF AWS&=%WS_EX_TOOLWINDOW THEN AH&=GetSystemMetrics(%SM_CYSMCAPTION) ELSE AH&=GetSystemMetrics(%SM_CYCAPTION) END IF AY&=(AY&+ACY&)-AH& ACY&=AY&+AH&-1 END SUB ' ------------------------------------------------------------------------ FUNCTION GetTrueTop(BYVAL hWnd&, BYVAL Y2&) AS LONG LOCAL AWS&, AH& AWS&=GetWindowLong(hWnd&, %GWL_EXSTYLE) AND %WS_EX_TOOLWINDOW IF AWS&=%WS_EX_TOOLWINDOW THEN AH&=GetSystemMetrics(%SM_CYSMCAPTION) ELSE AH&=GetSystemMetrics(%SM_CYCAPTION) END IF FUNCTION=Y2&-AH& END FUNCTION ' ------------------------------------------------------------------------ FUNCTION GetHeight(BYVAL hWnd&) AS LONG LOCAL AWS&, AH& AWS&=GetWindowLong(hWnd&, %GWL_EXSTYLE) AND %WS_EX_TOOLWINDOW IF AWS&=%WS_EX_TOOLWINDOW THEN AH&=GetSystemMetrics(%SM_CYSMCAPTION) ELSE AH&=GetSystemMetrics(%SM_CYCAPTION) END IF AH&=AH&+GetSystemMetrics(%SM_CYDLGFRAME) FUNCTION=AH& END FUNCTION ' ------------------------------------------------------------------------ FUNCTION ControlClassWndProc(BYVAL hWnd AS LONG, _ BYVAL Msg AS LONG, _ BYVAL wParam AS LONG, _ BYVAL lParam AS LONG) EXPORT AS LONG LOCAL RV&, hParent AS LONG ' If message is processed then set FUNCTION=0 and then EXIT FUNCTION SELECT CASE Msg CASE %WM_SIZE IF GetControlLong(hWnd,6)=0 THEN SetControlLong hWnd,6,1 FUNCTION = DefWindowProc(hWnd,Msg,wParam,lParam) DIM R AS RECT GetWindowRect hWnd,R R.nTop=R.nBottom-GetHeight(hWnd) ScreenToClient GetParent(hWnd), BYVAL VARPTR(R) ScreenToClient GetParent(hWnd), BYVAL VARPTR(R)+8 MoveWindow hWnd, R.nLeft, R.nTop, R.nRight-R.nLeft, R.nBottom-R.nTop, 1 SetControlLong hWnd,6,0 EXIT FUNCTION END IF CASE %WM_CREATE DIM CS AS CREATESTRUCT PTR, WS&, EXS&, WP2 AS WINDOWPOS CS=lParam WS&=@CS.style EXS&=@CS.dwExStyle WS&=WS& AND (%WS_CHILD OR %WS_VISIBLE OR %WS_CLIPSIBLINGS OR %WS_CLIPCHILDREN OR %WS_SYSMENU) WS&=WS& OR %WS_CAPTION @CS.style=WS& EXS&=EXS& AND %WS_EX_TOOLWINDOW @CS.dwExStyle=EXS& SetWindowLong hWnd, %GWL_STYLE, WS& SetWindowLong hWnd, %GWL_EXSTYLE, EXS& CASE %WM_NCHITTEST FUNCTION=%HTCLIENT EXIT FUNCTION CASE %WM_LBUTTONDOWN IF GetControlLong(hWnd,5)=0 THEN SetControlLong hWnd,5,1 SendMessage hWnd, %WM_NCACTIVATE, 1,0 ELSE SetControlLong hWnd,5,0 SendMessage hWnd, %WM_NCACTIVATE, 0,0 END IF hParent=GetParent(hWnd) IF hParent<>0 THEN ' Uses the Standard Static control message SendMessage hParent, %WM_COMMAND,MAKLNG(GetWindowLong(hWnd,%GWL_ID),%STN_CLICKED), hWnd END IF FUNCTION=0 EXIT FUNCTION CASE %WM_LBUTTONDOWN FUNCTION=0 EXIT FUNCTION CASE %CP_CUSTOM_MESSAGE CASE %CP_GETSTATE FUNCTION=GetControlLong(hWnd,5) EXIT FUNCTION CASE %WM_PAINT CASE %WM_ERASEBKGND CASE %WM_SETCURSOR CASE %WM_LBUTTONDBLCLK hParent=GetParent(hWnd) IF hParent<>0 THEN ' Uses the Standard Static control message SendMessage hParent, %WM_COMMAND, MAKLNG(GetWindowLong(hWnd,%GWL_ID),%STN_DBLCLK), hWnd END IF CASE %WM_DESTROY CASE ELSE END SELECT FUNCTION = DefWindowProc(hWnd,Msg,wParam,lParam) END FUNCTION ' ------------------------------------------------------------------------ ' Custom Control Library ' ------------------------------------------------------------------------ FUNCTION GetControlLong(BYVAL hWnd AS LONG, BYVAL N&) AS LONG LOCAL I&, RV& RV&=0 IF N&>=1 AND N&<=%ControlClassExtraData THEN I&=(N&-1)*4 IF IsWindow(hWnd) THEN RV&=GetWindowLong(hWnd, I&) END IF END IF FUNCTION=RV& END FUNCTION ' ------------------------------------------------------------------------ SUB SetControlLong(BYVAL hWnd AS LONG, BYVAL N&, BYVAL V&) LOCAL I& IF N&>=1 AND N&<=%ControlClassExtraData THEN I&=(N&-1)*4 IF IsWindow(hWnd) THEN SetWindowLong hWnd, I&, V& END IF END IF END SUB ' ------------------------------------------------------------------------
Notice, that despite it being WIN32 API code, it is still quite readable. Yes, BASIC makes WIN32 coding easier. Now this does not mean that one has to write everything in low level WIN32 API code. You can write higher level libraries on top of it or even use PowerBasic’s thin API user interface wrapper (called Dynamic Dialog Tools) to makes things a little easier. I built my own GUI framework using Powerbasic and the runtime for the entire framework is only about 1 megabyte in size and it includes a number of built in custom controls, a 2D sprite engine, a 3D openGL based graphic control and much more. By writing easy to use wrappers over the WIN32, one can build software even faster and more easily. Here is how the code to a simple app looks like using a GUI framework I wrote in Powerbasic:
#COMPILE EXE #DIM ALL #INCLUDE "..\includes\ezgui50.inc" ' ******************************************************************* ' Application Constants and Declares ' ******************************************************************* %FORM1_LABEL1 = 100 %FORM1_HScrollBar1 = 105 %FORM1_LABEL2 = 110 DECLARE SUB FORM1_HScrollBar1_Click() ' -------------------- #INCLUDE "..\includes\ezwmain50.inc" ' EZGUI Include file for WinMain ' -------------------- SUB EZ_Main(VerNum&) EXPORT EZ_LoadPatternLib "", "" EZ_Color 0,-56 EZ_Form "FORM1", "", "Select Colors", 0, 0, 48, 18, "C" END SUB ' --------------------------------------------------------- SUB EZ_DesignWindow(FormName$) EXPORT SELECT CASE FormName$ EZ_Color 0, 0 EZ_UseFont -1 EZ_UseFont 4 EZ_Label %FORM1_LABEL1, 1, 1, 46, 10, "", "CS" ' -------------------------------- EZ_Color -1,-1 EZ_UseFont 4 EZ_HScroll %FORM1_HScrollBar1, 2, 12, 44, 1.5, "" EZ_SetHScroll "FORM1", %FORM1_HScrollBar1, -57, 36, 0, 5 ' -------------------------------- EZ_Color 15, 1 EZ_DefFont 10, "Tahoma", 16, "BV" EZ_UseFont 10 EZ_Label %FORM1_LABEL2, 2, 15, 45, 2, "Move Slider to change colors", "CI" ' -------------------------------- CASE ELSE END SELECT END SUB ' --------------------------------------------------------- SUB EZ_Events(FormName$, CID&, CMsg&, CVal&, Cancel&) EXPORT SELECT CASE FormName$ CASE "FORM1" SELECT CASE CID& CASE %EZ_Window IF CMsg&=%EZ_Close THEN END IF CASE %FORM1_HScrollBar1 IF CMsg&=%EZ_Change THEN IF CVal&<=31 THEN EZ_SetColor "FORM1", %FORM1_LABEL1, 0, CVal& EZ_SetText "Form1", 0, "Current Color Number is "+STR$(CVal&) END IF END IF CASE ELSE END SELECT CASE ELSE END SELECT END SUB
The point is, that one need not have to write code for a Windows Lean using the WIN32 directly, but one can easily build easier to use wrappers over it, but without all the bulk of most of todays UI engines, like dot.net. Yes, dot.net has its place with the cross platform world, but in the IOT world or “Maker” world, coding to the native API’s produce amazingly lean and fast applications and the hardware requirements are minimal. The GUI framework I wrote can work even on an old legacy PC with earlier Windows versions (before XP) with as little as 256 meg ram or even less and the CPU need not be more than 300 MHz (that is megahertz, not gigahertz). The diskspace requirements are almost nothing (less than a floppy disk for app and runtime).
So I have no doubt that a leaner Windows would still perform extremely well if one leveraged the WIN32 API.
Most of the current x86 “Maker” boards (System on a Chip or SOC’s) are targeting at full blown Windows and they need at least 2 GB ram and 32 GB EMMC disk space. But a tiny SOC board with as little as 1 GB ram and an 8 GB EMMC (or even less) would suffice for a very lean (WIN32 only) Windows 10 and apps written using Powerbasic or C. Actually I would not doubt that using Powerbasic, if Windows could run on as little as a 500 MHz CPU, 256 meg RAM and whatever the OS needed for diskspace plus 1 GB extra, would suffice for developing apps and running them all on the device itself. Some manufacturers are already making SOC boards with minimal x86 hardware, such as the 86Duino which sports a 300 MHz CPU and has directly accessible GPIO ports on it, which I have not doubt Powerbasic could run on, if a Windows Lean was able to run on it. Check out the 86Duino boards here:
http://shop.dmp.com.tw/INT/products-516
Do real software companies actually use the likes of Powerbasic ?
Absolutely! Fathom Systems in the UK are writing many applications for industrial use using Powerbasic. Check out this video of an amazing piece of industrial equipment where a laptop running an app written using Powerbasic is controlling it:
https://www.youtube.com/watch?v=D9fvdfE59_Y
At about 4 minutes and 33 seconds you will see a laptop running the controlling software which was written in Powerbasic.
Native coding is a must for developing fast and lean applications which can run with minimal hardware. Check out Herb Sutter’s talk (on Channel 9) entitled “Why C++ ?” and notice his comments about the benefits of native coding:
https://channel9.msdn.com/posts/C-and-Beyond-2011-Herb-Sutter-Why-C
The hardware is capable in the x86 world. Now software needs to catch up. This would allow manufacturers of small and tiny x86 devices (SOC’s) to build even smaller and cheaper x86 boards and devices. Imagine school children being able to purchase a tiny x86 board with a Lean Windows 10 on it and be able to write apps on it even in BASIC (a real compiler with the raw power of C). It is doable and I sure would like to see it happen.