Monday, September 26, 2011

Wrong Pin Numbers in PS/2 socket

Today I spent almost the whole working day to make (solder) a few adapters to remedy my PCB designing error. The problem was that I used MINIDIN-6 surface-mount female socket on my PCB, and I incorrectly routed PCB tracks to pins of that socket. It revealed that I used mirrored view of the socket when direct, non-inverted view should be used. Only one additional checking procedure would save me almost a whole working day.

PS/2 connector on Wikipedia

Tuesday, September 20, 2011

Forms (Windows) Interface Font

Delphi 7, while being very powerful IDE for Windows development, has some deviations from standards set by Microsoft. One of them is that by default, VCL forms use MS Sans Serif, 8pt font for all controls. This may look good on developer's machine, but on some target machines, this may look very bad because of lack of this font and substituting it for some another.
Standard behavior would be to use default OS Dialog font.
To overcome this, in each form's OnCreate event, invoke the following procedure:

procedure SetFormFontToSystemDefaultFont(Form: TForm);
var
  NonClientMetrics: TNonClientMetrics;
begin
  NonClientMetrics.cbSize := SizeOf(NonClientMetrics);
  SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, @NonClientMetrics, 0);
  Form.Font.Handle := CreateFontIndirect(NonClientMetrics.lfMessageFont);
  if Form.Scaled then
  begin
    Form.Font.Height := NonClientMetrics.lfMessageFont.lfHeight;
  end;
end;

(Set ParentFont property to True for all controls on the Form for this to have effect).

Sunday, September 18, 2011

Delphi Inactive Forms Behavior

In Delphi 7, there is one drawback in VCL, which appears as lack of any indication of which window is active when user clicks with mouse on inactive window. Standard behavior of compliant windows application is to flash the title bar of active modal window in that case, but Delphi forms do not respond to this action.

To remedy this, add the following code to your modal forms:
type
  TMyForm = class(TForm)
  ...
  protected
    procedure CreateParams(var Para: TCreateParams); override;
  ....
  end;
.... 
procedure TMyForm.CreateParams(var Para: TCreateParams);
begin
  inherited;
  Para.WndParent := GetActiveWindow;//to allow title flashing of child modal dialogs
end;

Friday, September 16, 2011

Electronic Component Misorientation Problem

Today the first preproduction batch of my devices, consisting of four PCBs (Printed Circuit Boards), was finally completely mounted, and I began to power them up in order to test the mounting accuracy and device functionality. It was revealed during mounting that I had placed some components too close to each other, although this will not prevent embedded software developers from using the devices to debug their firmware. When I started to bring the live into the device, I found that at one position, on all devices, stabilitrons were mounted in opposite polarity. It seems that assemblers who performed actual soldering, are accustomed to the fact that diodes' Anode pole are usually goes to positive polarity, and Cathode pole - to negative. This is true for simple forward usage of regular and shottky diodes, but stabilitrons need to be used in reverse direction. I marked where the Anode should be on assembly drawing, nevertheless it seems that assembler was guided by datasheet, where Anode mark is showed, and polarity of PCB padstacks. I'm thinking about resorting to using SOT-23 case for this component in second version of a scheme (for those who are not familiar with it: this is 3-leads case, it have 2 leads on one side and one on another, thus it is impossible to place it in wrong orientation). It may be _slightly_ more expensive than currently used 2-leads case, but it will leave us from necessity to think about right orientation and to control it.

It seems, that many engineering decisions are often driven by similar motivation - to ease manufacturing and/or repairing processes, at price of slightly increasing components cost.

It also reminds me that responsibility of everyone who design any type of interfaces, is to make every interface as clean and consistent as possible, and to make sure that working with this interface requires from user absolutely minimum of possible knowledge of a system.

SOT-23 drawing

Thursday, September 15, 2011

On Interface Design

For historical reasons (it was chosen by management of our firm to process salary payments), I have an account in one bank, with Internet banking option. The problem with its bank-client application, which should be used to access an account and to perform financial operations, is that it is evident that in some points it looks very unprofessional. The most prominent things are appearing of default Borland C++ Builder Icon as an Icon for Alt+Tab window and in the title bar of some windows, and inability of built-in browser window to resize accordingly when its parent window is expanded to the whole screen size. I believe that their application does not contain flaws that may compromise data transfer security, but if I would choose from different banks now, I would not stick with such a poorly written software. Their offices look as they should be - clean, modern, with polite staff, but it seems that their management do not realize that when I work with Internet banking, the face of the bank is actually the software.
After noticing that, I began to tend to double-check all my user interface look-and-feel features and logic, although neither of my programs deal with user's financial data.

Wednesday, September 14, 2011

Using of Pocket PC for Reading Books

I have an old Pocket PC iPAQ h1930 with Windows CE 4.20 on board. I'm not interested in beautiful flash games or watching video on it, so it serves me well for the purpose of reading books. It has about 3.6'' inches screen diagonal, so it can be put into any pocket, that is very handy. It does not have built-in GSM transceiver, so I have to use a separate cell phone in addition. This scheme has three main drawbacks:
1. When you have two devices instead of one, it is easier to forget one of them or to forget to charge one of them.
2. When you have a scanned book in PDF format, Adobe Acrobat, even in "Reflow mode", cannot reformat the strings to shorten them and to fit them into the available screen space. So if with minimum acceptable scaling value the text strings do not fit into the screen height, you have to constantly drag the document view back and forth in order to be able to see the whole sentences. This is rather annoying, although with some practice you become to pay much less attention to it.
3. Sometimes the device for unknown reason goes into totally unresponsive state, and I have to do a hard reset via special technical button and a pen. It happens about once a week or in a few days.

Although despite the above cases, the device saves me a lot of time by allowing me to educate myself during trips in public transport, and I understand, that buying any new modern gadget of similar form factor will not improve my productivity in this area. Electronic books have larger screens, but they are less handy to put into your pocket.

What I like in the device, is that there are many applications already written for Windows Mobile, so I have no problems with viewing of virtually any needed file format. Yes, I know that this OS is in fact abandoned by MS, but this does not matter, since all practically required applications are already there.

Tuesday, September 13, 2011

Reusing of Classes in a New Project

I recently started a new small software project (program). Part of its functionality and GUI is common with another my relatively mature program. The latter consists of many classes written during 2 years. Although I tried to apply the best principles of Object-Oriented design and programming, such as incapsulation, the least possible coupling between classes and units, programming via interfaces and not implementations, etc., but when code of your classes is used in only one project, it is very easy to leave some project (or domain-) specific code in places where it should not be found. This leads to more tightly coupled code and reduce overall system maintainability. When you attempt to use such classes in another application, all such poorly written places become obvious. I have already fixed several errors of that kind, and I see now that my first project also will gain benefits from it, via improved code readability and structuring, despite the fact that I did not add features to it. I think it would be a good practice to always have at least two projects which both use a set of common classes, in order to be sure that those classes are written properly and do not make unnecessary assumptions about their usage.

Monday, September 12, 2011

64-bit Delphi version is ready

Embarcadero has finally released so long-awaited Delphi IDE version with 64-bit target compilation mode support. By far, I have been using Delphi 7 for about 10 years, and it still allows one to create first-class windows apps. I reluctantly considered an idea of upgrading to newer versions of IDE because of large amount of source code written during these years and of old habit. But I feel that now it is time to upgrade. For me, three main reasons are:

1. 64-bit compilation support

For example, if you have MS Office Add-In, clients will inevitably ask for support of 64-bit MS Office. You have to create 64-bit DLL in order to be able to integrate with any of 64-bit MS Office application, 32-bit, no matter how good it is, will not work. The only plausible solution before was to create a 64-bit stub DLL in Microsoft Visual Studio. Now one can provide 64-bit support without using another IDE.

2. Native Unicode support

Although using of WideString type instead of AnsiString everywhere, and components such as TNT Unicode Controls, in general solves the problem, there still remains some artefacts. For example, you can not register COM server with regsvr32 command, if DLL resides in a path that contains characters which are not representable in the default system Ansi Code Page. And WideStrings was designed to be compatible with system OLE interface calls, and thus they are not reference-counted and use a special system memory allocation routine, which degrade performance. In
contrast, since Delphi 2009, the new native UnicodeString type was introduced, which is reference-counted and uses internal memory manager to allocate space, more efficiently than system-wide does. TNT Unicode controls are also, while work, look a bit like a crutch.

3. Bugs fixing in the IDE

Delphi 7 is convenient IDE, but some intricate bugs sometimes annoy. These include "internal compiler error", AVs, and inability to customize the IDE watches and debug windows in arbitrary way (I constantly got AV after effort to do this). The same applies to C++ Builder 5.5 which I also used for several years.
Embarcadero seems to pay much attention to quality in last years, I hope that their latest products are much more stable.

Unfortunately, C++ Builder XE2 does not yet include 64-bit compilation mode, but its next version anyway seems to fix that. All what is said above, applies also to C++ Builder (I used it for several years).

During last years, Embarcadero are making great efforts to rehabilitate Delphi & Builder IDEs reputation in comparison with MS Visual Studio and open-source competitors. I hope that when demand of support for ARM CPUs will become evident, they will add it in time.

Saturday, September 10, 2011

About testing

While working on my software projects, I often encountered a situation when almost all was ready for releasing a next version, but after starting final tests on different systems, many unexpected bugs were revealed. Sometimes after a small change in one part, other, presumably totally unrelated functionality, started to work wrong, sometimes the program worked right on one OS, but not on another, sometimes something very strange at first look appears.
The end conclusion that I have drawn is that testing should never be neglected or shrunk. It takes time, but if not done well, the end users will be whose who will find bugs and errors.

Similar thing has to be said about hardware testing. You should never be confident that a given part of device is working properly if it was not properly and thoroughly tested.

Object-Orieneted Systems Analysis and Design using UML

I'm currently reading the mentioned book from Simon Bennett, Steve McRobb, and Ray Farmer. Less than half of it already read, but I can say with confidence that the book is very useful, high-quality, with thorough and systematic approach.
I remembered that personally I too often neglected the software design phase and rushed to write a code, which led to far-worse-than-they-may-be solutions. I did not deal with large-scale systems as described in this book, all my projects were much smaller, but they definitely might (and should) be much better. I hope that even if I will not apply the exact techniques from this book, the systematic approach to software development process described by authors, will remind me about necessity to assign more time for planning and design when the next project will start.

This book on Amazon

Hard-to-find lack of variable initialization issue

Another bug which I once encountered, raised from using local (i.e., stack) method (or procedure/function) variables of record type. When you forget to assign some value to simple local variable, and then try to use it, Delphi compiler warns about it:
Variable "VarName" might not have been initialized
But when you have record-type local variable, and somewhere passes it as a parameter to another function, the Delphi (7) compiler does not check that you have initialized all fields. It will silently use whatever values was in memory at the call stack on the location that was taken for such record field. So you must be especially careful when using local record vars. Doing ZeroMemory on all such records at the very beginning of the function (or procedure/method), seems to be a good habit, otherwise it is a big chance that you will lose some valuable time trying to understand why the program behaves so strange.

To illustrate what has been said, take a look at the following code:

type
  TFoo = record
    a, b: Integer;
  end;

procedure A(Foo: TFoo);
begin
end;

procedure B;
var
  Foo: TFoo;
begin
  A(Foo);
end;

Compiler will not say anything on A(Foo) source code string.
The following string
ZeroMemory(@Foo, SizeOf(Foo));
before A(Foo), if will not make your program free of logical errors, but at least will make the program behavior predictable and reproducible.

Hard-to-find object variable overwriting issue

I write software programs in Delphi, version 7 (also in C++ Builder, but this post is about Delphi). Once I decided to optimize the code and to add "const" specifier to all parameter declarations of methods which are not changed in the method body itself. This is recommended for better readability and for performance reasons. For variables of WideString type, if you do not use "const" specifier in function parameters list, the compiler will create new copy of  passed WideString variable upon function entry and release it after function will return. This is because WideStrings are not reference-counted, as opposed to AnsiStrings. But when "const" is specified, the compiler passes pointer to string content (2-byte-wide chars) as is. So, I added "const" specifier everywhere when applicable, and did not receive any copiler warning. But during following testing, it turned out that something had became broken after this change. Strange error sometimes appears, which resulted in wrong value in some object field of type WideString. This error did not appear always, and only on one of two tested MS Windows versions.
I started to seek for the reason, and finally it traced to using WideString-type field of the object which passed as now "const" parameter. The code was something like:

procedure TFoo.SetProperty(const APropValue: WideString);
...
begin
...
  FPropValue := APropValue;
end;

....

procedure TFoo.DoSomething(const APropValue: WideString;...);
...
begin
...
  SetProperty(APropValue);
  DoSomethingElse(APropValue);
end;

procedure TFoo.DoSomething2(...);
...
begin
...
  DoSomething(FPropValue);
...
end;


The compiler did not detect any issues, yet the problem was
that after invoking of SetProperty, the previous pointer to WideChars array contained in FPropValue field, and in APropValue parameter, becomes invalid, but this old pointer value was used when invoking DoSomethingElse method.
I fixed the problem by eliminating "const" specifier from DoSomething declaration.

Be aware of such a pitfall!

Hello all

I decided to start a blog where I will share some of my thoughts about software and hardware development.