## Tuesday, December 31, 2013

### Value with a constant growth factor

Many times we hear in the news, either financial news or economy in general, about growths with constant factor.  For example: "The appreciated value of residential property in townville grows at 4% per year', or "The stock price grows constantly at 5% per year", or "the population of villageville decreases by constant factor of 5%".

What does it mean?

Well, it is actually simple.  The value increases by factor of 4%.  If the current value is A0, next year its value is A0 + 4%*A0.  Next 2 years the value is A1 + 4%*A1 = A0*(1+4%)^2 and so on.  From this, we can deduct a general formula for a growth (which is a form of geometric series):

A(t) = A(0) * (1+g/100)^t

Where A(0) is the value at the initial evaluation (t = 0)
t = unit time for the growth
g = percentage of growth (in %), so we need to divide it by 100 there
A(t) = the value at t

From this formula, we also can find "Doubling Time", or the time needed for a value to be double.

Tdouble = ln(2) / ln( 1+g/100)

For example:
Michael bought his house in 2002 for \$315,000.  The average appreciation rate of properties in his area is 2%/year.  How long he has to keep his house to make the house value double (assuming the appreciation rate stays the same)?

Tdouble = ln(2) / ln( 1 + 2/100) = 0.693/0.0198 = 35 years.

P.S:
For negative growth (decrease), use negative g.

More complex calculation is if the growth factor is not constant.

## Monday, December 16, 2013

### How to mount disk used by ReadyNAS

The following steps are useful if we want to salvage data stored in the drive in ReadyNAS.
I am not sure if the steps below are going to work on other ReadyNAS models, but it works on my ReadyNAS Duo (Sparc CPU).

Basically, what we need is a SATA-to-USB cable (can be bought on the Internet for couple of bucks).
NETGEAR ReadyNAS partitions the drive into 4 partitions.  In my case, it is detected as /dev/sdc:

[root@r3000 media]# fdisk -l /dev/sdc

Disk /dev/sdc: 1000.2 GB, 1000204886016 bytes
255 heads, 63 sectors/track, 121601 cylinders, total 1953525168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

Device Boot      Start         End      Blocks   Id  System
/dev/sdc1               2     4096001     2048000   83  Linux
/dev/sdc2         4096002     4608001      256000   82  Linux swap / Solaris
/dev/sdc3         4608002  1953092233   974242116    5  Extended
/dev/sdc5         4608003  1953092233   974242115+  8e  Linux LVM
[root@r3000 media]#

There are couple of issues if we try to mount the partitions directly:

1. ReadyNAS uses non-standard ext3 block-size, which in my case is 16384 bytes (use command "lvsc" to check)
2. The home directory is partitioned as LV group, so conventional mount command is not gonna work
Here's the steps:
• Scan the usb for LVM volumes and identify in the output the volume group name that has your READYNAS volume (mine proved to be c):
# vgscan
[root@r3000 media]# vgscan
Reading all physical volumes.  This may take a while...
Found volume group "c" using metadata type lvm2
Found volume group "vg_r3000" using metadata type lvm2
Found volume group "VolGroup" using metadata type lvm2

• Activate the group for ReadyNAS (in this case, the group name is "C")
# vgchange -ay c
• Find the logical volume that  (mine proved to be 'c'):
# lvs
• root@r3000:/home/root# lvs
LV   VG   Attr      LSize   Pool Origin Data%  Move Log Copy%  Convert
c    c    -wi-ao--- 929.09g

• To display the logical name of the partition, use command "lvdisplay":
# lvdisplay /dev/c
--- Logical volume ---
LV Name                /dev/c/c
VG Name                c
LV UUID                7HUOrf-B5bL-ur6r-ULsd-yl4m-gCrA-zQc4s9
LV Status              available
# open                 0
LV Size                929.09 GiB
Current LE             29731
Segments               1
Allocation             inherit
- currently set to     256
Block device           253:5

We cannot use regular command "mount" to mount the non-standard blocksize ext3 partition.  Fortunately, there is a tool called "fuse-ext3" running in userspace that can help us.  The tool can be downloaded here.

Here's an example how to mount my ReadyNAS's LV volume:

And here is the command to mount the system (root) partition which has the Linux software (I will post later about how to reset root password without resetting the ReadyNAS to factory default etc.)

### Why we need to migrate to IPv6 sooner

The test result above was done using DOCSIS 3.0 modem, XFinity Blast and thru 5 MHz Wi-Fi (802.11n).

I think of the reason is that with IPv6, we no longer need NAT on the router.  So the router most likely bypassed the traffic and directly forward it from the server to my computer (using global IP address).

The latency also improves with IPv6.  This might be caused due to the fixed size of IPv6 header, unlike IPv4.  All other optional headers in IPv6 are moved beyond the header, so routers can forward packets faster.

## Tuesday, December 3, 2013

### Technology used

U-Verse: FTTN (Fiber-to-the Node) and VDSL
Comcast: DOCSIS (DataOver Cable Service Interface Specification) and HFC

### Diagram

CMTS = Cable Modem Termination System  (usually at curbside of a neighborhood serving house)
VRAD = Video-Ready Access Device (usually at curbside of a neighborhood serving house)
VDSL = Very-high-bit-rate Digital Subscriber Line
CPE = Customer Premise Equipment (e.g, U-Verse Residential Gateway)
FTTN = Fiber To The Node
HFC = Hybrid Fiber Coax
RG = Residential Gateway

### How They Work

The central office above is a simplified of interwork of switches, edge routers (facing customers), and core routers (facing the Internet cloud, where Tier-1 backbone connections are interconnected).

#### U-Verse

The top network is AT&T network, while the bottom one is Comcast network.  Off course, the diagram above is oversimplified.  There are many other components of the Internet (web servers, mail servers, dhcp servers, dns servers, etc.  They will be discussed some day in separate blog).

AT&T's U-Verse network system consists of CPE sitting inside customer's home.  The upstream connection most of the time use existing coax cable that are usually pre-installed inside most houses for cable tv to minimize cross-talk and noise.  The Layer-1 protocol of this connection to VRAD is VDSL (or VDSL2 for higher speed [24 Mbps], or even VDSL2 bonding for even faster speed up to 45 Mbps.  Using VDSL2 vectoring, theoretically we can achieve even 100 Mbps).

VRAD is an equipment (a rack equipment) sitting at the curb aggregating traffic from premises (homes).  It acts mostly like a layer-2 switch (with some layer-3 capability, such as DHCP, IGMP, some filtering).  The uplink connection to C.O is FTTN (Fiber To The Node) via optical fiber using GPON technology (or other optical technologies), while downlink connections to premises using existing regular phone's twisted pairs.  VRAD usually is equipped with backup batteries, so even when there is power outage, customers still can make phone call (if the customer uses VOIP, he also needs backup battery for his/her CPE).

The AT&T's CPE usually has multiple downlink ethernet ports and one (or two) POTS for VOIP (optional).  One of the Ethernet port is connected to setop-box (in case the customer subscribes to video as part of dual-play or triple-play).  Internet packets and IPTV packet streams are separated over separate VLAN.  For example, VLAN=100 for the Internet, while VLAN=999 for IPTV.

When customer wants to watch a TV program by selecting a certain channel via remote, the setop-box sends IGMP join packet to VRAD.  VRAD, with its IGMP snooping capability, then requests C.O's router to send multicast packets containing the program.  This multicast packets are then forwarded to the customer's CPE as unicast packets.When other customers watch the same channel, they just join the multicast group and VRAD then forward the stream to them as unicast packets, so there is single multicast video stream coming from central office to VRAD.

All AT&T's residential gateway /CPE support Wi-Fi.  Wireless connection is treated like other wired connection in a sense it is bridged logically.  Once a CPE is up, as usual it sends DHCP (if it is set for automatic IP assignment).  This DHCP is snooped by VRAD and forwarded to C.O.  Once the client device has been assigned an IP address (public IP address), everything is the same as normal wired connection.  It is up to the CPE/RG to assign a local private IP address to any device connected to it (see previous posting for more detail about how it works).

#### Cable Network

Front Panel of a cable modem

Back panel of a cable modem

## Sunday, December 1, 2013

### Connecting Cable Modem to Two routers

Sometimes we want to split our home private network to two separate subnets, but want to maintain connectivity to the Internet/outside world. The following article tries to explain the basics and internals of most home WiFi routers in the market.

First, let see what are the basic components of a Wi-Fi router:

The following is an example of topology and connection of typical home network:

Router-1: Linksys WRT-54G running DD-WRT firmware
Router-2: NETGEAR Genie WNDR3400v2

The cable modem (DOCSIS modem) is connected to cable provider thru coax cable and its main function is to modulate/demodulate DOCSIS signal to regular ethernet frames (it might bind multiple channels [channel bonding] to increase bandwidth).  The cable provider assigns a public IP address to us to use.  This single public IP cannot be shared if we don't use router.

Router-1 and Router-2 see packets coming from modem, but they don't know how to route them to our devices at home yet.  Assume router-1 is the router that assigns DHCP IP address (running DHCP server), while DHCP server on router-1 is set to forwarder to router-2.  Router-2 is chosen as the main router because it has more recent hardware, supports 11n Wi-fi and supports IPv6 (PS3 is actually better to be connected to router-2 to lower the latency).

Other clients such as as Ooma, Roku and PS3 don't support IPv6 yet, so it's Ok to connect them to Router-2.

On Router-1:
• Set DHCP to DHCP forwarder (forward DHCP requests) to router-2 IP address
• Set router IP address to 192.168.0.1/24
• Set DNS to either public DNS (such as Google: 8.8.8.8, opendns's IPs or our own local DNS server)
• Operation mode: router
• Set wireless to bridged mode (so router-1's wifi is like another L2 ethernet device in our private LAN)
• WAN type: Static IP.  If it is set to DHCP and the WAN port of router-1 is connected to the ethernet bridge, DHCP server at the ISP site may deny the request or even worse, shutdown the connection completely (thus require modem reboot to fix the problem).
• Set WAN static IP to router-2 ip address.  This way, we assume router-2 is the gateway and delegates NAT work to router-2 (that's why we set the operation mode of router-1 to "router")

Router-2:
• Enable AP mode
• Set router IP address to 192.168.1.1/24
• Internet IP: Get dynamically from ISP
• Set DMZ to Router-1

### How it works:

A tablet is trying to connect to the Internet via router-2.  All Wi-fi transactions have been done and now it sends DHCP request to router-2.  If this is an initial request made to router-2, router-2 doesn't learn any IP yet so it first learns for the tablet's MAC. Because router-2 runs local dhcp server, it snoops any DHCP request and serves it.  In this case, router-2 then assigns an address in the subnet 192.168.1.0/24 along with DNS addresses and gateway IP (in this case, an ISP-assigned IP address) back to the tablet as DHCP RESP packet.

Now the tablet has a valid private address, now it can connect to the Internet via router-2.  All requests from the tablet is network-translated to public address and vice-versa.  So, if the public IP is a.b.c.d, tablet' IP address is 192.168.1.5 and it is requesting access to www.google.com (http www.google.com:80) from a local tcp port xxxx, the actual packet in the public wire is "a.b.c.d:yyyy", where xxxx is a the original tcp port and yyyy is the translated tcp port by NAT (router-2 maps local to public IP via port) [ Click this for more info about NAT/PAT mechanism].

OK, everything seems to work.  Wait...what about all other devices connected to router-1? What happens if we want to watch Netflix on Roku?

When Roku device is turned on, it sends DHCP REQ similar to tablet above.  The sequence is the same, but the difference is, because router-1 doesn't run DHCP server, all DHCP packets are forwarded to router-2.  So, it is assigned an IP address in the same subnet (sorry, the diagram above is wrong, the subnet should be the same).  When the Roku starts sending tcp packets, the packets not-intended to the private subnet and coming to router-1 are assumed to be forwarded to its gateway (router-2).  Router-1 sees these packets coming from its DMZ and do the same translation to public IP.

An alternative is to subtend router-1 to router-2 directly, not via ethernet switch.  The rest is the same.

## Sunday, November 10, 2013

### AT&T U-Verse with external wifi router running DD-WRT software

I don't like the way wi-fi connection is handled by CPE (Customer Premise Equipment, such as the provider's home gateway/router), so I want to use the Wi-Fi capability of Linksys.  DD-WRT gives features in handling L2 connections (MAC filtering etc.),  but I still want the CPE to handle DHCP and NAT services.  Basically, I just want to make the Linksys router acts like a Wi-Fi and Wired switch, as an extender of the existing CPE.

The objects in yellow box represents component in the Wi-Fi router (in this case, a Linksys WRT54G running DD-WRT firmware).

DHCP server on U-Verse CPE is configured to give IPs in 192.168.0.x subnet.  The CPE address is set manually to 192.168.0.1

Here's what I want:
CPE internal IP address = 192.168.0.1
IP range for Clients = 192.168.0.3 - 192.168.0.254

CPE setting:
• Wireless  disabled
• Configure DHCP to assign IP range: 192.168.0.3 - 192.168.254

DD-WRT settings:
• WAN connection type = disable
• Local IP = 192.168.0.2/24
• DHCP server = forwarding to 19.168.0.1 (CPE)
• Check option box to assign WAN port to switch (NAT is thus disabled; it is now acting like a pass-thru to switch)
• Wiress network configuration = bridged (so all Wi-Fi clients are seen by CPE as they're directly connected)
• Wiress Tx Power = 250 mW
• Advanced routing = router (doesn't matter actually)
• Disable CPI firewall
• Routing = disable
This way, all Wi-Fi is handled by Linksys router/switch, but only its L1-L2 layers.  Everything else is handled by the CPE.  We can also relocate the Linksys somewhere else, no need to be close to CPE as long as we have long ethernet cable or by using Powerline extender.

## Monday, October 21, 2013

### Which PC/gadget has the highest pixel resolution?

Here I have collected and calculated PPI (Pixels per Inch) for some laptops and tablets.

 Screen Diameter (inch) Screen Ratio (Width/Height) Angle (rad) Screen width Screen Height Number Of Pixels (Horizontal) Number Of Pixels (Vertical) PPI 15.6 1.78 0.51 13.60 7.65 1280 720 94.14 HP Pavilion 2000T 15.6 1.78 0.51 13.60 7.65 1366 768 100.44 17.3 1.78 0.51 15.08 8.48 1600 900 106.11 HP Pavilion 17z Laptop 14 1.78 0.51 12.20 6.86 1366 768 111.92 HP Pavilion 14 Chromebook 15.6 1.78 0.51 13.60 7.65 1600 900 117.68 18.4 1.78 0.51 16.04 9.02 1920 1080 119.72 Alienware 18 15.6 1.60 0.56 13.23 8.27 1680 1050 127.00 17.3 1.78 0.51 15.08 8.48 1920 1080 127.34 HP ENVY 17t 1080p 15.6 1.78 0.51 13.60 7.65 1920 1080 141.21 HP ENVY 15t Quad 1080p 15.6 1.78 0.51 13.60 7.65 1920 1080 141.21 Dell XPS 15 8.9 1.60 0.56 7.55 4.72 1280 800 169.60 Amazon Kindle HD 17.3 1.78 0.51 15.08 8.48 2560 1440 169.78 15.4 1.60 0.56 13.06 8.16 2880 1800 220.53 Apple Macbook 15.4 with Retina Display 13.3 1.78 0.51 11.59 6.52 2560 1440 220.84 Toshiba KIRAbook™ 13 Ultrabook 13.3 1.60 0.56 11.28 7.05 2560 1600 226.98 Apple Macbook 15.4 with Retina Display 14 1.78 0.51 12.20 6.86 3200 1800 262.25 HP TouchSmart 14 Ultrabook 8.9 1.33 0.64 7.12 5.34 2048 1536 287.64 iPad 8.9" with Retina Display 7 1.60 0.56 5.94 3.71 1920 1200 323.45 Amazon Kindle HDX 7" 8.9 1.78 0.51 7.76 4.36 2560 1440 330.02 Amazon Kindle HDX 8.9"

So far, nothing can beat Amazon Kindle HDX, not HP not even Apple iPad with Retina display.  Because the price of a laptop is significantly higher with higher PPI, the affordable price of Kindle plus its highest PPI makes it the best gadget for eyes and pocket!

## Saturday, October 12, 2013

### Distance Measurement

Last week my order of ultrasonic ranging device arrived.  With excitement I connected it to my Pic18 protoboard.  With my existing code framework I added driver to access this thing and display it to LCD (as well as logging it via rs232 to laptop pc).

I took a short video of  the board with my new iPhone5s and edited it using iMovie which is now available for free on iTunes store.

## Sunday, September 1, 2013

### XML-RPC Client/Server in Python

This demo shows how to have RPC connection in python.  The server collects CPU information (Linux).

Server-side:

#!/usr/bin/python
import re
import os
import sys
import xmlrpclib

from SimpleXMLRPCServer import SimpleXMLRPCServer

def is_even(n):
return n%2 == 0

def get_mhz():
try:
#return 0
f = open("/proc/cpuinfo", 'r')
except IOError:
print "Unable to access /proc/cpuinfo"
exit
except:
print "Other unhandled error (why?)"

else:
f.seek(0)
while line:
line = line.strip()
print "line = %s" % line
m = re.match("cpu MHz[\t ]+: (.*)", line)
if m:
print m.group(1)
f.close()
return m.group(1)

#    finally:
#        print "Sorry, still fails"

def xmlsrv_exit():
print "trying to exit now..."
try:
print "try sys.exit(0)"
#sys.exit(0)
except:
print "Unable to exit"

server = SimpleXMLRPCServer(("localhost", 8000))
print "Listening on port 8000..."
server.register_function(is_even, "xmlsrv_is_even")
server.register_function(get_mhz, "xmlsrv_get_mhz")
server.register_function(xmlsrv_exit, "xmlsrv_exit")
server.serve_forever()

Client side:

#!/usr/bin/python

import xmlrpclib

try:
proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
#print proxy.system.listMethods()
print "3 is even: %s" % str(proxy.xmlsrv_is_even(3))
print "100 is even: %s" % str(proxy.xmlsrv_is_even(100))

print "CPU Clock: %s" % str(proxy.xmlsrv_get_mhz())

except xmlrpclib.Fault, err:
print "A fault occurred"
print "Fault code: %d" % err.faultCode
print "Fault string: %s" % err.faultString

#proxy.xmlsrv_exit()

Example how to access raw socket in Python:

#!/usr/bin/python

from socket import *
from struct import *
from time import *
import sys
import IN
import signal

src = '192.168.2.2'
dst = '224.0.0.1'
dev = "eth1.100" + "\0"

if len(sys.argv) > 1:
dev = sys.argv[1]
print "device = %s" % dev

src = gethostbyname(gethostname())

def ichecksum(data, sum=0):
""" Compute the Internet Checksum of the supplied data.  The checksum is
initialized to zero.  Place the return value in the checksum field of a
packet.  When the packet is received, check the checksum, by passing
in the checksum field of the packet and the data.  If the result is zero,
then the checksum has not detected an error.
"""
# make 16 bit words out of every two adjacent 8 bit words in the packet
for i in range(0,len(data),2):
if i + 1 >= len(data):
sum += ord(data[i]) & 0xFF
else:
w = ((ord(data[i]) <> 16) > 0)
sum = (sum & 0xFFFF) + (sum >> 16)

# one's complement the result
sum = ~sum

return sum & 0xFFFF

def dump( data ):
i = 0
for x in data:
if i == 4:
print ''
i = 0
i += 1
sys.stdout.write( ' %0.2x' % ord(x) )
print ''

def create_ip_hdr(id, type):
ip_ihl = 5
ip_ver = 4
ip_tos = 0
ip_tot_len = 0  # kernel will fill the correct total length
ip_frag_off = 0
ip_ttl = 255
ip_proto = type #IPPROTO_IGMP
ip_check = 0    # kernel will fill the correct checksum
isrc = inet_aton( src )
idst = inet_aton( dst )
ip_ihl_ver = (ip_ver << 4) + ip_ihl
router_alert = int( '1001010000000100', 2 ) << 16

# the ! in the pack format string means network order
ip_hdr = pack('!BBHHHBBH4s4sI',
ip_ihl_ver, ip_tos, ip_tot_len, id, ip_frag_off, ip_ttl, ip_proto,
ip_check,
isrc, idst,

crc = pack( '!H', ichecksum( ip_hdr ) )
ip_hdr = ip_hdr[:10] + crc + ip_hdr[12:]
return ip_hdr

# type (octet), max resp time (octet), checksum (octet), group (4-octets)
IGMP_QUERY = 0x11
IGMP_REPORT = 0x16
IGMP_LEAVE = 0x17
igmp_type = IGMP_QUERY
IGMP_RESP_TIME = 120

igmp = pack( '!BBH4s', type, IGMP_RESP_TIME, 0, inet_aton(group_addr))
crc = pack( '!H', ichecksum( igmp ) )
igmp = igmp[0:2] + crc + igmp[4:]
packet = create_ip_hdr(id, IPPROTO_IGMP) + igmp
print 'packet:'
dump( packet )
return packet

igmp = pack( '!BBH4s', type, IGMP_RESP_TIME, 0, inet_aton(group_addr))
crc = pack( '!H', ichecksum( igmp ) )
igmp = igmp[0:2] + crc + igmp[4:]
packet = create_ip_hdr(id, IPPROTO_UDP) + igmp
print 'packet:'
dump( packet )
return packet

group = '224.0.0.1'
id = 1

s = socket( AF_INET, SOCK_RAW, IPPROTO_RAW )
s.setsockopt( IPPROTO_IP, IP_HDRINCL, 1 )
s.setsockopt( IPPROTO_IP, IP_MULTICAST_TTL, 2)
s.setsockopt( SOL_SOCKET, IN.SO_BINDTODEVICE, dev)

stop = False

def signal_handler(signal, frame):
global stop
print 'You pressed Ctrl+C!'
stop = True
#th1.join()
#th2.join()
#sys.exit(0)

def run(self):
global stop,id
while (not stop):
socksema.acquire()
print "Sending IGMP query"
igmp_q = create_igmp_packet(id, IGMP_QUERY, group)
print s.sendto( igmp_q, (dst, 0) )
socksema.release()
dump( igmp_q)
id += 1
sleep(1)

def run(self):
global stop,id
while (not stop):
socksema.acquire()
print "Sending IGMP report"
igmp_r = create_igmp_packet(id, IGMP_REPORT, group)
print s.sendto( igmp_r, (dst, 0) )
id += 1
socksema.release()
sleep(1)

i = 0

th1.start()
th2.start()

signal.signal(signal.SIGINT, signal_handler)
print 'Press Ctrl+C to quit'
#signal.pause()

while(not stop):
if (i % 5 == 0):
print "Sending NON-IGMP (%d)" % i
false_igmp = create_non_igmp_packet(id, IGMP_QUERY, group)
print s.sendto( false_igmp, (dst, 0) )
#stop = True
id += 1
sleep( 1 )
i += 1

th1.join()
th2.join()

s.close()

## Sunday, July 7, 2013

### Create Delay using Number of Cycles in PIC MCU

Most of the delay code available on the Internet for PIC is based on real time delay.  The problem with this approach is that it's hardcoded for certain clock frequency only.  When we use the code for different frequency clock, we have to change the code, sometimes drastically.

Another approach is just to make a routine to waste number of instruction cycles, regardless of the clock frequency.  The caller then later calculate how many cycles it needs to waste in order to get the wanted delay.  It's more maintainable this way than the former.  All PIC MCUs have each instruction executed in 4 clock frequency, or F_cy = F_clock/4, hence T_cy = 1/F_cy = 4/F_clock.

Here is the example of the code for PIC16F877A to waste 10 T_cy cycles.  If F_clock is 16 MHz, F_Cy = 4MHz and T_Cy = 0.25 uSec.  So 10*T_cy = 2.5 uSec delay.
I don't see any reason it won't be compiled and working on other pic16-based MCUs.  I compiled the code with gpasm and header file from sdcc.

title "Delay 10 Tcy"

include <p16f_common.inc>

list n=0

global    _delay10tcy
extern   _d1

; -----------------------------------------------------------------------
; Variables declaration
;DLY_VAR UDATA_SHR  0x190
;WREG         res 1
WREG        equ     _d1

code_delay10tcy code

_delay10tcy:
; polynomial for 10tcy delay is f(x) = 10 + 10 * (x-1)

; caller takes 2 TCy, return takes 2 Tcy, so we need 6 more Tcy here
banksel   WREG            ; 2 Tcy
decf      WREG,f          ; (x-1), 1 TCy.  TCy so far = 4 + 2 + 1 = 7

movfw     WREG            ; 1, TCy so far = 8
bz        @delay10_end    ; 2 Tcy if x=0, otherwise 1, TCy so far = 9 (if x>0)
nop                       ; 1 TCy, TCy so far = 10

@delay10_loop:                  ; (x-1) * 10
goto       \$+1            ; 2 TCy, TCy so far = 2
goto       \$+1            ; 2 TCy, TCy so far = 4
goto       \$+1            ; 2 TCy, TCy so far = 6

nop                       ; TCy so far 7
decfsz    WREG, f         ; TCy so far 8 (if x>0), else 9
goto       @delay10_loop  ; TCy so far 10
nop

@delay10_end:

return                    ; 2

end

Save the code to a file name delay10tcy.S.

To compile it on Linux:

gpasm -c -M -m --mpasm-compatible -e ON -DSDCC -Dpic16f877a -p16f877a -I/usr/local/share/sdcc/include/pic14  delay10tcy.S

The variable "_d1" above has been defined elsewhere as 8-bit user data (so it's shareable among other delayxtcl routines), but if we want to make it local just declare is such as:

DELAY_VAR  udata_shr 0x190
d1  res 1

and remove underscore in all references to d1.

## Wednesday, June 19, 2013

### Parent-Child Relationship in OOP C++

The C++ source code below:

```#include <cstdio>
#include <iostream>

using namespace std;

class CParent {
public:
CParent() {
ref++;
cout <<  "class CParent: constructor ref=" << ref << endl;
Function();
};
virtual ~CParent() {
ref--;
cout << "class CParent: destructor ref=" << ref << endl;
}
virtual int Function() {
cout << "\tA::Function()" << endl;
return ref;
}
static unsigned int ref;
};

class CChild : public CParent {
public:
CChild() {
ref++;
cout << "\tclass CChild: constructor ref=" << ref << endl;
m_a = new CParent();
};
virtual ~CChild() {
ref--;
cout << "\tclass CChild: destructor ref=" << ref << endl;
delete m_a;
}

static unsigned int ref;
private:
CParent *m_a;
};

unsigned int CParent::ref = 0;
unsigned int CChild::ref = 0;

int main()
{
int i;
int n = 2;

CChild *c = new CChild[n];
for(i=0; i(&c[i]);
printf("p[%d].Function()=%d\n", i, p->Function());
}
cout << "CChild::Ref=" << CChild::ref << endl;
delete [] c;
}

```

### SPI on Arduino Nano v3.0

IC Package: 32 pin MLF

Arduino
Pin #
ATMEL 328P
(MLF) pin#
ATMEL 328P
(PDIP) pin#
Label Function
D10 14 16 PB2 SS*
D11 15 17 PB3 MOSI
D12 16 18 PB4 MISO
D13 17 19 PB5 SCK

The problem is, according to Arduino Nano schematic, pin 13 is connected to LED through 330 ohm resistor in series.
To be able to use SPI correctly, we need to disconnect the LED.

## Tuesday, June 18, 2013

### Arduino Nano v3.0 with avr-dude

My order of two Arduino Nano-compatible v3.0 from eBay (shipped from China) just arrived. Also bought the USBASP USBISP AVR Programmer from eBay (about \$3.0, from China too, see the picture on the left).

The good thing about this USBISP AVR programmer, besides the unbelievable price, I was told that it is  also compatible with avrdude, even Atmel AVR Studio (never tried it, thought)

But when I tried to program it with avr-dude, it always failed with various errors, such as:

avrdude: ser_recv(): programmer is not responding

avrdude: stk500v2_getsync(): timeout communicating with programmer
or:
...
Using Port                    : /dev/ttyUSB2
Using Programmer              : avrisp
Overriding Baud Rate          : 57600
avrdude: ser_recv(): programmer is not responding
avrdude: stk500_recv(): programmer is not responding
...

I tried "-c arduino" without setting the baud-rate, I also tried different programmer type (stk500v2, etc.), nothing worked.  Turned out, the parameters combination I used was wrong.
In this case, the programmer should be "arduino" but the baudrate must be set to something (in this case, 57600).

The following is the correct one:

bash-4.2\$ avrdude -c arduino -b 57600 -P /dev/ttyUSB2 -p atmega328p -vv -U flash:w:blink.hex

avrdude: Version 5.11, compiled on Sep  9 2011 at 16:00:41
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/

System wide configuration file is "/usr/local/etc/avrdude.conf"
User configuration file is "/home/mlutfi/.avrduderc"

Using Port                    : /dev/ttyUSB2
Using Programmer              : arduino
Overriding Baud Rate          : 57600
AVR Part                      : ATMEGA328P
Chip Erase delay              : 9000 us
PAGEL                         : PD7
BS2                           : PC2
RESET disposition             : dedicated
RETRY pulse                   : SCK
serial program mode           : yes
parallel program mode         : yes
Timeout                       : 200
StabDelay                     : 100
CmdexeDelay                   : 25
SyncLoops                     : 32
ByteDelay                     : 0
PollIndex                     : 3
PollValue                     : 0x53
Memory Detail                 :

Block Poll               Page                       Polled
Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
eeprom        65     5     4    0 no       1024    4      0  3600  3600 0xff 0xff
flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

Programmer Type : Arduino
Description     : Arduino
Hardware Version: 2
Firmware Version: 1.16
Vtarget         : 0.0 V
Varef           : 0.0 V
Oscillator      : Off
SCK period      : 0.1 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f
avrdude: safemode: lfuse reads as 0
avrdude: safemode: hfuse reads as 0
avrdude: safemode: efuse reads as 0
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: input file blink.hex auto detected as Intel Hex
avrdude: writing flash (1468 bytes):

Writing | ################################################## | 100% 0.41s

avrdude: 1468 bytes of flash written
avrdude: verifying flash memory against blink.hex:
avrdude: input file blink.hex auto detected as Intel Hex
avrdude: input file blink.hex contains 1468 bytes

Reading | ################################################## | 100% 0.30s

avrdude: verifying ...
avrdude: 1468 bytes of flash verified

avrdude: safemode: lfuse reads as 0
avrdude: safemode: hfuse reads as 0
avrdude: safemode: efuse reads as 0
avrdude: safemode: Fuses OK

avrdude done.  Thank you.

## Monday, May 27, 2013

### MSP430 or PIC?

After sometime using LaunchPad, I was ready to buid my own board utilizing some msp430g2211 on breakout boards laying around on my workbench.  I was going to use the JTAG pins available to program them, but bumped with the overpriced USB-based JTAG programmers/debuggers available in the market.  Yes, I could use the LaunchPad to program these separate microcontrollers, but it's not a good and decent way.

I got a  msp430 BSL usb-to-serial programmer from eBay.  After reading the datasheet for msp430g2211, I realized these type of low-cost microcontrollers don't support BSL, either.  So the only way (other than wiring LauchPad to my protoboard) to in-circuit program the chips is to use a JTAG programmer.  That's a lame, as with PIC microcontrollers, I still could used my PicKit2 to program 44-pin 18Fxx chips.  Even AVR from Atmel could do the similar way using cheap programmer available on eBay or even BusPirate.

Well, sorry msp430, for now I am back to PIC as it has so many features I need (wide availability of PDIP footprints, wide I/O voltage (2 - 5 volt) and cheap programmer).  I am aware there are some open-source efforts to build this kind of programmer for msp430 (GoodFet is one of them, the pre-assembled board is sold at https://www.adafruit.com/products/1279#Technical%20Details)

## Sunday, April 21, 2013

### DIY Arduino Uno on Breadboard and programmed with BusPirate

This is based on the blog on Programming AVR with AVR-GCC and AVR Programming with BusPirate

Instead of pin 13 (PB5) for LED blinking test, I use pin 8 (PB0) because PB5 is shared with SCK which we're going to use for ICSP (connected to BusPirate's SCK)

To test whether avrdude and BusPirate can communicate as well as to see if the chip is readable (so the connections are correct):

bash-4.2\$ avrdude -c buspirate -P /dev/ttyUSB0 -p atmega328p -v

avrdude: Version 5.10, compiled on Mar  2 2011 at 21:55:09
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/

System wide configuration file is "/etc/avrdude/avrdude.conf"
User configuration file is "/home/mlutfi/.avrduderc"
User configuration file does not exist or is not a regular file, skipping

Using Port                    : /dev/ttyUSB0
Using Programmer              : buspirate
AVR Part                      : ATMEGA328P
Chip Erase delay              : 9000 us
PAGEL                         : PD7
BS2                           : PC2
RESET disposition             : dedicated
RETRY pulse                   : SCK
serial program mode           : yes
parallel program mode         : yes
Timeout                       : 200
StabDelay                     : 100
CmdexeDelay                   : 25
SyncLoops                     : 32
ByteDelay                     : 0
PollIndex                     : 3
PollValue                     : 0x53
Memory Detail                 :

Block Poll               Page                       Polled
Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
eeprom        65     5     4    0 no       1024    4      0  3600  3600 0xff 0xff
flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

Programmer Type : BusPirate
Description     : The Bus Pirate

Detecting BusPirate...
**
**  Bus Pirate v3a
**  Firmware v5.10 (r559)  Bootloader v4.4
avrdude: buspirate_readline(): DEVID:0x0447 REVID:0x3046 (24FJ64GA002 B8)
**  DEVID:0x0447 REVID:0x3046 (24FJ64GA002 B8)
**  http://dangerousprototypes.com
**
BusPirate: using BINARY mode
BusPirate binmode version: 1
BusPirate SPI version: 1
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e950f
avrdude: safemode: lfuse reads as 62
avrdude: safemode: hfuse reads as D9
avrdude: safemode: efuse reads as 7

avrdude: safemode: lfuse reads as 62
avrdude: safemode: hfuse reads as D9
avrdude: safemode: efuse reads as 7
avrdude: safemode: Fuses OK
BusPirate is back in the text mode

avrdude done.  Thank you.

bash-4.2\$

Now we can deploy this command into Makefile I have posted before.
For example, the following lines can be inserted at the very bottom of Makefie:

install: \$(PRG).hex
avrdude -c buspirate -P /dev/ttyUSB0 -p \$(MCU_TARGET) -v -U flash:w:\$(PRG).hex

To compile:

bash-4.2\$ make
|| { echo empty blink_eeprom.hex not generated; exit 0; }
avr-objcopy: --change-section-lma .eeprom=0x0000000000000000 never used
|| { echo empty blink_eeprom.bin not generated; exit 0; }
avr-objcopy: --change-section-lma .eeprom=0x0000000000000000 never used
|| { echo empty blink_eeprom.srec not generated; exit 0; }
avr-objcopy: --change-section-lma .eeprom=0x0000000000000000 never used
bash-4.2\$

To install/program it to the target (ATMega328P on the breadboard):

bash-4.2\$ make install
avr-c++ -c -g -Wall -O2 -mmcu=atmega328p -D__AVR_ATmega328P__ -DF_CPU=16000000UL -I /home/mlutfi/src/arduino/include -I /home/mlutfi/src/arduino/include/arduino -I /home/mlutfi/src/arduino/include/variants -I /home/mlutfi/src/arduino/include/variants/standard -I /opt/arduino-1.0.4/libraries/LiquidCrystal  blink.cpp -o blink.o
***********************************************************
***********************************************************
avr-c++ -g -Wall -O2 -mmcu=atmega328p -D__AVR_ATmega328P__ -DF_CPU=16000000UL -I /home/mlutfi/src/arduino/include -I /home/mlutfi/src/arduino/include/arduino -I /home/mlutfi/src/arduino/include/variants -I /home/mlutfi/src/arduino/include/variants/standard -I /opt/arduino-1.0.4/libraries/LiquidCrystal  -Wl,-Map,blink.map -o blink.elf -L /home/mlutfi/src/arduino/include -lm -lc  blink.o /home/mlutfi/src/arduino/include/libatmega328p.a
avrdude -c buspirate -P /dev/ttyUSB0 -p atmega328p -v -U flash:w:blink.hex

avrdude: Version 5.11, compiled on Sep  9 2011 at 16:00:41
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/

System wide configuration file is "/usr/local/etc/avrdude.conf"
User configuration file is "/home/mlutfi/.avrduderc"
User configuration file does not exist or is not a regular file, skipping

Using Port                    : /dev/ttyUSB0
Using Programmer              : buspirate
AVR Part                      : ATMEGA328P
Chip Erase delay              : 9000 us
PAGEL                         : PD7
BS2                           : PC2
RESET disposition             : dedicated
RETRY pulse                   : SCK
serial program mode           : yes
parallel program mode         : yes
Timeout                       : 200
StabDelay                     : 100
CmdexeDelay                   : 25
SyncLoops                     : 32
ByteDelay                     : 0
PollIndex                     : 3
PollValue                     : 0x53
Memory Detail                 :

Block Poll               Page                       Polled
Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
eeprom        65     5     4    0 no       1024    4      0  3600  3600 0xff 0xff
flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

Programmer Type : BusPirate
Description     : The Bus Pirate

Detecting BusPirate...
**
**  Bus Pirate v3a
**  Firmware v5.10 (r559)  Bootloader v4.4
avrdude: buspirate_readline(): DEVID:0x0447 REVID:0x3046 (24FJ64GA002 B8)
**  DEVID:0x0447 REVID:0x3046 (24FJ64GA002 B8)
**  http://dangerousprototypes.com
**
BusPirate: using BINARY mode
BusPirate binmode version: 1
BusPirate SPI version: 1
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e950f
avrdude: safemode: lfuse reads as 62
avrdude: safemode: hfuse reads as D9
avrdude: safemode: efuse reads as 7
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: input file blink.hex auto detected as Intel Hex
avrdude: writing flash (1444 bytes):

Writing | ################################################## | 100% 4.46s

avrdude: 1444 bytes of flash written
avrdude: verifying flash memory against blink.hex:
avrdude: input file blink.hex auto detected as Intel Hex
avrdude: input file blink.hex contains 1444 bytes

Reading | ################################################## | 100% 4.37s

avrdude: verifying ...
avrdude: 1444 bytes of flash verified

avrdude: safemode: lfuse reads as 62
avrdude: safemode: hfuse reads as D9
avrdude: safemode: efuse reads as 7
avrdude: safemode: Fuses OK
BusPirate is back in the text mode

avrdude done.  Thank you.

bash-4.2\$

The code "blink.cpp" itself as below:

/*
Turns on an LED on for one second, then off for one second, repeatedly.

This example code is in the public domain.

According to UNO schematic:
pin 13 = PB5 (19)
pin 12 = PB4 (18)
pin 11 = PB3 (17)
pin 10 = PB2 (16)
pin 9 = PB1 (15)
pin 8 = PB0 (14)
pin 7 = PD7 (13)
pin 6 = PD6 (12)
pin 5 = PD5 (11)
pin 4 = PD4 (6)
pin 3 = PD3 (5)
pin 2 = PD2 (4)
pin 1 = PD1 (3)
pin 0 = PD0 (2)
*/
#include <arduino/Arduino.h>

#define LED     8

void setup() {
// initialize the digital pin as an output.
// Pin 13 (has an LED connected on most Arduino boards:
// but myproto on breadboand uses PB0 (14) = pin 8 as LED output
pinMode(LED, OUTPUT);
}

void loop() {
digitalWrite(LED, HIGH);   // set the LED on
delay(25);              // wait for a second
digitalWrite(LED, LOW);    // set the LED off
delay(25);              // wait for a second
}