Friday, December 11, 2009

Protecting Flash Memory of a Fujitsu MCU

I had a requirement to protect flash memory of Fujitsu MB95F128JB MCU but I could not find any satisfactory hardware/software tool to protect it. Later, I conceived an idea to hack its .mhx file. After adding the following line before the last line of the .mhx file, it had been protected.
S104400001BA
Ref: http://en.wikipedia.org/wiki/SREC_%28file_format%29

Saturday, October 10, 2009

Multidrop network for RS232

I got a requirement to communicate one master device and eight slave devices. I intended to use RS485 half-duplex communication for this system but all devices happened to have only RS232 interfaces. RS232 communication is a sort of communication that is to be used for one-to-one system. There is no problem if only the master device transmits and all slaves are receiving. The problem is that transmit lines of the slaves cannot be disabled and so that they cannot connect to the same line. After analyzing the voltage signals, I have got an alternative solution to this problem. By adding a diode to the transmit line of each slave, I can use the system just like RS485 half-duplex communication. See the following figure for the hardware connection.


Updated: 2017 Sep 02
Thanks for all your comments. I have added more configurations according to your comments.

RS232 network with multiple masters and multiple slaves



UART/TTL-Serial network with single master and multiple slaves

If you are not using RS232 transceivers to change the physical signal voltages, the outputs of UARTs are still TTL level signals. In this case, you can connect multiple UARTs to a single master as follow.



UART/TTL-Serial network with multiple masters and multiple slaves



Friday, September 25, 2009

CRC Calculation in VB and C

Just to share a few software modules that were written in Visual Basic 2005 and C for the calculation of CRC -Cyclic Redundancy Check.


CRC Calculation in VB2005

The followings are the source code for various CRC calculations in VB2005. To make the calculation faster, they use CRC tables.


CRC Calculation - GitHub

An example usage for calculation of CRC16 CCITT is shown below.

Dim StrIn as String= "String to calculate CRC"
Dim CRCVal16 As UInt16 = 0
Dim crc As String
CRCVal16 = CRC16_CCITT.Calculate(StrIn)
crc = CRC16_CCITT.ToString(CRCVal16)

Initial value for CRC16 CCITT is 0xFFFF. The following example calculate CRC for Str1 and use that CRC value as initial value to calculate Str2.

CRCVal16 = CRC16_CCITT.Calculate(Str1)
CRCVal16 = CRC16_CCITT.Calculate(Str2, CRCVal16)
crc = CRC16_CCITT.ToString(CRCVal16)

CRC Calculation in C

The followings are the source code for various CRC calculations in C. To save storage, they do not use CRC tables .


CRC Calculation - GitHub

An example usage for calculation of CRC16 CCITT is shown below.

#define STRLEN 4
char str[STRLEN]={0x01,0x01,0x00,0x0B};
unsigned char c[2];
unsigned int crc;
//Calculate CRC16 CCITT
crc=CRC16CCITT_InitialValue();
crc=CRC16CCITT_Calculate(str,STRLEN,crc);
CRC16CCITT_ToString(crc,c);
printf("CRC16 CCITT = %02X %02X \n",c[0],c[1]);


Online checksum calculator such as the following one may be useful to debug the code.

Online Checksum Calculator

Tuesday, August 18, 2009

SDCC - Small Device C Compiler

SDCC - Small Device C Compiler - is a free open source C compiler software for 8051 and a few other microcontrollers. Unlike SDCC, there are other popular commercially available compilers such as Keil that you can purchase. You can download a free evaluation version there but that trial version is limited to 2k byte code size. A good thing about SDCC is that you can get it for free at no cost. This post is just an overview of SDCC manual at http://sdcc.sourceforge.net/doc/sdccman.pdf. Writing and compiling of a few example C programs on Windows for 8051 are  also discussed.


Installing
Go to http://sdcc.sourceforge.net/ and download the setup program Run the setup program and follow the installation process.

Testing the SDCC Compiler
To test the installation of the compiler whether it is OK or not, go to command prompt and enter "sdcc -v". This should return sdcc's version number.

Example C Program
Type in the following example program using your favorite ASCII editor and save as led.c. This is an example C program for 8051 microcontroller to blink an LED connected to P3.4 pin.
#include<8052.h>
void main()
{
int i;
while(1)
{
P3_4=0;   //Output 0
for(i=0;i<30000;i++);  //delay loop
P3_4=1;   //Output 1
for(i=0;i<30000;i++);  //delay loop
}
}


Compiling and Getting Hex File
Go to the path where led.c is located and enter "sdcc led.c". If all goes well the compiler will link with the libraries and produce a led.ihx output file. You can enter "dir" to see if there is led.ihx file. After that, enter "packihx led.ihx>led.hex" to get the intel hex file that is suitable to download into your chip.

Projects with Multiple Source Files
SDCC can compile only ONE file at a time. Let us, for example, assume that you have a project containing the following file: main.c blink.c Type in the following example code in these files.
//File name: main.c
#include "blink.h"
void main()
{
while(1)
{
toggle();
delay();
}
}


//File name: blink.c
#include <8052.h>
#include "blink.h"
void toggle()
{
P3_4^=1;
}
void delay()
{
int i;
for(i=0;i<30000;i++); //delay loop
}


//File name: blink.h
void toggle();
void delay();

The files without main() function will need to be compiled separately with the commands: "sdcc -c blink.c". Then compile the source file containing the main() function and link the files together with the command- "sdcc main.c blink.rel". You will get main.ihx file and then you can get main.hex file as discussed before.

Monday, March 16, 2009

String and ASCII Code Conversion in VB 2005


We have written a customized class for various conversion between ASCII code and string that we need to use occasionally. The source code for the class can be downloaded A Visual Basic class to convert between hexadecimal, ascii, and text string on GitHub.
'Author: Yan Naing Aye
'WebSite: http://cool-emerald.blogspot.sg/
'Updated: 2009 April 24
'-----------------------------------------------------------------------------
Public Class ClsMyStr
    Public Shared Function AsAsciiEncodedStr(ByVal CharString As String) As String
        Dim outS As String = ""
        Dim temp As String = ""
        Dim i As Integer = 0
        For i = 0 To CharString.Length - 1
            temp = "00" & Hex(Asc(CharString(i)))
            temp = Right(temp, 2)
            outS = outS & temp
        Next i
        Return outS
    End Function
    Public Shared Function AsSpacedAsciiEncodedStr(ByVal CharString As String) As String
        Dim outS As String = ""
        Dim temp As String = ""
        Dim i As Integer = 0
        For i = 0 To CharString.Length - 1
            temp = "00" & Hex(Asc(CharString(i)))
            temp = Right(temp, 2)
            outS = outS & temp & " "
        Next i
        Return outS
    End Function
    Public Shared Function AsAsciiDecodedStr(ByVal AsciiEncodedStr As String) As String
        Dim outS As String = ""
        Dim i As Integer = 0
        Dim l As Integer = AsciiEncodedStr.Length - 2

        If (AsciiEncodedStr.Length Mod 2) <> 0 Then
            l -= 1
        End If
        For i = 0 To l Step 2
            outS = outS & Chr(Val("&H" & AsciiEncodedStr.Substring(i, 2)))
        Next i
        Return outS
    End Function
    Public Shared Function GetAsciiEncodedStr(ByVal RawAsciiEncodedStr As String) As String
        Dim i As Integer = 0
        Dim c As String
        Dim cmd As String = ""

        For i = 0 To RawAsciiEncodedStr.Length - 1
            c = RawAsciiEncodedStr(i)
            If (Asc(c) >= &H30) AndAlso (Asc(c) <= &H39) Then
                cmd = cmd & c
            ElseIf (Asc(c) >= &H41) AndAlso (Asc(c) <= &H5A) Then
                cmd = cmd & c
            ElseIf (Asc(c) >= &H61) AndAlso (Asc(c) <= &H7A) Then
                cmd = cmd & Chr(Asc(c) - &H20) 'change to upper case
            Else
                'MessageBox.Show("Got invalid character.")
            End If
        Next i
        If cmd.Length < 2 Then
            cmd = "0" & cmd
        End If
        Return cmd
    End Function
    Public Shared Function DoubleQuote() As String
        Return ControlChars.Quote
    End Function
    Public Shared Function Byte2Text(ByVal byteArray() As Byte) As String
        Dim str As String = BitConverter.ToString(byteArray)
        Return str
    End Function
    Public Shared Function Byte2Str(ByVal byteArray() As Byte) As String
        'Dim str As String = System.Text.Encoding.ASCII.GetString(byteArray)
        Dim str As String = ""
        For i As Integer = 0 To UBound(byteArray)
            str &= Chr(byteArray(i))
        Next
        Return str
    End Function
    Public Shared Function Str2Byte(ByVal str As String) As Byte()
        'Dim ba() As Byte = System.Text.Encoding.ASCII.GetBytes(str)
        Dim ba() As Byte
        Try
            ReDim ba(str.Length - 1)
            For i As Integer = 0 To UBound(ba)
                ba(i) = Asc(str(i))
            Next
        Catch ex As Exception
            ReDim ba(0)
            ba(0) = 0
        End Try        
        Return ba
    End Function
    Public Shared Function GetSignedDecimalText(ByVal RawStr As String) As String
        Dim i As Integer = 0
        Dim c As String
        Dim cmd As String = ""

        For i = 0 To RawStr.Length - 1
            c = RawStr(i)
            If (Asc(c) >= &H30) AndAlso (Asc(c) <= &H39) Then
                cmd = cmd & c
            ElseIf (Asc(c) = &H2D) Then
                If cmd.Length = 0 Then
                    cmd = cmd & c
                End If
            Else
                'MessageBox.Show("Got invalid character.")
            End If
        Next i        
        Return cmd
    End Function
End Class

Sunday, February 22, 2009

Reading and Writing a File in VB 2005

We occasionally need to read or write a file in Visual Basic 2005. For an easy reference, we want to post a few code here. The following two examples of reading and writing a file are from this web site.

Dim objStreamReader As StreamReader
Dim strLine As String

'Pass the file path and the file name to the StreamReader constructor.
objStreamReader = New StreamReader("C:\Boot.ini")

'Read the first line of text.
strLine = objStreamReader.ReadLine

'Continue to read until you reach the end of the file.
Do While Not strLine Is Nothing
  'Write the line to the Console window.
  Console.WriteLine(strLine)

  'Read the next line.
  strLine = objStreamReader.ReadLine
Loop

'Close the file.
objStreamReader.Close()

Dim objStreamWriter As StreamWriter

'Pass the file path and the file name to the StreamWriter constructor.
objStreamWriter = New StreamWriter("C:\Testfile.txt")

'Write a line of text.
objStreamWriter.WriteLine("Hello World")
'Write a second line of text.
objStreamWriter.WriteLine("From the StreamWriter class")

'Close the file.
objStreamWriter.Close()


If an error occurs while processing the file, the current method might be exited before you have an opportunity to close the file. A Try ... Finally block can be used to avoid this problem.

Dim strLine As String
Dim sr As StreamReader = Nothing
Try
    sr = New StreamReader(fileName)
    strLine = sr.ReadToEnd()
Finally
    sr.Close()
End Try



Visual Basic 2005 has a new Using statement that can automatically release one or more IDisposable objects. Any exception will be reported to callers. If you want to catch exceptions, you need a complete Try ... Catch ... Finally block.

Dim strLine As String
Using sr As New StreamReader(fileName)
    strLine = sr.ReadToEnd
End Using


Reading a text file can also be performed more easily by means of the new File.ReadAllText static method. For binary file, File.ReadAllBytes can be used.
Log File

We have written a class to write log files easily. Its source code can be seen and downloaded VB class for log file on GitHub.

'Author: Yan Naing Aye
'WebSite: http://cool-emerald.blogspot.sg/
'Updated: 2009 June 25
'-----------------------------------------------------------------------------
Imports System.IO
Public Class ClsLog
    Private mEnableLog As Boolean = False
    Private mLogFileDirectory As String = ""
    Private mLogFilePath As String = ""
    Private mLogFileLifeSpan As Integer = 0
    Private mLogFileFirstName As String = "AppName"
    Public Sub New()
        mEnableLog = False
        mLogFileDirectory = My.Application.Info.DirectoryPath
        mLogFileLifeSpan = 0
        mLogFileFirstName = My.Application.Info.AssemblyName
    End Sub
    Public Property LogFileLifeSpan() As Integer
        Get
            Return mLogFileLifeSpan
        End Get
        Set(ByVal value As Integer)
            mLogFileLifeSpan = IIf(value >= 0, value, 0)
        End Set
    End Property
    Public Property LogFileFirstName() As String
        Get
            Return mLogFileFirstName
        End Get
        Set(ByVal value As String)            
            mLogFileFirstName = value
        End Set
    End Property
    Public Property LogEnable() As Boolean
        Get
            Return mEnableLog
        End Get
        Set(ByVal value As Boolean)
            If value = True Then
                If Directory.Exists(Me.LogFileDirectory) Then
                    mEnableLog = value
                Else
                    mEnableLog = False
                    Throw New Exception("Invalid file directory.")
                End If
            Else
                mEnableLog = value
            End If
        End Set
    End Property
    Public Property LogFileDirectory() As String
        Get
            Return mLogFileDirectory
        End Get
        Set(ByVal value As String)
            value = Trim(value)
            If Directory.Exists(value) Then
                Dim i As Integer = value.Length - 1
                If (((value(i)) = "\") OrElse ((value(i)) = "/")) Then
                    value = value.Substring(0, i)
                End If
                mLogFileDirectory = value
            Else
                Throw New Exception("Invalid file directory.")
            End If
        End Set
    End Property
    Public ReadOnly Property LogFilePath() As String
        Get
            Return mLogFileDirectory & "\" & mLogFileFirstName & Format(Now, "-yyyy-MMM-dd") & ".log"
        End Get
    End Property
    Public Sub WriteLog(ByVal LogEntry As String)
        If mEnableLog = True Then
            mLogFilePath = mLogFileDirectory & "\" & mLogFileFirstName & Format(Now, "-yyyy-MMM-dd") & ".log"
            Dim objStreamWriter As StreamWriter = New StreamWriter(mLogFilePath, True)
            Try
                objStreamWriter.WriteLine(LogEntry)
            Catch ex As Exception
            Finally
                objStreamWriter.Close()
            End Try
        End If
    End Sub
    Public Sub WriteTimeAndLog(ByVal LogEntry As String)
        WriteLog(Now.ToLongTimeString & " " & LogEntry)
    End Sub
    Public Sub CleanupFiles()
        If mLogFileLifeSpan > 0 Then 'if life span is zero, there will be no cleaning up
            Try
                Dim LogFiles() As String = Directory.GetFiles(mLogFileDirectory)
                For Each LogFile As String In LogFiles
                    If (DateDiff("d", File.GetLastWriteTime(LogFile), Now) > mLogFileLifeSpan) _
                    AndAlso (Right(LogFile, 4) = ".log") Then
                        File.Delete(LogFile)
                    End If
                Next
            Catch ex As Exception
            End Try
        End If
    End Sub
End Class

Sunday, February 1, 2009

FAT32 Format

I want to use my removable hard disk on both Windows and Linux machines. The problem was that Linux does not support NTFS and I could not format my disk to FAT32 in Windows XP. Using "format x: /fs:fat32" command ended in vain because it was larger than 32 GB. I also tried to format in Windows Vista but it still did not work in Linux. Later, I found a small and easy to use freeware program called fat32format.exe that can format large hard disks very fast. Just partition the drive, then type "fat32format X:" where X is the partition letter. Formatting a drive in FAT32 will allow it to be read by other operating systems, such as Mac, Linux, older versions of Windows, etc.

Tuesday, January 20, 2009

Using Notify Icon in Visual Basic 2005


To add notify icon to system tray is much easier in VB2005 than VB6. Create a new Windows Application in VB2005. Add NotifyIcon control as shown in the following figure.


Select "NotifyIcon1" control. In its properties window, choose "Icon" and open your icon to be used. If you do not define an icon there, you will not see notify icon in the system tray.
To display the notify icon when you close your application, go to code view and enter the following code to FormClosing event.

Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing        
          If MessageBox.Show("Do you really want to exit?", "Exit", MessageBoxButtons.YesNo) = Windows.Forms.DialogResult.No Then            
                e.Cancel = True           
                Me.Visible = False
                NotifyIcon1.Visible = True
          End If        
    End Sub 

To display the application back when you double click the notify icon in the system tray, write the following code in MouseDoubleClick event of NotifyIcon1 control.

Private Sub NotifyIcon1_MouseDoubleClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles NotifyIcon1.MouseDoubleClick
          Me.Visible = True ' Show the form.
          Me.Activate() ' Activate the form.
          NotifyIcon1.Visible = False
End Sub

To close the application also from File menu and context menu. Add these controls.


Then add the code 'Me.Close()' to their click event so that it becomes ...

Private Sub ExitToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExitToolStripMenuItem.Click
          ' Close the form, which closes the application.
          Me.Close()
End Sub

Private Sub ContextMenuStrip1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles ContextMenuStrip1.Click
          Me.Close()
End Sub

Select NotifyIcon1 control and define the ContextMenuStrip1 control in its ContestMenuStrip property so that the pop up menu will appear when you right click on the notify icon.

After that you can run the program. When you close the window, a message box will appear to confirm that you really want to exit. If you choose "No", the application will remain in the system tray on which you can double click to call back the application.

Sunday, January 18, 2009

Capturing and Sending Key -Using AJAX

AJAX is not a new programming language, but a technique for creating better, faster, and more interactive web applications. By using the key object -XMLHttpRequest of AJAX, we can create a dynamic webpage which can make a request and get a response from web server in the background without reloading the page. The user may not even notice that it is communicating invisibly.
Let us discuss an example that captures and sends the key input using AJAX. This example is based on the one that can be found in W3Schools site. There will be three files- keyCapture.html, keyCapture.js, and keyCapture.php.
First, we will create an HTML page called "keyCapture.html" that have a DIV element to display the message returned by the server. All JavaScript will be put in a separate file.


<html>
<head>
<title>Key Capture</title>
<script src='keyCapture.js'></script>
</head>
<body>
<form>
Press a key to send to server.
<div id='text1' style="font-size: 40px; color:blue;">
</div>
</form>
</body>
</html>

Second, the JavaScript file called "keyCapture.js" is created to capture keyboard input and send to the server using AJAX. It is explained in details.

var xmlHttp;
document.onkeypress = DisplayMsg;
function DisplayMsg(key_event) {
    var keyChar;
    if (document.all) {
        keyChar = String.fromCharCode(event.keyCode);
    }
    else if (document.getElementById) {
        keyChar = String.fromCharCode(key_event.which);
    }
    else if (document.layers) {
        keyChar = String.fromCharCode(key_event.which);
    }
    xmlHttp = GetXmlHttpObject();
    if (xmlHttp == null) {
        alert("Your Browser does not support AJAX!");
        return;
    }
    var url = "keyCapture.php";
    url = url + "?keyC=" + keyChar + "&sid=" + Math.random();
    xmlHttp.onreadystatechange = stateChanged;
    xmlHttp.open("GET", url, true);
    xmlHttp.send(null);
}

function stateChanged() { if (xmlHttp.readyState == 4) { document.getElementById('text1').innerHTML = xmlHttp.responseText; } } function GetXmlHttpObject() { var xmlHttp = null; try { // Firefox, Opera 8.0+, Safari xmlHttp = new XMLHttpRequest(); } catch (e) { // Internet Explorer try { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } } return xmlHttp; }

There are three main parts in this JavaScript file.
1. Creating XMLHttpRequest object
2. To define a function to handle the data returned by the server
3. To send off a request to the server


1. Creating XMLHttpRequest object
Depending on browser, the method for creating XMLHttpRequest object can be different. ActiveXObject is used in Internet Explorer and XMLHttpRequest JavaScript object is used in other browsers. The following JavaScript function can be used to deal with different browsers.
function GetXmlHttpObject()
{
var xmlHttp=null;
try
  {
  // Firefox, Opera 8.0+, Safari
  xmlHttp=new XMLHttpRequest();
  }
catch (e)
  {
  // Internet Explorer
  try
    {
    xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
    }
  catch (e)
    {
    xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
  }
return xmlHttp;
}

In the function that wants to use the XMLHttpRequest object, we can just call this GetXmlHttpObject() function as
var xmlHttp
xmlHttp=GetXmlHttpObject();


If the object cannot be created, we can alert a message that AJAX is not supported.

if (xmlHttp==null)
  {
  alert ("Your browser does not support AJAX!");
  return;
  } 

2. To define a function to handle the data returned by the server
The following JavaScript define a function that will be called when the server response status has changed. The readyState property has five possible values (from 0 to 4) and it checks for request complete state (state value 4) before it process the response.


function stateChanged()
{
if (xmlHttp.readyState==4)
{
document.getElementById("txtHint").innerHTML=xmlHttp.responseText;
}
}

When the server response status has changed, the function stored in onreadystatechange property will be called automatically. It must be defined in the function that initiates the XMLHttpRequest as

xmlHttp.onreadystatechange=stateChanged;


3. To send off a request to the server
When we submit a request using "GET" method, the ids of the fields and values of that fields are sent in the url e.g.,
http://youraddress.com/keyCapture.php?id1=val1
We will modify the url of our php script using that format and add another ramdom value to make sure that cached version is not returned.


var url = "keyCapture.php";
url = url + "?keyC=" + keyChar + "&sid=" + Math.random();

By using the open() method and the send() method of the XMLHttpRequest object, a request can be sent to the server. The first argument of the open method can be GET or POST. The second argument is URL of the server-side script and third one specifies to handle the request asynchronously.

xmlHttp.open("GET", url, true);
xmlHttp.send(null);


Third, the server side script called "keyCapture.php" will be written in PHP as follow.

<?php
//get the parameter from URL
$k=$_GET["keyC"];
echo "Received: " . $k;
?>

Saturday, January 17, 2009

Capture Key Event in JavaScript

A friend of me wanted to control a hardware module that attached to a remote linux server using keyboard input in a client web page. She asked me how to do it. And I also didn't know :) We agreed to use JavaScript in client side and PHP on remote server. In the internet browser of the client computer, she didn't want to fill in and submit a form manually. That means key inputs must be captured directly and immediately sent to remote server to control the hardware accordingly.
After surfing for a while, a web page was found here about how to capture key inputs in JavaScript. Then we wrote a web page in PHP that sends key input directly. See the code that was written in "key.php".



<html>
<head>
<script language="JavaScript" type = "text/javascript">
<!--
document.onkeypress = DisplayMsg;
function DisplayMsg(key_event)
{
if (document.all) //Checks for IE 4.0 or later
{
document.form1.text1.value = String.fromCharCode(event.keyCode);
}
else if (document.getElementById) //checks for Netscape 6 or later
{
document.form1.text1.value = String.fromCharCode(key_event.which);
}
else if (document.layers) //Checks for Netscape 4
{
document.form1.text1.value = String.fromCharCode(key_event.which);
}
document.form1.submit();
}
//-->
</script>
<title>Capture Key Pressed</title>
</head>
<body>
<div style="display:none">
<form name="form1" action="key.php" method=GET>
<input type = "text" name = "text1">
</form>
</div>
<div style="font-size: 40px; color:blue;">
<?php
echo "Received: ";
echo $_GET["text1"];
?>
</div>
</body>
</html>


In this example, the problem in submitting the captured key is that the whole web page reloads everytime a key is pressed. It can be very slow when the page contains a lot of other contents. The better way is to use AJAX (Asynchronous JavaScript and XML) technique.