Constructing an External Camera Using T-Engine

- An Application Using an AR Camera and a Wireless LAN -


Introduction

With T-Engine, by combining abundant hardware and middleware and loading applications on top, it is possible to easily construct precise solutions conforming to respective applications. In this paper, as one example of this, we will take up a simple sample in which we transmit via a LAN motion picture taken with a camera, and display those motion pictures on a handheld receiver terminal.

Device Configuration

The fine details, such as the camera, LCD resolution, and communication method, will change depending the purpose, but, here, paralleling the selection and development of such hardware, we will configure a device as a prototype for the development of software [Fig. 1].

Figure 1. Device configuration

First is the camera that takes the motion pictures; here, we will use the AR (Artificial Retina) camera (160 x 144 pixels; 65,536 colors) that is attached to the µT-Engine/M32104 Development Kit. In addition, for the LAN board also, we will likewise use as is the one attached to the µT-Engine/M32104 Development Kit.

On the other hand, let's use a standard T-Engine for the handheld receiver terminal. Here, we will use T-Engine/SH7727, and for image display also, we will use the LCD board (240 x 320 pixels) that is attached to T-Engine/SH7727.

For the wireless LAN, we will make do with one that is being marketed to the general public. After preparing the access point, hub, PC Card type wireless LAN card, we connect to the T-Engine PC Card slot. Here, for the wireless LAN card, we will use the IEEE 802.11b BUFFALO WLI-PCM-L11.

Software Configuration

Continuing on, let's select the middleware for running the above-mentioned hardware [Fig. 2].

Figure 2. Software configuration

First is the camera side; for the AR camera device driver, we will use the standard one that is provided in the user support pages of the µT-Engine/M32104 Development Kit. Also, as for the µT-Engine/M32104 LAN driver and TCP/IP protocol stack, we have used "KASAGO for µT-Engine/M32104" here.

Next is the receiver terminal side; a wireless LAN-compatible LAN driver and TCP/IP protocol stack, and, also, display middleware for displaying on the LCD screen are needed. Here, we use "PMC T-Shell" middleware set, which includes all of these.

After doing things in this manner, the hardware and middleware preparations are in order, and thus afterward is just the loading of the applications on top of this. Furthermore, we will make it our business to store these middleware and applications on the Flash ROMs of T-Engine and µT-Engine.

Applications

We decide to carry out communications with the client-server method by making the camera side the TCP server, and the receiver terminal side the TCP client. We have decided in the manner of Fig 3 for the protocol. First we send a photo shot request and take a picture, and following that, we split up and transmit the photos that were taken on the basis of transmission requests.

Figure 3. Communication protocol

In List 1, we show an outline of the communications part on the receiver terminal (client) side, and, in List 2, an outline of the communications part on the camera (server) side*. Because we have employed standard socket APIs for both T-Shell and KASAGO, we have realized communications with socket programming. Please pay attention to the point that prefixes such as so_ and ka_ have been attached to the API names order to prevent the collision of API names. Also, because the endian is different at the client side and the server side (T-Engine/SH7727 is little endian, and µT-Engine/M32104 is big endian), it is necessary to carry out endian conversion with hton1(), etc.

Makefile
#
#  TRONWARE VOL.85 Recorded
#  Wireless LAN Solution Sample Program
#
#  Image Receiver Client Sample (Standard T-Engine; common to each model)
#
#  Copyright (C) 2004 Personal Media Corporation

DEPS = Dependencies
DEPENDENCIES_OUTPUT := $(DEPS)

include $(BD)/bappl/etc/makerules

TARGET = client

S = ../src
VPATH = $S

SRC = client.C

OBJ = $(addsuffix .o, $(basename $(SRC)))

SRC.C	= $(filter %.C, $(SRC))

CFLAGS += $(CFLAGS_WARNING)

# ----------------------------------------------------------------------------

.PHONY: all install clean

ALL = $(TARGET)

all: $(ALL)

$(TARGET): $(OBJ)
	$(LINK.o) $(LDOBJS) $^ $(LOADLIBES) $(LDLIBS) $(OUTPUT_OPTION)
	$(STRIP) $@

clean:
	$(RM) $(OBJ) $(SRC.C:%.C=%.c) $(ALL) $(DEPS)

install: $(addprefix $(EXE_INSTALLDIR)/, $(ALL))

$(TARGET:%=$(EXE_INSTALLDIR)/%): $(EXE_INSTALLDIR)/%: %
	$(EXE_INSTALL_STRIP)


# Source dependencies
ifdef DEPENDENCIES_OUTPUT
  $(DEPS): ; touch $(DEPS)
else
  $(DEPS): $(SRC) ; $(MAKEDEPS) $@ $?
endif
include $(DEPS)

$(SRC.C:%.C=%.c):
client.C
/*
  TRONWARE VOL.85 Recorded
  Wireless LAN Solution Sample Program

  Image Receiver Client Sample (Standard T-Engine; common to each model)

  Copyright (C) 2004 Personal Media Corporation

  Start up method

  From on top of the CLI

  Start up by means of 

  client server IP address server port number

  The protocol between the server and the client is as follows:

  - Taking of the image
    Client to server: [0] (1 word)
    Server to client: [0] (1 word)

  - Transmission of the image
    Client to server: [1][line number][number of lines] (3 words)
    Server to client: [image] (160 * number lines half word)
*/

#include <basic.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tstring.h>
#include <btron/bsocket.h>
#include <btron/dp.h>

#define PX 160  /* Number of pixels in one line of the AR camera image */
#define PY 144  /* Number of lines of the AR camera */

/*
  Transmission
 */
int my_send( int fd, void *buf, int n )
{
  int r, k; char *p;
  for(p = buf, r = n; r > 0; r -= k, p += k) {
    k = so_send( fd, (void*)p, r, 0 );
    if (k == 0) break;
    else if (k < 0) return -1;
  }
  return (n - r);
}

/*
  Reception
 */
int my_recv( int fd, void *buf, int n )
{
  int r, k; char *p;
  for(p = buf, r = n; r > 0; r -= k, p += k) {
    k = so_recv( fd, (void*)p, r, 0 );
    if (k == 0) break;
    else if (k < 0) return -1;
  }
  return (n - r);
}

/*
  Receiving the image from the server
 */
void get_image( char *server_ip, int server_port, short *img )
{
  int fd, n, y, buf[3];
  struct sockaddr_in saddr;
  const int M = 4; /* Transmit every 4 lines */
  /* Acquisition of the socket*/
  fd = so_socket( AF_INET, SOCK_STREAM, 0 );
  if (fd < 0) {
    puts( "socket failed" );
    return;
  }

  /* Connect to the server */
  memset( &saddr, 0, sizeof(saddr) );
  saddr.sin_family = AF_INET;
  saddr.sin_port = htons( server_port );          /* Port number */
  saddr.sin_addr.s_addr = inet_addr( server_ip ); /* IP address */
  n = so_connect( fd, (struct sockaddr *)&saddr, sizeof(saddr) );
  if (n < 0) {
    puts( "connect failed" );
    goto e;
  }

  /* Taking of the image */
  buf[0] = htonl( 0 );                            /* Photo shot request */
  n = my_send( fd, (void*)buf, sizeof(int) );
  if (n != sizeof(int)) goto e;
  n = my_recv( fd, (void*)buf, sizeof(int) );
  if (n != sizeof(int)) goto e;

  /* Acquisition of the image */
  for(y = 0; y < PY; y += M) {
    buf[0] = htonl( 1 );                          /* Transmission request */
    buf[1] = htonl( y );                          /* Line number */ 
    buf[2] = htonl( M );                          /* Number of lines */ 
    n = my_send( fd, (void*)buf, 3 * sizeof(int) );
    if (n != 3 * sizeof(int)) goto e;

    n = my_recv( fd, (void*)&img[y * PX], PX * sizeof(short) * M );
    if (n != PX * sizeof(short) * M ) goto e;
  }

  /* Endian conversion of the acquired image */
  for(n = 0; n < (PX * PY); n++) img[n] = ntohs( img[n] );

  /* Close the socket */
e:
  so_close( fd );
}

/*
 Main
 */
int main( int ac, TC *av[] )
{
  char server_ip[32]; int server_port;
  GID gid; BMP bmp;
  static TC scr[] = {L"‚r‚b‚q‚d‚d‚m"};
  static CSPEC cspec16 = { DA_COLOR_RGB, {0x0b05, 0x0506, 0x0005, 0}, NULL };
  static short img[PX * PY];

  /* Processing of the command line argument */
  if (ac == 3 && tcstoeucs( server_ip, av[1] ) > 0
      && ( server_port = tc_atoi( av[2] ) ) > 0 ) {
  } else {
    puts( "Usage: client  server-IP-address  server-port-No" ); 
    return 0;
  }

  /* Open the drawing environment */
  gid = b_gopn_dev( scr, NULL );
  if (gid < 0) {
    puts( "T-Shell dp is not ready" );
    return 0;
  }

  /* Setting of the bitmap */
  bmp.planes = 1;
  bmp.bounds.c.left = bmp.bounds.c.top = 0;
  bmp.bounds.c.right = PX;
  bmp.bounds.c.bottom = PY;
  bmp.pixbits = (sizeof(short) << 3) | (sizeof(short) << (8 + 3));
  bmp.rowbytes = PX * sizeof(short);
  bmp.baseaddr[0] = (void*)img;
  b_gset_bcs( gid, &cspec16 );

  /* Reception and display of the image */
  for(;;) {
    get_image( server_ip, server_port, img );
    b_grst_bmp( gid, &(bmp.bounds), &bmp, &(bmp.bounds), NULL,
		G_STORE | G_CVFORM | G_CVCOLOR );
  }

  b_gcls_env( gid );
  return 0;
}

Makefile
#
#  TRONWARE VOL.85 Recorded
#  Wireless LAN Solution Sample Program
#
#  AR Camera Server Sample (for use with T-Engine/M32104)
#
#  Copyright (C) 2004 Personal Media Corporation

# Source dependencies file (automatically generated)
DEPS = Dependencies
DEPENDENCIES_OUTPUT := $(DEPS)

# Standard rules
include $(BD)/kappl/etc/makerules

# ----------------------------------------------------------------------------
# Creation target
TARGET = server

# Source file search path
S = ../src
VPATH = $S

# Source file
SRC = server.c

ifeq ($(MACHINE), m32104)
  # Load address
  START_ADR = -Wl,-Ttext,0x00100000,-Tdata,0x04900000
  # KASAGO endian specification
  CFLAGS += -DTM_BIG_ENDIAN
  # Do not optimize
  CFLAGS += -O0
endif

OBJ = $(addsuffix .o, $(basename $(SRC)))

# KASAGO extensions library
LOADLIBES += -lsvc_ka 

# ----------------------------------------------------------------------------

.PHONY: all install clean

ifeq ($(MACHINE), m32104)
  ALL = $(TARGET) $(TARGET).map $(TARGET).mot
  %.map: %.abs
else
  ALL = $(TARGET) $(TARGET).map 
  %.map: %
endif

all: $(ALL)

$(TARGET): $(OBJ)
	$(LINK.o) $(LDOBJS) $^ $(LOADLIBES) $(LDLIBS) $(OUTPUT_OPTION)

$(TARGET).mot: $(TARGET)
	$(OBJCOPY) $(OUTPUT_SREC) $< $@

clean:
	$(RM) $(OBJ) $(ALL) $(DEPS)

install: $(addprefix $(EXE_INSTALLDIR)/, $(ALL))

$(TARGET:%=$(EXE_INSTALLDIR)/%): $(EXE_INSTALLDIR)/%: %
	$(EXE_INSTALL_STRIP)

# Source dependencies
ifdef DEPENDENCIES_OUTPUT
  $(DEPS): ; touch $(DEPS)
else
  $(DEPS): $(SRC) ; $(MAKEDEPS) $@ $?
endif
include $(DEPS)
server.c
/*
  TRONWARE VOL.85 Recorded
  Wireless LAN Solution Sample Program

  AR Camera Server Sample (for use with T-Engine/M32104)

  Copyright (C) 2004 Personal Media Corporation

  Startup Method

  By means of IMS

  lodspg @00100000  IP address  subnet mask  port number

  start up from on top of IMS. 

  Load beforehand the following middleware:
  - AR camera driver
  - KASAGO for T-Engine/M32104 (TCP/IP and network driver)

  The protocol between the server and the client is as follows:

  - Taking of the image
    Client to server: [0] (1 word)
    Server to client: [0] (1 word)

  - Transmission of the image
    Client to server: [1][line number][number of lines] (3 words)
    Server to client: [image] (160 * number of lines half word)
 */

#include <basic.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tk/tkernel.h>
#include <device/ar.h>
#include <btron/kasago.h>

/* AR camera settings */
#define PX           160  /* Number of pixels in 1 line of the AR camera image */
#define PY           144  /* Number of lines of the AR camera */
#define COLOR          6  /* Hues of the AR camera */
#define BRIGHTNESS    15  /* Brightness of the AR camera */
int dd;                   /* Opened device disk rebooter */
short *ar_img;            /* Beginning address of the image taken from AR camera */

/*
  Acquiring the image from the AR camera
 */
void ar_take( void )
{
  int asiz, n;

  /* Image acquisition of the AR camera */
  tk_srea_dev( dd, 0, (void*)&ar_img, sizeof(void*), &asiz );

  /* Endian conversion of the acquired image */
  for(n = 0; n < (PX * PY); n++) ar_img[n] = ka_htons( ar_img[n] );
}

/*
  Setting the hues and brightness in the AR camera
 */
static void set_color( int x, int y )
{
  int asiz, k;

  /* Setting of the hues */
  tk_swri_dev( dd, AR_COLOR, &x, sizeof(int), &asiz );

  /* Setting of the brightness */
  tk_swri_dev( dd, AR_BRIGHTNESS, &y, sizeof(int), &asiz );

  /* After setting the hues and brightness, the image is unstable, 
   when a photo is not taken for how many times? */
  for( k = 0; k < 4; k++) ar_take();
}

/*
  Setting the frequency of the power supply to the AR camera
 */
void set_hz( int x )
{
  int asiz;
  tk_swri_dev( dd, AR_HZ, &x, sizeof(int), &asiz );
}

/*
  Transmission
 */
int my_send( int fd, void *buf, int n )
{
  int r, k; char *p;
  for(p = buf, r = n; r > 0; r -= k, p += k) {
    k = ka_send( fd, (void*)p, r, 0 );
    if (k == 0) break;
    else if (k < 0) return -1;
  }
  return (n - r);
}

/*
  Reception
 */
int my_recv( int fd, void *buf, int n )
{
  int r, k; char *p;

  for(p = buf, r = n; r > 0; r -= k, p += k) {
    k = ka_recv( fd, (void*)p, r, 0 );
    if (k == 0) break;
    else if (k < 0) return -1;
  }
  return (n - r);
}

/*
  Operations of the server for 1 session 
 */
void session( int cfd )
{
  int er, n, buf[3]; void *adr;

  for(;;) {
    /* Receiving a request from the client */
    n = my_recv( cfd, (void*)buf, sizeof(int) );
    if (n != sizeof(int)) return;

    /* Processing of the request */
    switch (ka_ntohl( buf[0] )) {

    case 0 : /* Taking of the image */
      ar_take();
      adr = buf;
      n   = sizeof(int);
      break;

    case 1 : /* Transmission of the image */
      n = my_recv( cfd, (void*)&buf[1], 2 * sizeof(int) );
      if (n != 2 * sizeof(int)) return;

      adr = &(ar_img[ka_ntohl( buf[1] ) * PX]);
      n   = (PX * sizeof(short)) * ka_ntohl( buf[2] );
      break;

    default :
      return;
    }

    /* Sending a reply to the client */
    er = my_send( cfd, adr, n );
    if (er != n) return;
  }
}

/*
  Server main body
 */
void serv( char *ip, char *subnetmask, int port )
{
  int fd, er, cfd, clen;
  ttUserInterface ih;
  struct sockaddr_in saddr, caddr;

  /* Display of the startup message */
  puts( "Server running" );

  /* Opening of the AR device */
  dd = tk_opn_dev( "ara", TD_UPDATE );
  if (dd < 0) {
    puts( "AR driver not ready" );
    return;
  }
  set_hz( AR_50HZ );
  set_color( COLOR, BRIGHTNESS );

  /* Network settings */
  memset( &saddr, 0, sizeof(saddr) );
  saddr.sin_family      = AF_INET;
  saddr.sin_port        = ka_htons( port );   /* Port number */
  saddr.sin_addr.s_addr = ka_inet_addr( ip ); /* IP address */

  ih = ka_tfAddInterface( "Neta" );
  er = ka_tfOpenInterface( ih, saddr.sin_addr.s_addr,
			   ka_inet_addr( subnetmask ), 0, 1 );
  if (er < 0) {
    puts( "KASAGO not ready" );
    return;
  }

  fd = ka_socket( AF_INET, SOCK_STREAM, 0 ); /* Acquisition of the socket */
  if (fd < 0) {
    puts( "socket failed" );
    return;
  }

  er = ka_bind( fd, (struct sockaddr *)&saddr, sizeof(saddr) );
  if (er < 0) {
    puts( "bind failed" );
    return;
  }
  
  er = ka_listen( fd, 5 );
  if (er < 0) {
    puts( "listen failed" );
    return;
  }
  
  /* Main loop of the server */
  for(;;) {
    /* Accept request from the client */
    clen = sizeof(caddr);
    cfd = ka_accept( fd, (struct sockaddr *)&caddr, &clen );
    if (cfd < 0) continue;
    puts( inet_ntoa( caddr.sin_addr ) );

    /* 1 session operation */
    session( cfd );

    /* Close */
    ka_tfClose( cfd );
    puts( "closed" );
  }
  /* Do not terminate the server */
}

/*
 Main
 */
int main( int ac, char **av )
{
  if ( ac == 4 ) {
    serv( av[1], av[2], atoi(av[3]) ); /* Server main body */
  } else {
    puts( "Usage: lodspg @00100000 IP-address subnet-mask port-No" );
  }
  return -1;
}

Outside of this, we carry out the taking of photos with the AR camera on the server side by writing into the device driver using tk_swri_dev() of T-Kernel/SM. Also, on the client side, we display the images on the LCD screen using the b_grst_bmp() display primitive of T-Shell (please see the attached CD-ROM for the complete list).

Conclusion

In this paper, we have taken up a sample of a wireless LAN solution in which we have combined hardware and middleware on top of T-Engine. In this manner, T-Engine is the most suitable open platform in the development of embedded systems. Please, by all means, utilize T-Engine for cost reduction and development period reduction.

____________________

* The full lists and documentation given in the CD-ROM attached to Vol. 85 of TRONWARE are presented in this translation. These are: a ReadMe file (given below), a client Makefile file, client.C program file, a server makefile file, and a server.c program file. The original article has two short lists: List 1 An Outline of the Communication Part on the Handheld Receiver Terminal (Client) Side, and List 2 An Outline of the Communication Part on the Camera (Server) Side.

ReadMe
===============================================
           TRONWARE VOL.85 Recorded
     Wireless LAN Solution Sample Program
 Copyright (C) 2004 Personal Media Corporation
===============================================

•This software is a sample program created for explaining
 T-Engine application development. It is not something
 that was created with the objective of actual operation. 
 We do not guarantee the operation of this software.
 Personal Media Corporation will not bear any responsibility 
 whatsoever for direct/indirect hindrance or loss that occurs 
 as a result utilization, and also in other circumstances of
 whatever matter.
 We kindly request for you to please use this on the basis of
 your own responsibility.

•One Example of Device Configuration

 [µT-Engine/M32104 (AR Camera, LAN board)] 
                ||
               [hub] 
                ||
     [wireless LAN access point]
                 :
                 :
                 :
      (electromagnetic waves)
                 :
                 :
                 :
   [T-Engine/SH7727 (wireless LAN card)]

•Software Configuration

  (1) AR camera server sample       (for use with T-Engine/M32104)
  (2) Image receiver client sample  (Standard T-Engine; common to each model)

  On the server side, we use the following middleware:
  - AR camera driver           (takes images)
  - KASAGO for T-Engine/M32104 (TCP/IP, LAN driver)

  On the client side, we use the following middleware:
  - T-Shell   (TCP/IP, Wireless LAN Driver, image display processing)

•AR Camera Server Sample (for T-Engine/M32104)

  By means of

    cd server
    mkdir m32104
    cd m32104
    ln -s ../src/Makefile
    gmake

  create the S format file server.mot, and write it into the
  T-Engine/M32104 Flash ROM. 

  Defaults are placed in the following addresses. 
  Modify Makefile depending on your needs.

  program area 0x00100000 --
  data area    0x04900000 --

  We carry out startup with the following command from on top of IMS:  

    lodspg @00100000  IP address  subnet mask  port number

  Furthermore, because the following middleware is needed,
  load it beforehand:

  - AR camera driver
  - KASAGO for T-Engine/M32104 (TCP/IP plus network driver)

•Image Receiver Client Sample   (Standard T-Engine; common to each model)

  By means of

    cd client
    mkdir sh7727
    cd sh7727
    ln -s ../src/Makefile
    gmake

  create the execution file client, and transmit it to T-Engine
  (this is in the case it is T-Engine/SH7727).
  
  We carry out startup with the following command from on top of the CLI:

    client  server IP address  server port number

  Furthermore, because the following middleware is needed,
  load it beforehand:
  - T-Shell (TCP/IP, network driver,
             plus display primitives)


The above article on T-Engine appeared on pages 82-85 in Vol. 85 of TRONWARE . It was translated and loaded onto this Web page with the permission of Personal Media Corporation.

Copyright © 2004 Personal Media Corporation

Copyright © 2004 Sakamura Laboratory, University Museum, University of Tokyo