-
4) Publish at least one (1) image illustrating how the project might be used.
04/30/2017 at 19:34 • 1 commentThis may be a sketch, schematic, flow chart, rendering, or other type of image. - from Hackaday Prize rules.
So, @Radomir Dopieralski drew a sketch:
And I made a diagram:
Over these three months, while explaining ZeroPhone to people, I understood one thing - it's a platform, and platforms can be hard to explain because there are so many possible usages. ZeroPhone is a platform for hackers, people not happy with their smartphones, people that want privacy, people that want the power of Linux in their pockets and many more. I hope we'll see a lot of usage examples from all those categories as the project grows =) -
ZeroPhone software - pyLCI TODO and challenges
04/30/2017 at 12:20 • 0 commentsIntroduction:
When I started developing pyLCI, it was meant to be an interface for 2x16 character displays. Therefore, it was optimised for having only two lines of text on the screen and 5 buttons. I'm not aiming to maintain backwards compatibility between pyLCI for character displays and ZeroPhone pyLCI. In fact, the ZeroPhone version of pyLCI might as well be renamed to signify the fact that it's a similar, yet different version of software.
Right now, ZeroPhone pyLCI is not too far from original pyLCI in terms of capabilites. I'm listing those problems so that there's a list of problems that currently interfere with pyLCI being a good ZeroPhone interface.
The problems listed are either finished, WIP or still waiting to be solved - I encourage you to help me solve them by either helping me find a good solution, or contributing to the development (I've opened GitHub issues to keep track of problems, they're linked in the titles and sometimes in the text.)
Naming
pyLCI is Python-based Linux Control Interface. However, right now it's becoming ZeroPhone-specific and moving further from pyLCI concept. I'll be thinking of a better name - it obviously has a low priority, but if you have some ideas, please throw them here.
Text-based UI elements
As pyLCI was character display-based, it mainly operated with text. Right now, ZeroPhone uses a display which actually allows setting individual pixels, and there's much more screen real estate - but pyLCI still uses text in UI elements, using the display_data function which is limited to text. In fact, there's so much more ways a simple menu could look like, but it still does same old stuff it did before. Granted, it's going to be harder to test graphical views than it'd have been with text, but I don't have tests anyway, so maybe it doesn't matter ;-)
UI is mostly 5-key based
pyLCI was designed for as less keys as possible, and back then I decided that 5 keys should be enough for everyb^W basic interfacing needs. There were other keys, yeah, but I didn't have a good purpose for them at that time. Those keys are UP, DOWN, LEFT, RIGHT and ENTER - on default ZeroPhone keypad board, they form a cross in the upper center, it's easy to spot them. The problem is - right now, there are some other keys, and they aren't used, even though in many places they are the intuitive choice. For example, C1 and C2 (top left and top right corners) could easily be used for "Back" and "Options" choices in menus - but that's not yet the case. This is going to be fixed - but it's not as simple as updating the mapping because display also has to reflect the key purpose with some kind of labels right on top of the keys.
Also, the interface, as well as drivers, doesn't yet report type of keypress, as well as the fact that a key is held, though there's going to be a mechanism for it sooner or later.
Lack of tests
I never really taught myself TDD - my main software project for the last year has been pyLCI, and I often didn't know how the thing I'd have had implemented would behave like until I implemented it, so writing tests before adding functionality would never work for me =) However, right now there actually are things that could benefit from tests - mainly UI elements, and I do believe my programming style could benefit from getting used to TDD. The main obstacle (though a small one, admittedly), that was preventing me from just adding tests as I go, is mainly the setup cost - picking one of the testing frameworks and writing a base of tests for the most important things. Fortunately, this February, the project was joined by a person that is currently working on project's code infrastructure, as well as helping refactor the code. Shout out to [unnamed contributor], he's doing work that's vital for ZeroPhone success!
Division of apps by processes
Right now, pyLCI apps are more like plugins. You add them in a folder and they get auto-detected and added to main menu at pyLCI startup. This lacks all the flexibility that apps have, like "restarting/installing/uninstalling apps on the fly", but also adds security problems - now, each app can basically access any app's namespace and do whatever. Security is lacking, and so is usability. So, the outline of my idea is - run pyLCI core, with all its hardware drivers and context switching logic, as root, or maybe even as a low-privilege user added to groups having access to hardware. Then, make input and output proxies that'd run over local sockets, basically, make them RPC-enabled, and pass input and output events from/to apps that'd run as separate processes. It seems like a reasonable way, and, once there are input and output proxies, it should be easy as well. However, one challenge that comes to mind is running many, many apps under many different users. Like, if each app is going to need a Python interpreter and there are 20 of them, CPU and RAM consumption is going to be horrible. If that can be gotten down to even 5 processes of different levels of security, that would be awesome. The way to decrease process count, assuming most apps are stock and more or less trusted, is to have a process that could run multiple pyLCI apps with one Python interpreter, more or less how pyLCI does it with plugins, but have it over sockets and as a separate user. Say, we have a calculator app, a stopwatch/timer app, an app to fetch RSS from the internet and an app to control the music player - it's not unreasonable to launch them together in one interpreter, especially when they're trusted and more or less need the same privileges.
With the structure I'm describing, there's some good news, too - it's going to create pyLCI bindings for different languages, like, say, JavaScript - no matter what people talk about it, it's insanely popular. The downside would be having to reimplement all UI elements along with creating bindings for each language - UI elements are one thing that need to be in app-side code =(
One more obvious thing to point out - I don't know how much security could launching apps as different users give, there's certainly some but I can't tell if it's going to be secure enough to, say, eliminate any data leaks from a secure messenger when there's at least one untrusted third-party app. It's entirely possible there could be encrypted RPC and everything, but at this point I'm sure I'm missing something I'll discover while actually implementing this. Of course, this is a necessary feature and we'll have to figure that out.
Context switching - input/output proxies?
From the beginning, pyLCI is single-context - no multitasking, the workflow is menu-driven, you need to go back in a menu if you want to exit the current application and go to another. No notification support - the problem is that UI elements wouldn't know if they lost context, so if screen contents were suddenly changed, a menu wouldn't know that they did, and if input callbacks were set by something that popped on the screen, the UI element would never know it happened. The whole flow is quite linear, and one step throwing an exception, or an UI element accidentally setting callbacks at the wrong time, would make the interface not respond. This means that there can be no notifications, no hotkeys to switch to another app instantly, no "press call button to get to call menu", and this obviosly suc^W isn't a good architecture for phone UI, where any app could be requested at any moment. One of the main problems is that InputListener and Screen objects (i and o) speak to hardware directly, there's no object that could be passed to UI elements so that they wouldn't have to distinguish between "app active" and "app not active" states while operating, which IMO is more of a hack- compared to just having proxy objects that'd also save input/output state and be able to restore it instantly when the app is activated. For now, it's going to need some hacks (mainly because of the thread problem, described right below), but it looks very doable (apart from the fact I'll need to somehow save active PIL canvases from output device), and I've already started a small rewrite.
Threads constantly spawned - better idle loop? Idle loop managed by pyLCI?
When I started developing pyLCI, a long long time ago, I didn't know as much of programming architectures as I know today - and even what I know today isn't that much. In the beginning, pyLCI was basically menu code, horrible input/output drivers and some hard-coded functions. Even at that point, menu actions (move up/down, select element, exit menu) were callbacks. One of problems I stumbled upon at that time was that menus couldn't be nested because the input listener thread (the one to execute callbacks), being busy with the first menu, never got to callbacks of second menu. I solved it, but I didn't understand how - for a year and a half, I was occasionally thinking "It works, but I actually don't know why". Then, after a year and a half, when I was reducing pyLCI CPU consumption, I added some debugging statements to input listener threads and understood that, for each nested menu, a separate thread is started.
Say, we have menu A and its idle loop is run by Thread number 1, and there's input thread (Thread 2) that's executing menu A callbacks. ENTER key is pressed, and select_entry callback is executed from Thread 2. The callback is another menu's (Menu B) activate() method, so it, after setting things up, moves on to another idle loop. However, before that idle loop, menu calls InputListener's listen() method, which basically makes the InputListener forget about the currently running listener thread and launch a new one, Thread 3, which will then execute the Menu B callbacks.
I think this is a problem, but I'm not sure why - I had some points against that approach, but I have too much stuff in my head to remember them now. Also, I don't know how to actually solve it - now, all those threads help preserve UI element execution contexts, so that you can actually go back in a menu. If I were to remove the threads, I'd need to invent another way to store execution contexts, and a lot of stuff which, frankly, doesn't completely fit in my head. For now, having a context actually means any step in UI is done by an object - so all UI elements are objects (and Printer is trying hard to look like one). A context-less approach might yield some nice usage scenarios, but I can't imagine any good scenarios yet. Anyway, sometime this year I'll be looking into how other UI libraries implement it - and if somebody has a better plan, or is even willing to implement a new execution context scheme, that would help. For now, I'll probably make this behaviour more explicitly expressed in the code - and even after refactoring I might leave this "feature" in InputListener anyway, as long as it doesn't break anything, it could be useful in some apps.
CPU load
You've read about the thread problem, right? While UI elements run in background, they basically run an idle loop which sleep()'s. I'm guessing this isn't the best use of CPU time and could probably be done with something less CPU-consuming. There aren't useful things that UI elements could run while in background, but I guess there could still be a way to decrease CPU consumption - it might very well be that time.sleep()s could be replaced by something like select().
UI element rewrite - was it worth it?
While looking for ideas to solve thread problem, I decided to make an UI element rewrite and, possibly, also cover them with tests. The problem is - there are multiple UI elements that give a list of entries that you can scroll through - Listbox, PathPicker, Menu and Checkbox elements. PathPicker and Listbox were based off Menu UI element, but Checkbox wasn't - for some reason, I just copied the menu.py file to checkbox.py while creating the UI element. Considering that I was in a hospital because of some inflammation when I was writing the Checkbox element, I'm not going to question my motives =) However, the lack of an unified interface caused multiple inconsistencies when adding features - for example, Checkbox element didn't have "page up/down" or scrolling through elements, and PathPicker had some hacks due to the way it was overriding Menu functions. This all needed a better base class, that would contain all the repeating code. What I did was - print out the code, and then go through it with a marker. This is a way I use to refactor code, and while I'm guessing IDEs are much more effective at this, I've never been good with IDEs =)
I understood there are two kinds of UI elements - those that can be nested, and those that can't. For example, Menus can't be nested, which is one of their main features, PathPicker has a right button menu that lets you select a directory (instead of entering it, which is what ENTER key is going to do) and see its path. On the other hand, Listbox lets you select one element out of many and Checkbox lets you enable/disable things. First group has in_background property and will use that to know when to get deactivated, second group just uses in_foreground. After looking through the documents, I understood that second group can easily have the same base, and first group can re-use that base with some features added and one or two functions overriden, so that's what I did. For example, here's the Listbox inheritance chain:
Listbox <- BaseListUIElement
- and here's a Menu inheritance chain -
Menu <- BaseListBackgroundableUIElement <- BaseListUIElement
At the moment, the code pushed to GitHub, but is not finished. Hopefully I upstream the changes soon. There are also no tests now, I might need one more day just to make them - but I do want to test this through, since I was finishing the rewrite while being quite sleep-deprived, and I fucked up a couple more things that same day =) I do think it would be very unfair for me to not make tests after the test coverage effort a project's contributor started, though.
More code was deleted than added, this is a good sign IMO
Was there a benefit? I'm not sure anymore. On one hand, now the code doesn't repeat, it's likely going to be easier to write new UI elements, add features to existing ones and surround them with tests - especially since UI elements are the thing that needs testing the most, it's basically what the user interacts with, and where most of the logic happens. On the other hand, I can't imagine many list-like UI elements that could be added - there could be some that will be added once there's a need and a vision, but the question is - are they going to fit in the scheme that I created? Also, instead of understanding one Python object, you now need to understand a chain of two or three objects in two separate files. IMO, now the UI objects need much better documentation, with some graphs to show which functions are used and when, and how to override them to achieve whatever is necessary. Moreover, I didn't get a better insight into "new threads spawning" problem while refactoring, even though I hoped to - though I'm starting to get some ideas while writing this worklog =)
Listbox code shortened to three function overrides after the rewrite.
This is more or less all about pyLCI problems. Later on, there'll be a new installation of "ZeroPhone software": about APIs, power consumption, scripting interfaces and UI standartization.
P.S. I just saw that there's a "Project boards" feature on GitHub, and maybe these kind of issues could be better tracked by these. Does anybody have a good example of a project that uses GitHub Project Boards?
-
Project state: Gamma boards finished, beta boards released, components on the way
04/30/2017 at 11:35 • 0 commentsOne more iteration of hardware - I wish I could say it's the v1.0, but I made enough changes to know there will certainly be bugs. Therefore, it's a Gamma revision - this is the revision that's going to go to project contributors and reviewers. I already know about some changes that I want to make for the next version, but I'm afraid I don't have time to re-trace what I want to re-trace (to be exact, I want to move the GSM modem to the back of the back board, along with GPIO expander, and move the charging breakout to the front). However, that might just be the change I make today/tomorrow if I have enough time =)
I have ordered components for 20 ZeroPhones from Taobao - using Spreenow agent. They ordered everything for me, which was something I couldn't really risk, with about 30 different things I needed to buy. I spent 630 EUR on all the components, from which I think 400-450 EUR were spent directly on ZeroPhone parts (other were either extra parts or stuff for my personal projects). I'm surprised about how TaoBao is cheap, really. Before this, I didn't know about a good way to order stuff from China quickly. With Spreenow, I was able to submit a list of parts, they ordered them, checked all of them and sent them by EMS in a single box. When I tried to do the same with an eBay vendor, the price would have had been consolidated in a really expensive way, and last time I tried to negotiate a better price with a seller ('cause DHL from China shouldn't cost 150$ for 100$ shipment), the seller said "No, use the rate eBay gives you" and I was like "Fuck it" and re-planned the project I was working on at the time, which wasn't a pleasant thing to do.
Now I have all the PCBs I need, except one - I have to make a 7x4 board which would house the 18650 battery holder I'm using. Other than that, I'm ready to order panels filled with misc boards. The soldermask is blue - to look like all the Chinese breakouts the phone is using =) After that, it's time for software work - all the things I didn't yet code, I'll be coding them now. For that, there's a separate worklog - go read it if you're interested in software problems that ZeroPhone is facing.
Now, on the changes. Pi Zero W release prompted me to rethink my GPIO function choices. See, here are the pins that I think need to be free:
They have I2S, which is crucial if we want proper sound hardware on ZeroPhone. Otherwise, you could use the third SPI port of BCM2835 - SPI2 - even with 2 chip-selects, if we free GPIO17. So, I swapped the pins around and got a reasonable layout. Now I'm thinking I should free GPIO16 as well - this could be a good last minute change for gamma boards, now that I think about it =D
One of my ideas is to make expansion modules for the ZeroPhone using the connector that I2S is on - for example, to expose GSM audio to the system. However, the expansion headers on the sides won't be suitable for something that's supposed to be permanently attached. Instead, we could move the 5V DC-DC to in between the back board and Pi Zero (tricky, but doable) and then make boards which'd fit right where the USB DC-DC is right now - using castellated pads.
The beta back board was a mess. To fix it, I needed to simplify the schematic, rethink some of the design decisions and, sadly, get rid of some things I wanted to leave in. Even with the pin swapping, I've spent some time rearranging expansion header pins. For example, IR expansion header had +5V from the DC-DC, but when I looked at it once again, I understood it has to be routed diagonally through the whole board, from bottom to top right corner. However, the VBAT trace was right there near the IR header - and could provide more amps on demand, too (useful if you want to drive powerful IR LEDs, or maybe power a sound amplifier from that header) - so I've swapped +5V for VBAT.
I've also removed the level shifting circuitry that could allow one to use a 5V-only RTC like DS1307 - even though it would be nice to have, there was just no board space to properly route traces for it, and I2C traces looked like a mess with it.
ATMega header was one pin too wide for other headers to properly fit, so I had to make it a 6-pin header - however, it's now a "FTDI-compatible" header, meaning that it has the "GND-GND-VCC-TXD-RXD-RST" pinout. It can even work with 5V "FTDI" programmers, as long as the front board is disconnected from the Pi Zero (which is to be attached to the back board anyway). I left out the spare ATMega GPIO - but there's a solder jumper you can use to bring it back, so it's is not that bad =)
Here's a Google document with the pin mappings for alpha, beta and gamma boards. This is more of a wiki material, so the ZeroPhone wiki will appear sooner or later, once there are enough materials to put there.
In other news, I made a beta board release. For me, making a hardware release means listing both the features and the bugs - changes from the previous version and changes that'll have to be included in the next version. This will change once there's some kind of wiki in place - so that there's another place to keep track of bugs and features as they appear, and not only when the boards have been tested.
-
Why not a large display (with a touchscreen)?
04/15/2017 at 22:00 • 4 commentsThis is a complicated question to answer. Part of that choice is a design decision, another part is a matter of convenient development for me at the time I was working on ZeroPhone base, and there are also hardware limitations, let's start with those!
Hardware limitations
Raspberry Pi has a couple of display interfaces - or interfaces we could use for a display. Let's count - there's DSI, DPI (parallel RGB), HDMI, composite video and SPI, let's get through those.
DSI is supported by many cool displays, like iPhone screens. However, it's not available on Pi Zero, and is out of question for RPi in general - it's locked down, only peripheral that works with it is official Raspberry Pi touchscreen, which is large, expensive and consumes a lot of power. Next!
HDMI is good, it's GPU-accelerated, powerful and compatible with lots of stuff. However, there aren't many small screens compatible with it, it's proprietary-ish and the available HDMI chips don't have the best power consumption. Moreover, Pi Zero has MiniHDMI and it's hard to integrate stuff with this kind of connector. Let's leave it for an external display, next!
Composite video is ubiquitous, has been there for ages and is very cheap. It also has a fundamental video quality cap, and market is full of small shitty screens with no quality ones. The power issue is there, too - not only popular chips for analog video still use 5V, most Chinese product designers would use a linear regulator for in-screen 5V, and say that "it requires 12V" - bam, the power consumption is "horrible" on top of "bad"!
DPI is GPU-accelerated, supported by many displays and actually has software support. However, it would take most of GPIOs we have on a Pi Zero, and most of those aren't re-mappable, meaning we'd lose I2C, SPI, UART and some more cool things.
SPI is what ZeroPhone uses now. It's not GPU-accelerated, but we don't always need that - especially not in the case of a 128x64 monochrome display (though AFAIK it becomes relevant when screen is bigger and a color one). It doesn't use too much power, can reach high enough speeds for quick redraws (unlike I2C, for example) and is compatible with lots of existing displays.
Development and sourcing limitations
When I started this project, in December 2016, I was quite low on money. It was the end of the year when the idea of a wearable assistant was requiring more resources and skills than I had, and pyLCI had most of the features I needed from it. It was time to change my course to a bigger project, something that I could dedicate most of my time to - and a smartphone project was something I could personally get behind. I was looking at eBay, picking screen breakouts to sample, and most of them were unsuitable - by size, by price or by some other characteristic. Some of them were horribly outdated - like the Nokia 3310 display, 84x48 isn't enough when you see just how huge those displays are.
- Ideal display - but not symmetric because it has 7 pins and adjustable header has 8
- Even more ideal display - same, but symmetric!
- Small and no breakout available (though cheap and with color pixels)
- Huge, especially compared to its pixel count
- Small (though interesting for a notification display mod)
- Monochrome, cheap&popular but very small
- Allegedly a color display, but the breakout is the same as 6 (did the seller fool me?)
- Just huge
- Huge and the pinout is crazy
- Absolutely barbaric (for scale)
With the money I had, I bought 3 color OLED panels (I didn't get to make a breakout for them yet), 1 color OLED with a breakout (which I didn't put to use, ultimately), 3 1.3 monochrome OLEDs and 3 TFTs of different pinouts - all ILIxxxx, two 1.8" and one 1.44". When they arrived and I compared them, it became clear which is the main one to be used for now - the 1.3" OLEDs, which you've seen many more times since then =)
Even now, ZeroPhone still has the adjustable headers and backlight PWM pin (unnecessary for OLEDs) - from that time when I wasn't sure about which one I'd have had picked, but would need to make any of them fit well. I'm not sure if this feature is worth keeping at this point - will people use it at all? See, for other screens to work, there'd need to be a driver, and while it wouldn't be too hard (luma.lcd library accepts most of the screens that fit those headers), most of the people aren't going to be concerned about this.
("most of the people aren't going to be concerned about this" - it's a problematic statement, because most of ZeroPhone's features are what most people don't care about. That's why it's so hard for me to leave features out =) )
Vision of the project
There are, I'm sure, billions of phones with touchscreens in this world by now. The thing is - having a large display and a touchscreen isn't the main feature of ZeroPhone, and if we focus on that, we would obviously never win, and we can't compete with any of current mass-produced smartphones by hardware. Thankfully, ZeroPhone is not about hardware, it's about what you can do with it. It's about having control over your smartphone, about using it in scenarios nobody yet thought of and modifying it to suit any task you want it to do. ZeroPhone is a phone you can trust, one that serves you instead of whoever programmed it and whoever designed the apps you run.
When I was designing the current version of ZeroPhone, I understood I had to abandon "large display with touchscreen" for "accesible, Raspberry Pi-based, power-efficient and easy-to-use". Just like ZeroPhone wouldn't really take off without the success of Raspberry Pi, a ZeroPhone with a big display won't be able to take off until there's a good hardware interface for it available, and a suitable display to support it. Hopefully, we'll see some projects like that in the next years =)
Don't get me wrong - powerful hardware is nice to have. However, until we actually can get some to work with, let's squeeze the most out of what we can get ;-)
-
Resuming work - boards, coding and Taobao
04/11/2017 at 21:37 • 5 commentsAfter quite a delay, I'm resuming writing worklogs. Even with lots of donations, I still wouldn't have enough money to order all the parts and boards, and pay for all the shipping I'd need. So, I accepted a freelance project offer a couple of weeks ago, and completed it successfully - right now I have enough money to not worry about money, and to not be pressed to cut corners on things. I still need to go the TaoBao route, but with the funds that I have, I can build 20 to 24 phones instead of 10 to 12 (depends on how many boards DirtyPCBs will send me). So, I'm returning to full-time ZeroPhone work.
With that out of the way, roadmap for this month is simple:
- Writing logs and answering emails - through this week
- Ordering parts - starting from tomorrow
- Writing software - starting this week, till the parts arrive.
- Preparing crowdfunding - main worry is financials, along with writing good PoC software for demo units
- As soon as parts arrive, assembling phones and sending them out
I'd elaborate more, but it seems that my habit to write logs only when things are more defined and complete is getting into the way of how much I should write =)
I hadn't posted any photos in a while - let's fix that:
Beta ZeroPhone, with a 7-pin OLED, no speaker and very small battery, so always connected to charger ;-)
Back board view - ugly, but most of the ugliness is fixed in the new release
Side view - you can see the modem, the SIM slot and audio jack, as well as the small battery I initially connected to it.
I'd post more up-to-date photos - now I added a bigger battery, USB port is turned 180 degrees and it has a 6-pin screen which looks more symmetric. However, I can't take new photos now, and I don't want this log to be blocked by this, so here we go =)
Now I'll go get some sleep - and continue writing when I wake up =)
-
Pi Zero W - first impression (designed in 2016?)
03/07/2017 at 12:06 • 4 commentsI got this beautiful board in the mail yesterday, put it in my pocket and forgot about it till I needed something from that pocket, about 20 hours later. Anti-static bags FTW, also, Zeros are small and this one is no exception.
Zero W 1.1, Zero 1.3 and back board of ZeroPhone Beta
This review is going to derive as much conclusions as possible from the PCB layout (comparing Zero W to a simple Zero), components, specs and datasheets - I don't even have enough components to assemble a Zero W-based ZeroPhone, never mind the time.
First of all, a closer look of the front - comparing the Zero W and the usual Zero.
- Must have been quite an optimization, stuffing it all in. CPU had to move further up, SMPS part got more tightly-packed. Most traces are re-routed. Even though connectors stay in the same place, most SMTs have been moved (with exception of HDMI stuff, it seems). Traces have been completely re-routed, some even moved to other layers (looking at the GPIO area.)
- They even removed Raspberry Pi logo and component markings (why were they even necessary on this board? It's not OSHW anyway.) Even USB port markings ("USB" and "POWER") were moved, even though there was enough space. RF black magic-ish requirements (not too likely, the USB label isn't that far from the antenna anyway)? Simply lack of space? Hard to tell for me, a weird decision. "CAMERA" label simply disappeared, too, though that one is understandable (but it could have been moved to the bottom, at least - and it wasn't).
- RPF also changed inductor of the SMPS - apparently, to one capable of more current (it's 3.3V line inductor, in case you were wondering, I just checked).
- The u.FL connector could just be usable, but I should re-read the RPF statements - I recall hearing something about the fact that this antenna is as good as RPi3 one. Having an external antenna is generally good, but even the permanent mod is going to be hard - moving a 0402 (is this even 0402, or is it smaller?) is, well, tricky. As for this, I should go ask somebody what kind of antenna is this.
- A temporary mod like "a connector with a switch" would be hard to make, too. Depending on what part of the antenna trace actually works as an antenna, it could be from easy to impossible - it'd require cutting traces, anyway. I don't think we'll be getting monitoring mode with this one, too - when I last looked, it wasn't there.
Zero W 1.1 and Zero 1.3 - back sides
- Testpoint markings disappeared from here, too. However, the placement didn't change - I assume it's so that they don't need new testing jigs (however, VC JTAG FPC socket did get repositioned slightly!)
- There are 7 new testpoints, the smaller ones on the W. Even though BT+WiFi take 8 pins, there are only 7 testpoints. I'm very, very curious, why there are only 7 and what GPIOs do those correspond to.
- The OTG_ID testpoint (PP40 on the right board, same palce on the left) trace was re-routed in a weird way - it goes away from the connector, then goes to another layer and comes back, to the USB socket. Most likely, it's because of that space full of vias that the antenna goes through (part of the antenna?)
- There's a disclaimer about who they got the antenna from - "Uses antenna technology licensed from Proant AB". Could have been part of the deal they had to make to get a lower price, who knows - anyway, it's a good advertisement for them, I should check their site sometime soon =D
- The board copyright marking says "2016".
The last part is interesting - two months between the "board designed" and "board available" seems to be quite a long time for me. I assume that FCC took quite some time, or, possibly, RPF wanted to make enough of the boards first. Also, maybe v1.0 was designed in 2016, v1.1 was made more recently but the copyright year wasn't updated, who knows =)
Impact of the changes
- As with the Pi 3, the UARTs have been swapped - Bluetooth gets the stable and high-performance UART, we get the MiniUART instead of the one we were used to. What does it mean? This:
- It's going to consume more current. It's not going to be a problem with most Zeros connected to wall-warts out there, but might be a problem for the battery-powered projects, since we now need to make new power measurements. Also, does WiFi still have those stability problems in "power saving" mode?
- If you use a pHAT with a ground pour, it might negatively impact the antenna performance. In practice, you might not notice anything.
- If you have a case with a cutout for a CPU heatsink, it won't really fit - the CPU has moved.
What's the importance of this to the ZeroPhone project?
It's more good than bad news, in general.
- + We get Bluetooth - something that would have been hard to implement with just a Zero - UART is already occupied by GSM modem.
- + We free 6 pins - from the SDIO interface that ESP8266 used. We can then use those SDIO lines for something else, like, using SPI and getting additional UARTs through an SPI-to-UART chip, or using I2S.
- - There'll most likely need to be two different versions of boards, to accomodate the differences - the W version wouldn't need to have ESP8266, but could have something else instead. I'll have to think it over for at least a week. I'm already having problems with needing two different versions - one for 2G and one for 3G, this isn't any better.
- - The power consumption is yet unknown. If the WiFi+BT version would consume more current, all of the time, with no way to disable it in a way that lowers the current consumption to the same values that normal Zero has, that'd just suck, a lot.
- - MiniUART - ZeroPhone uses the UART for a GSM modem, and any stability problems are going to be a big problem for ZeroPhone, given it's supposed to be a phone, first and foremost. We could try and swap the UARTs (so we get normal GSM and so-so BT), but we can't do it fully - we can remap normal UART back to the GPIO header, but we can't remap the MiniUART to the Bluetooth, unfortunately (not without hardware mods, maybe the testpoints could be used). Hell, it's not even certain BT hardware (as well as driver) could use the MiniUART.
TODO:
- Power consumption measurements - compare to ESP8266-based solution (will be easier to do once I get the current sensor boards from DirtyPCBs)
- Determine those 7 testpoint purpose and GPIOs - maybe try toggling them from userspace?
- Plan out the GPIO alt functions for the next revisions of ZeroPhone - quite likely, for the version that comes out as a result of the crowdfunding (should the version that I'm developing now be called Gamma instead of v1.0?)
-
ZeroPhone - streaming to Youtube Live, Facebook or Twitch
03/04/2017 at 01:00 • 0 commentsI recently spent a weekend on a hackathon. It was organized by Garage48, an organization that makes hackathons, among other things. This hackathon was called "Hardware&Arts", naturally, it's hardware-centered, with a really small part of "arts" in it. I pitched an idea, assembled a small team interested in it - and we've made it in 48 hours! More importantly, it can work with ZeroPhone, too.
%YOUTUBE_VIDEO_OF_OUR_PITCH%
The idea is Streamo. It's a lifestreaming device, a camera and a microphone streaming your life to the Internet 24/7. It's not for the faint of heart, but I have a friend who believes it could be the next cool thing, and is willing to do whatever it takes. And, of course, it's Pi-powered (I've described it here earlier, it's #Twitch Your Life - a Raspberry Pi streamer device, but it's an old description).
The gist of it is a ffmpeg command-line - video from camera, audio from microphone, all is re-encoded and goes into an rtmp stream. We spent quite some time making it work, you could say we spent a day and a half debugging one line of code =) Regardless, it's very simple - and it's not something you'd be capable of doing on your Android, not without a smartphone-tailored app, at least.
Funny thing is that the command-line actually needs minimal changes to work across at least 4 services - Facebook, YouTube, Twitch and Ustream. That means - there could be a ZeroPhone app for one-click streaming to the most popular streaming services out there.
There's still plenty of work to be done. We need to make it more hardware-accelerated, test it for connection instabilities, make safeguards, command output parsing and
I'll only guide my friend on the software (and develop hardware for him), I do have enough projects to manage already. I'm going to build a small Pi Zero-powered platform for him, with plenty of batteries to get through the day (and a Pi3 workstation for quicker development, if he ever needs to recompile ffmpeg, like I did). However, once it's done, it could be easily ported to the ZeroPhone, so that ZeroPhone users get this feature, too - not only for lifestreaming, but for any time they want. What are your thoughts on this?
-
Project state - testing beta hardware, CrowdSupply,
02/26/2017 at 01:16 • 1 commentI've had about a week of a delay in the project - went to a hackathon, then did some work on the #ICeeData project, then fell ill for a couple of days. When I came back to my hackerspace, I got a note saying the back board shipment was waiting for me at the post office, and this was a powerful reminder about ZeroPhone. I went to the post office, received the boards and started assembling the next version of the hardware.
It's not fully assembled yet - I need to get some more parts, but as soon as it's done, I'll test it, find bugs, make v1.0 of the boards and send them to the board house (should I get the blue soldermask option so that it goes well with the Chinese module PCB color?) That's for the "sending prototypes out" part. I wanted to do more of this in parallel, but now I see that this part of hardware prototyping can't be done in parallel. I need to get the boards, assemble a phone and then see if it works - only then I'll have boards I could send to reviewers.
Tl;dr, current targets:
- Quick newsletter edition (it's been 20 days since the #3)
- Testing hardware
- Ordering parts for the prototypes
- SD card image (alpha testers)
- BOM (for crowdfunding)
- A big project video
-
Software: notes on beta software, part 1
02/11/2017 at 17:23 • 0 commentsFebruary 11th:
Software is one of the numerous tasks for today. First, I decided to implement a character input UI element - using the numpad. It won't be as fancy as it's supposed to be, but that's beta. However, there are absolutely crucial features, and all added together they form a bulk of the work.
I decided to liberally spray the code with comments, as if whoever will be reading the code will be a Python beginner who has only interacted with the code but hasn't understood its workings yet. It goes against Clean Code, a book I respect and partially live by, but then - the code I'm writing is not for professional coders and there isn't a tightly-knit team of developers, and the code will be read much, much more often than it'll be modified. There's the problem of keeping the comments up to date, but, in general, commenting as the code flows might very likely become a contribution requirement, at least for the software core of the ZeroPhone project (I'm not going to dictate what external apps do, of course, as long as it's not in the core).
Numpad character input UI element is fun. I've discovered that, it seems, there's some kind of bug that makes the display library I'm using kinda crash Python (getting the same error message as this bug in numpy) - if you pass None as a string to be displayed on the display. Here's the commit which has the bug, I incorrectly thought it could've been a bug in the interpreter but then I remembered there actually is an external library I'm using for that and it's what should have the bug. There's a pull request to be sent then, but that's for later =)
There are two threads in any UI element - one is "application's current thread" (ACT, your Python application's thread, where activate() is running), another is "input listener's thread" (ILT, where callbacks attached input events are executed). In this UI element, ILT changes value upon keypresses, and ACT is responsible for "wait a second after last keypress and any consecutive keypresses will make a next character" - anybody who has ever typed an SMS on a keypad phone has encountered this. However, I pressed a button 100 times and got a race condition. Now onto learning threading.Lock.
An hour spent debugging an issue which I myself set up for me to stumble upon. Fail. At least I made this snippet (which didn't help me debug anything, but hey, it prettyprints what currently running threads are doing):
import threading import traceback import signal import sys def dumpthreads(*args): for th in threading.enumerate(): print(th) traceback.print_stack(sys._current_frames()[th.ident]) print() signal.signal(signal.SIGUSR1, dumpthreads)
Okay, I might just leave this UI element at "no on-screen pointer, no arrow keys used, thus, no character skipping and in-the-middle editing", at least for today. What's next? An nmap app? Can do.
February 12th:
Nope, couldn't. Spent half an hour on "'ImportError: cannot import name IncompleteRead'?" error, then had to go to sleep. "easy_install -U pip" fixed this problem. Let's try to nmap the hackerspace's network using CLI "nmap -sn" first:
There should be at least something that the app I'll write will be able to find. I know most of these devices, but not all, and, given some things there were left after the #Hacker Olympics 2016 @MakeRīga hackerspace, my app should be able to find at least something interesting - something I could show as proof-of-concept.
Let's see the Python-nmap package examples and whip up a simple app skeleton:
try: import nmap except ImportError: nmap = None def callback(): if nmap is None: Printer(ffs("nmap module not found!", o.cols), i, o, 3) return False menu_contents = [ ["Scan localhost", scan_localhost] #["Scan a network", scan_network], #["Scan arbitrary IP", scan_ip], ] def init_app(input, output): global i, o i = input; o = output
Basically, let's implement "Scan Localhost" function for a start, then go to other functions - as they all have their own requirements, "Scan Network" will need a way to get all available networks and "Scan IP" will need a way to enter an IP using a keypad, localhost scan needs neither and is therefore the easiest for PoC. However, all three will need a "show scan results" function - so we'll implement that in the beginning, too.
def scan_localhost(): host = "127.0.0.1" nm = nmap.PortScanner() nm.scan("127.0.0.1", "0-1024") show_scan_results()
Hmmm...def scan_localhost(host = "127.0.0.1"): scan_ip(host) def scan_ip(ip): nm = nmap.PortScanner() nm.scan(ip, "0-1024") show_scan_results_for_ip(nm, ip)
If can lay some groundwork now, why not? Now, showing results:def show_scan_results_for_ip(nm, ip): #Assembling a report we can pass straight to Menu object report = [] #Scan results for the IP, as we get them from nmap interface ip_results = nm[ip] #IP, state, hostname report.append([ "IP: {}, {}".format(ip, ip_results.state()) ]) report.append([ "Host: {}".format(ip_results.hostname()) ]) #Now assemble a list of open ports: protocols = ip_results.all_protocols() if protocols: report.append(["Open ports:"]) for protocol in protocols: ports = ip_results[protocol] for port in ports: report.append([" {}:{}".format(protocol, port)]) else: #No open ports for any protocol found? report.append(["No open ports found"]) #Show report Menu(report, i, o).activate()
First try, the scanning process actually was so slow I thought it hanged on something and Ctrl+C'ed it. There needs to be some visual feedback:def scan_ip(ip, ports="0-1023"): Printer("Scanning {}:{}".format(ip, ports), i, o, 0) #Leaves the message on the screen nm = nmap.PortScanner() nm.scan(ip, ports) show_scan_results_for_ip(nm, ip)
Should work, let's try again:I have a feeling I just passed those 20% of work which produce 80% of the result. Okay, now onto scanning networks. I got a library that can get IPs from "ip addr" output (alredy in pyLCI, in "Networks" app), but I need a library to get the network IP from the interface. "ipaddr" library from Google could help, let's see:
def scan_network_by_ip(ip_on_network) if ip == "None": Printer("No IP to scan!", i, o, 2) return False network_ip = #Reading library documentation, nothing there but confusing objects #...Okay, fuck the ipaddr library, I'll do it myself.
The "if_info" module I'm using to get network interfaces seems to be perfect to stuff some unreadable code into. Some experimenting:Works. Now, some unreadable byte-represented-as-string manipulation:
The top part is a proof you can write unreadable code in any language. The bottom part shows it works - now gotta finish it off:
It's written in the right way, and hey, who needs tests anyway?
root@zerophone-prototype:~/pyLCI/apps/network_apps/nmap# python -i if_info.py {'lo': {'addr6': '::1/128', 'ph_addr': None, 'state': 'unknown', 'addr': '127.0.0.1/8'}, 'wlan 0': {'addr6': 'fe80::b1ee:79a9:55db:63f4/64', 'ph_addr': '18:fe:34:02:8d:8e', 'state': 'up', ' addr': '192.168.88.153/24'}} IP 192.168.88.153/24 is from network 192.168.88.0 >>>
Now, moving on, back to the "scan entire network" thing. However, I'd need to test some code out:
def scan_network_by_ip(ip_on_network): if ip_on_network == "None": Printer("No IP to scan!", i, o, 2) return False network_ip = get_network_from_ip(ip_on_network) nm = nmap.PortScanner() import pdb; pdb.set_trace() #I should probably try Jupyter
Okay, seems like that to scan the network we also need to add the network mask, sounds reasonable. Some more code, small refactorings, bugfixes, and the network scanning feature is ready:It's all nice, but the menus that you can see can show that I lack one important feature - cursor. The HD44780 displays that pyLCI initially used have a cursor function, this doesn't - it just draws whatever you tell it. It's bad UX and needs to be fixed, and additionally I need to remake the Menu object so that it uses one cursor consistently. Let's see what the display library can offer...
Hmm, I can draw a line, or a rectangle. Should be enough!
Kinda better. Hmm, do I need the arbitrary IP scan thing? I guess not now - just don't feel like validating IPs/writing a keypad layer with proper mapping. Better add "show cursor" support to the numpad UI element - will it be any easy?
Yep, was pretty easy, and fixed a bug on the way there. Guys, overengineering FTW! Let's add some nmap features! First, saving a scan report by pressing a hardware key - from any place. For that, let's make some global storage variables and add an app-wide callback... Not that fast. Say, you go and scan a network (writes to storage), then scan an IP (writes to storage), then come back to network scan menu and press a button to record the scan - and it records the result of the IP, not the network, even though you have long left the IP viewing menu. It's obvious that the results have to be somehow restored, and that's what I'll do - with a decorator.
----------------------------------
February 16th:
Well, I had to go home, spent a day coding (without making a worklog), one day resting and a day sorting out everything related to project, but not to coding. Today, in short, I've finished the nmap app and added an UI element that can input numbers from the numpad - basically, made the NumpadCharInput UI element easily modifiable, so you can easily subclass it and substitute your own mapping. I also added "heuristic scan" and "any IP scanning" functions to the nmap app - aiming to make a video tomorrow morning =)
Some future features for nmap app:
- Caching of results - ain't nobody got time for scanning the same IP twice, takes quite some time so it'll be cool to have in the production version.
- Better support of the nmap flags, in general, just more ways to adjust arguments (submenus?). Also, better support of all the things that appear in the nmap output
- Looking through the captured files - IMO absolutely crucial
Some more important things:
- Making worklogs while coding is cool.
- Too verbose worklogs aren't cool
- There has to be some kind of worklog discipline. My thoughts:
- Not being too verbose - maybe pasting lots of code and big screenshots is excessive. It can be cool for tutorials, but this isn't really a tutorial (though kinda aiming to be one)
- Following some kind of timing - I usually use Pomodoro timing when I work, maybe, from that, 5 minutes could be taken to add something to the worklog. That could also help with the verbosity\
That's all for now. Sorry for the chaotic worklog, next one will be more organized - and expect a separate nmap app announce!
#Damn, I should add the photos sometime soon.
-
What about the apps?
02/08/2017 at 18:12 • 15 comments"Apps" is a concept that has been with us for ages. I won't be talking about anything that Apple, Google or Microsoft might mean by "apps", I'll use it as "applications, software" because it's short, precise and gets the point across, as well as the most common usage at this point in time.
ZeroPhone is not my first project of a portable, personal assistant, communicator device. Indeed, the listed qualities are what made smartphones so important in our lives. During all the previous projects I've worked on, I understood one important thing - in the end, it's all about software.
Nowadays, software support makes or breaks a project, I won't get tired of repeating it because it's true and software really is so damn important. This project needs to have above average software coverage quality - I want to outline what "above average" means here, and what I'll be aiming for when planning my priorities for the project.
In general, it's good coverage of what users need - and coverage of what other platforms don't provide. For now, my guidelines are:
- All the typical features that a phone should have. There's no way ZeroPhone can succeed if it hangs on every 10th call, or can't parse a popular (or obscure) type of SMS encoding.
- Some of the advanced features typically found in smartphones (not dumbphones). For example, caller/SMS sender blacklists, WiFi hotspot or simple SMS/phonebook data export functions (had lots of *fun* exporting caller lists from dumbphones at some time).
- Typically unavailable features - whatever is not found in phones at all because not too many people actually use it most of the time. Jamming/rogue cell tower detection, free GPIOs for sensors, a 5V output capable of charging other phones - anything that phone manufacturers won't even think about.
Other than these general focuses, I'll focus on those types of apps:
- Apps for easier tinkering. Makers are an important part of ZeroPhone audience. The ZeroPhone has about 50 different usable connection points you can use to make addons, and I want people to understand just how important it is to have them - because there are lots of amazing things you can do using interfaces that ZeroPhone offers. You can connect modules you could never add to your phone, for the low low prices of Chinese breakouts. The limit is no longer the decisions of those making your phone, it's the one of your imagination and skills, it's the inner beauty of tinkering that people over the world have come to embrace and love.
- Apps for privacy-concerned people. Say, Tor control panel I just wrote for ZeroPhone - it's supposed to give you control on when and how you want to use Tor on the ZeroPhone, and easy control over your tools is an important part of ensuring your privacy. Remember the bomb threat guy who was caught because he was the only one using Tor on the network? You shouldn't make stupid bomb threats like he did, but the threat vector will remain valid no matter how good your intentions on Tor might be - you might be a journalist in a war-torn country and get killed because of government looking on who's streaming through which ports. This is one of numerous reasons we need ZeroPhone apps if we want to counteract the privacy breaches happening everywhere.
- Apps for pentesting. For example, I want to make a simple nmap application - with some very important enhancements. Doing security assessments on networks/tech is something that people rarely do - this fact undermines security. I think the reason is - we're used to the fact that you need an security-oriented Linux distribution to use most of the tools typically necessary. What if you could use most of those on a stock ZeroPhone with a press of a button? For example, nmap - with a simple port-scanning script, bindings to something like metasploit and some simple logic added, you could instantly know of any potentially unsecured devices on your network. Looking at all the problems we encounter, I think easy-to-use one-click pentesting tools are important component of infrastructure in the future, something that could motivate us and help us fix the security mess we're creating.
For the infrastructure to actually be able to survive in the long term, I'll be enforcing limitations.
- Apps should be open-source. This is something A/G/M trio have no interest in enforcing. They want the best user experience, but they are going the "let the market regulate itself" way, with a couple of regulations to avoid breaking laws, as well as usual "we reserve all rights and are not responsible" clause. My opinion is that a single user should be able to fork and change any of the apps if he/she desires, no matter if it goes against what majority might want from the app, and this is exactly what open-source always helped with.
- Is open-source model a panacea? No. It's just damn good at what it does, which happens to be exactly what this project needs.
- No implicit tracking/analytics in apps. Ideally, make it opt-in. This is something an enoumous amount of people are tired of now, and I'll go to the slight extreme of "don't do it unless user explicitly agrees to help you". Open-source components and reviewing code should help with any bad actors on this, too.
- I understand there are ways where analytics and statistics help (such as better user need targeting, bug fixing and feature priority adjustment), so I'll be making sure app authors have a way to remind the user that there's a checkbox they could tick to help the author make better apps - by being better informed on what people need and use. I, for example, will make this feature for ZeroPhone UI framework - a "send error log to help fix bugs" button, a "yes, send telemetry to help development" checkbox (off by default), and a "receive notifications on important updates" mechanism (that'll be asked when ZeroPhone will be first configured).
- There should be a "readable code" expectation from apps. It doesn't matter if an app (external to the core code) is not well-structured as long as it works, honestly - and doesn't interfere with anything else. However, readable code is usually the most modifiable one. To paraphrase - a code that does app-limited localization can have a switch statement with hardcoded things instead of a map, where it'd be shorter to write a map using a dictionary.
- Of course, more elegantly-coded versions are better - but I know I can't expect too much from people that just want to share what they did for their own phones in their free time, and thought others could benefit from that as well. And the usual "no side effects" rules still stand - though more often than not it's easy to fix the side effects (hey, it's open-source!)
There are things I don't yet have a clue about, of course. For example:
- App distribution ways. There are app stores, there are mechanisms for adding GitHub repositories, there are distro-specific repositories and then there are custom package managers for things, all of those ways have its pros and cons, and I'm not yet sure what fits so it's bound I'll have to return to this later, when I'll have my requirements ready.
- If there's anything that has to be done about closed-source apps. While it's a requirement in my book, some people will be overriding it anyway and provide .pyc or .pyo files instead of plain .py apps. I'm going to discourage it, but sometimes people will do their own thing no matter what - and if you look at it, this whole phone is designed to allow people to do things without restrictions, so placing a restriction on it would be as inappropriate as to not allow people to change logos in the UI (a nice example of this is xscreensaver. I understand your reasons, and I disagree - the logo looks goddamn ugly to me).
- Something else that I have stupidly forgotten about? Any ideas, guys?
This guy can't wait to tell me about the extents of this post's suckery in the comments.
This post was hard, but satisfying to write - I know it addresses many important points and questions. As usual, I'd love to hear your feedback - here in the comments, or email me on info at zerophone dot org.
If you're coming from Reddit/HackerNews and you like this project: