Here you can find a step-by-step tutorial about the Bascom-AVR code to drive
the AVR Ethernet I/O-board

 

This tutorial is based on my own hardware

Step 1. Get the hardware...

 

A bare board size 180 x 90 mm.

 

Step 2: Description

AVR Ethernet I/O board. Atmega128, 2 x MAX3232EEWE for 2 x RS232, 1 x VNC1L-1A with 2 x USB connector, black/white composite video with Atmega32, DS1307 Real Time Clock with battery backup, PS/2 keyboard connector, Wiz810MJ ethernet module and LCD 16 x 2 with backlight.

 

Step 3: Some images building the board

Main processor, Atmega128, 3,3 volt, on 8 Mhz.

Step 4: Fusebits Atmega128 and Atmega32

 

The fusebits of the Atmega32, the composite video controller.

The fusebits of the Atmega128, the main processor.

 

Step 5: Atmega32 as a composite video chip

 

On https://www.sbprojects.net/projects/apple1/a-one-terminal.htm you can find the a1term.zip made by a electronics-friend. 

You can find a copy of the video controller software, including the source file, on his Download page. The program was written using his SB-Assembler.

The entire program runs in one single interrupt routine. The main program is empty, well almost empty. Interrupts are spaced exactly 64µs apart for 50Hz systems, or 63.5µs for 60Hz systems. Each interrupt routine starts by generating an H-Sync pulse. A state machine then determines what is to be done during the rest of the line. Care should be taken that the interrupt routine ends before it's time to start a new one.

What needs to be done?

  • Generate a V-Sync pulse every field.
  • Generate an H-Sync pulse every line.
  • Generate pixels according to character bit map.
  • Display a flashing cursor.
  • Accept characters from the Apple 1 and put them on the screen.
  • Introduce an artificial character input delay every 16ms or so.
  • Echo incoming characters to the serial output.
  • Clear the screen if necessary.
  • Scroll the screen if necessary.

All these tasks are performed inside the interrupt routine. A simple state machine determines what task needs to be done during each particular video line. Some lines leave no time to do anything else but control the video/sync outputs. Other lines allow plenty of time ( >55µs ) to do other tasks. These other tasks are: accepting characters from the Apple 1, sending the characters to the serial output, scrolling the screen, flashing the cursor, etc, etc.

When the a1video.hex-file has been loaded in the Atmega32, here a demo how to use it with the Atmega128.
Bascom-AVR can be used to program the Atmega32. Start Bascom-AVR, push on the button program chip, but instead of program, press on manual program. Erase the Atmega32, set the fusebits, load the buffer with the a1video.hex file (standard there is asked for a BIN-file, you can however load a HEX-file) and flash it into the Atmega32.


'Video demo

$regfile "m128def.dat"
$crystal = 8000000
$baud = 115200 ' first hardware UART
$baud1 = 115200 ' second hardware UART

'Hardware

'LCD
'portb.7 LCD Db7
'portb.6 LCD Db6
'portb.5 LCD Db5
'portb.4 LCD Db4
'portb.3 LCD RS
'portb.2 LCD E

'portd.4 Beeper

'portd.5 Clock keyboard
'portd.6 Data keyboard

'porte.2 Wiz810MJ reset
'portb.4 Wiz810MJ /scs

'portb.1 SPI SCK
'portb.2 SPI MOSI
'portb.3 SPI MISO

'porte.4 video Puls_RDA
'porte.5 video Acknowledge
'portc.0 video ASCII bit 0
'portc.1 video ASCII bit 1
'portc.2 video ASCII bit 2
'portc.3 video ASCII bit 3
'portc.4 video ASCII bit 4
'portc.5 video ASCII bit 5
'portc.6 video ASCII bit 6


Declare Sub Beep
Declare Sub Video_pulse_rda
Declare Sub Video_cls

Dim X As Byte

Beeper Alias Portd.4
Pulse_rda Alias Porte.4
Da Alias Pine.5
Video_clear Alias Porte.3

Config Beeper = Output
Config Portc = Output
Config Video_clear = Output
Config Pulse_rda = Output
Config Da = Input

Config Lcdpin = Pin , Db4 = Porta.4 , Db5 = Porta.5 , Db6 = Porta.6 , Db7 = Porta.7 , E = Porta.2 , _
Rs = Porta.3
Config Lcd = 16 * 2

Cursor Off
Cls
Home

Lcd "Videotest"
Call Beep

Wait 3

'clear screen
Call Video_cls

Do
For X = 65 To 90
Portc = X
Call Video_pulse_rda
Next X
Wait 10
Call Video_cls
Wait 5
Loop
End

Sub Beep
Set Beeper
Waitms 1
Reset Beeper
End Sub

Sub Video_pulse_rda
Set Pulse_rda
Bitwait Pine.5 , Reset
Reset Pulse_rda
End Sub

Sub Video_cls
Reset Video_clear
Waitms 5
Set Video_clear
End Sub

Close up of the Atmega32 video controller, Wiz810MJ ethernet module and PS/2 keyboard connector.

During testing, small messages on the LCD are essential.

The result on a DVD-player with composite connection (yellow plug right)

 

Step 6: Driving LCD 16 x 2 and the serial ports

 

Settings for COM2, in the middle of JP4. 
When you put the jumpers on the right side you connect COM2 straight to the UART connection of the VNC1L-1A.
When you put the jumpers to the left the Atmega128 is connected to the VNC1L-1A.


' LCD, Beeper, Com1 en Com2

$regfile "m128def.dat"
$crystal = 8000000
$baud = 9600 ' first hardware UART
$baud1 = 9600 ' second hardware UART

'Hardware

'LCD
'portb.7 LCD Db7
'portb.6 LCD Db6
'portb.5 LCD Db5
'portb.4 LCD Db4
'portb.3 LCD RS
'portb.2 LCD E

'portd.4 Beeper

'portd.5 Clock keyboard
'portd.6 Data keyboard

'porte.2 Wiz810MJ reset
'portb.4 Wiz810MJ /scs

'portb.1 SPI SCK
'portb.2 SPI MOSI
'portb.3 SPI MISO

'porte.4 video Puls_RDA
'porte.5 video Acknowledge
'portc.0 video ASCII bit 0
'portc.1 video ASCII bit 1
'portc.2 video ASCII bit 2
'portc.3 video ASCII bit 3
'portc.4 video ASCII bit 4
'portc.5 video ASCII bit 5
'portc.6 video ASCII bit 6


Declare Sub Beep

Open "COM2:" For Binary As #1

Beeper Alias Portd.4

Config Beeper = Output

Config Lcdpin = Pin , Db4 = Porta.4 , Db5 = Porta.5 , Db6 = Porta.6 , Db7 = Porta.7 , E = Porta.2 , Rs = Porta.3

Config Lcd = 16 * 2

Cls
Home

Cursor Off

Lcd "AVR I/O Board"
Call Beep


Do
Wait 1
Print "This is commport 1"

Print #1 , "This is commport 2"
Loop


End

Sub Beep
Set Beeper
Waitms 2
Reset Beeper
End Sub

2 x MAX3232EEWE and connectors

Step 7: VNC1L-1A - USB Controller

Two buttons to program the VNC1L-1A USB-controller on the AVR Ethernet I/O board. Called PROG and RESET. When you buy the VNC1L-1A, it is almost blanc, it has a bootloader.. With the COM2 serial port, a terminal program like Hyperterminal (on 115200 baud) and a ROM-file from www.vinculum.com you can load the VNC1L-1A with the functions you want it to have. Once firmware has been loaded, an upgrade or other functions can be flashed by just plugging a USB memory stick in one of the USB connectors.

By removing two SMD resistors and placing two resistors on another place both buttons can be connected to the Atmega128, so you will have a total of 5 buttons to work with.

2 x USB connector

Don't under-estimate placing this chip on the AVR Ethernet I/O board, the VNC1L-1A.
It is difficult. Very small.

When you put the JP4 jumpers to the right, COM2 with it's MAX3232 is connected to the VNC1L-1A and you can type the commands from Hyperterminal at 9600 baud. When a memorystick is inserted it is detected. First thing is looking for a file to upgrade the firmware of the VNC1L-1A.

FS, followed with IDD will show you the information of the memory stick.

To create and write to a file this is what you can do in Hyperterminal

IPA

OPW TEST.TXT

WRF 16

AVR ETHERNET I/O

CLF TEST.TXT

and to read the file back

RD TEST.TXT

 

And to do this from within Bascom-AVR

 

'VNC - Doing a DIR of the USB-stick, create a file called AVR.TXT, add or append a line of text and read the file back.

'Monkey proof code

$regfile "m128def.dat"
$crystal = 8000000
$baud = 9600                                                ' first hardware UART
$baud1 = 9600                                               ' second hardware UART

Declare Sub Wait_for_prompt
Declare Sub Reset_vnc
Declare Sub Usb_cmd(byval Command As String)

'dimension used variables
Dim C As String * 1
Dim X As Byte
Dim Z As Byte
Dim Command As String * 15
Dim Usb_handle As Byte
Dim Check As Byte
Dim Teller As Word
Dim No_stick As Byte

Open "COM2:" For Binary As #2
Open "COM1:" For Binary As #1

Config Portc.7 = Output
Config Timer1 = Timer , Prescale = 256                      'Config timer1 for a 1 second interval

Enable Timer1

On Timer1 Isr_timer1                                        'Timer interrupt routine
Enable Interrupts                                           'Activate the Interrupts
Timer1 = 34285                                              'Startvalue for the second timer

Do

Call Reset_vnc
usb_handle = 1
Check = 10
Call Wait_for_prompt
Wait 3

Call Usb_cmd( "DIR")
Check = 10
Call Wait_for_prompt
Wait 3

Call Usb_cmd( "IPA")
Wait 1

Call Usb_cmd( "OPW AVR.TXT")
Check = 10
Call Wait_for_prompt

Call Usb_cmd( "WRF 17")
Wait 1

Call Usb_cmd( "Bens HobbyCorner{013}")
Check = 10
Call Wait_for_prompt
Wait 1

Call Usb_cmd( "CLF AVR.TXT")
Check = 10
Call Wait_for_prompt
Wait 1

Call Usb_cmd( "RD AVR.TXT")
Check = 10
Call Wait_for_prompt

Incr Teller
Loop Until Teller = 10000

End

'reset VNC1L-1A
Sub Reset_vnc
   Reset Portc.7
   Set Portc.7
   Check = 10
   Incr No_stick
   If No_stick = 10 Then
      Print "No stick"
      Stop
   End If
End Sub

Sub Usb_cmd(command As String)
   Print Command
   For X = 1 To Len(command)
   C = Mid(command , X , 1)
   Z = Asc(c)
   Put #2 , Z
   Waitms 100
   Next X
   Z = 13
   Put #2 , Z
End Sub

Sub Wait_for_prompt
   Do
   Get #2 , Z
   Print Chr(z);
   Loop Until Z = Asc( ">")
   Check = 0
   No_stick = 0
End Sub

Isr_timer1:                                                 'ISR of Timer1
Timer1 = 34285                                              'Timer1 must start from 34285 again

If Usb_handle = 1 Then
   Decr Check
   If Check = 0 Then
      Call Reset_vnc
   End If
End If
Return

 

You have to format your USB memory stick with 512 bytes sector size. This can be done like this:

FORMAT E: /FS:FAT32 /A:512

Step 8: Tools and toughts about VNC1L-1A

 

The way to program the blanc VNC1L-1A USB chip.
CTS jumper on. 6-pin jumper place to connect COM2 directly to the UART of the VNC-chip
DB9 to DB9 dongle, with RTS and CTS crossed.

Start VPROG_COM.EXE, select the right ROM-file, select the COM-port, press PROG on the board and power-up the board. Shortly press RESET and the firmware update is started.

 

Step 9: PS/2 keyboard

'PS2-keyboard


$regfile = "m128def.dat"
$crystal = 8000000
$baud = 9600

'Hardware

'LCD
'portb.7 LCD Db7
'portb.6 LCD Db6
'portb.5 LCD Db5
'portb.4 LCD Db4
'portb.3 LCD RS
'portb.2 LCD E

'portd.4 Beeper

'portd.5 Clock keyboard
'portd.6 Data keyboard

'porte.2 Wiz810MJ reset
'portb.4 Wiz810MJ /scs

'portb.1 SPI SCK
'portb.2 SPI MOSI
'portb.3 SPI MISO

'porte.4 video Puls_RDA
'porte.5 video Acknowledge
'portc.0 video ASCII bit 0
'portc.1 video ASCII bit 1
'portc.2 video ASCII bit 2
'portc.3 video ASCII bit 3
'portc.4 video ASCII bit 4
'portc.5 video ASCII bit 5
'portc.6 video ASCII bit 6

'Portd.4 Beeper

'portd.5 Clock keyboard
'portd.6 Data keyboard

'porte.2 Wiz810MJ reset
'portb.4 Wiz810MJ /scs

'portb.1 SPI SCK
'portb.2 SPI MOSI
'portb.3 SPI MISO

$hwstack = 64 ' default use 32 for the hardware stack
$swstack = 64 ' default use 10 for the SW stack
$framesize = 64 ' default use 40 for the frame space

Config Lcdpin = Pin , Db4 = Porta.4 , Db5 = Porta.5 , Db6 = Porta.6 , Db7 = Porta.7 , E = Porta.2 , Rs = Porta.3

Config Lcd = 16 * 2

Cls
Home

'configure the pins to use for the clock and data
'can be any pin that can serve as an input
'Keydata is the label of the key translation table
Config Keyboard = Pind.5 , Data = Pind.6 , Keydata = Keydata

'Dim some used variables
Dim S As String * 100
Dim B As Byte

'In this example we use SERIAL(COM) INPUT redirection
$serialinput = Kbdinput

'Show the program is running
Lcd "Keyboard"
Lowerline
Lcd "to com-port"

Do
Input S
Do
B = Getatkbd()
Loop Until B <> 0
'Print B
Loop
End

'Since we do a redirection we call the routine from the redirection routine
'
Kbdinput:
'we come here when input is required from the COM port
'So we pass the key into R24 with the GetATkbd function
' We need some ASM code to save the registers used by the function
$asm
push r16 ; save used register
push r25
push r26
push r27

Kbdinput1:
rCall _getatkbd ; call the function
tst r24 ; check for zero
breq Kbdinput1 ; yes so try again
pop r27 ; we got a valid key so restore registers
pop r26
pop r25
pop r16
$end Asm
'just return
Return

'This is the key translation table

Keydata:

'normal keys lower case
Data 0 , 0 , 0 , 0 , 0 , 200 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , &H5E , 0 '
Data 0 , 0 , 0 , 0 , 0 , 113 , 49 , 0 , 0 , 0 , 122 , 115 , 97 , 119 , 50 , 0
Data 0 , 99 , 120 , 100 , 101 , 52 , 51 , 0 , 0 , 32 , 118 , 102 , 116 , 114 , 53 , 0 '
Data 0 , 110 , 98 , 104 , 103 , 121 , 54 , 7 , 8 , 44 , 109 , 106 , 117 , 55 , 56 , 0 '
Data 0 , 44 , 107 , 105 , 111 , 48 , 57 , 0 , 0 , 46 , 45 , 108 , 48 , 112 , 43 , 0 '
Data 0 , 0 , 0 , 0 , 0 , 92 , 0 , 0 , 0 , 0 , 13 , 0 , 0 , 92 , 0 , 0 '
Data 0 , 60 , 0 , 0 , 0 , 0 , 8 , 0 , 0 , 49 , 0 , 52 , 55 , 0 , 0 , 0 '
Data 48 , 44 , 50 , 53 , 54 , 56 , 0 , 0 , 0 , 43 , 51 , 45 , 42 , 57 , 0 , 0 '

'shifted keys UPPER case
Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 '
Data 0 , 0 , 0 , 0 , 0 , 81 , 33 , 0 , 0 , 0 , 90 , 83 , 65 , 87 , 34 , 0 '
Data 0 , 67 , 88 , 68 , 69 , 0 , 35 , 0 , 0 , 32 , 86 , 70 , 84 , 82 , 37 , 0 '
Data 0 , 78 , 66 , 72 , 71 , 89 , 38 , 0 , 0 , 76 , 77 , 74 , 85 , 47 , 40 , 0 '
Data 0 , 59 , 75 , 73 , 79 , 61 , 41 , 0 , 0 , 58 , 95 , 76 , 48 , 80 , 63 , 0 '
Data 0 , 0 , 0 , 0 , 0 , 96 , 0 , 0 , 0 , 0 , 13 , 94 , 0 , 42 , 0 , 0 '
Data 0 , 62 , 0 , 0 , 0 , 8 , 0 , 0 , 49 , 0 , 52 , 55 , 0 , 0 , 0 , 0 '

Data 48 , 44 , 50 , 53 , 54 , 56 , 0 , 0 , 0 , 43 , 51 , 45 , 42 , 57 , 0 , 0 '

 

Step 10: Wiz810MJ-ethernet controller

 

' WIZ810MJ Ethernet demo

'---------------------------------------------
' Atmega128 and WIZ810MJ 
'---------------------------------------------


$regfile = "m128def.dat"
$crystal = 8000000
$baud = 9600

$hwstack = 128
$swstack = 128
$framesize = 128


'Hardware

'LCD
'portb.7 LCD Db7
'portb.6 LCD Db6
'portb.5 LCD Db5
'portb.4 LCD Db4
'portb.3 LCD RS
'portb.2 LCD E

'portd.4 Beeper

'portd.5 Clock keyboard
'portd.6 Data keyboard

'porte.2 Wiz810MJ reset
'portb.4 Wiz810MJ /scs

'portb.1 SPI SCK
'portb.2 SPI MOSI
'portb.3 SPI MISO

'porte.4 video Puls_RDA
'porte.5 video Acknowledge
'portc.0 video ASCII bit 0
'portc.1 video ASCII bit 1
'portc.2 video ASCII bit 2
'portc.3 video ASCII bit 3
'portc.4 video ASCII bit 4
'portc.5 video ASCII bit 5
'portc.6 video ASCII bit 6

Beeper Alias Portd.4

Config Beeper = Output

Config Lcdpin = Pin , Db4 = Porta.4 , Db5 = Porta.5 , Db6 = Porta.6 , Db7 = Porta.7 , E = Porta.2 , Rs = Porta.3

Config Lcd = 16 * 2

$include "w5100.inc"

'Used Wiz5100 ports and pins
Wiz5100_cs Alias Portb.4 ' Chipselect WIZ810MJ
Wiz5100_res Alias Porte.2 ' reset of WIZ810MJ

'Used ports and pins
Config Wiz5100_cs = Output
Config Wiz5100_res = Output


'Configuration of the SPI-bus
Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = Low , Phase = 0 , Clockrate = 4 , Noss = 0

'Init the spi pins
Spiinit

Wait 1

'Here we declare the used sub routines
Declare Sub Wiz5100_init
Declare Sub Wiz5100_readvalue(byval Reg As Word)
Declare Sub Wiz5100_writevalue(byval Reg As Word , Byval Value As Byte)
Declare Sub Wiz5100_reset
Declare Sub Beep

Dim Value As Byte
Dim Adres As Word
Dim Adresl As Byte At Adres Overlay
Dim Adresh As Byte At Adres + 1 Overlay
Dim Wiz5100_opcode_read As Byte
Wiz5100_opcode_read = 15
Dim Wiz5100_opcode_write As Byte
Wiz5100_opcode_write = 240

Cls
Home

Cursor Off

Lcd "Seaportlighting"
Lowerline
Call Beep
Lcd "Wiz810MJ-test "

Wait 1

Call Wiz5100_init ' We initialize the Wiz810MJ

Do
Loop

End

Sub Wiz5100_init
Call Wiz5100_reset 'Hardware reset
'Register reset
Call Wiz5100_writevalue(w5100_mr , &H80)
'Set gateway IP adress
Call Wiz5100_writevalue(w5100_gar0 , 192) 'My gateway
Call Wiz5100_writevalue(w5100_gar1 , 168)
Call Wiz5100_writevalue(w5100_gar2 , 0)
Call Wiz5100_writevalue(w5100_gar3 , 254)
'Set Subnetmask
Call Wiz5100_writevalue(w5100_subr0 , 255) 'My networkmask
Call Wiz5100_writevalue(w5100_subr1 , 255)
Call Wiz5100_writevalue(w5100_subr2 , 255)
Call Wiz5100_writevalue(w5100_subr3 , 0)
'Set MAC
Call Wiz5100_writevalue(w5100_shar0 , 0) 'My MAC-address
Call Wiz5100_writevalue(w5100_shar1 , 1)
Call Wiz5100_writevalue(w5100_shar2 , 2)
Call Wiz5100_writevalue(w5100_shar3 , 3)
Call Wiz5100_writevalue(w5100_shar4 , 4)
Call Wiz5100_writevalue(w5100_shar5 , 5)
'Set own IP adress
Call Wiz5100_writevalue(w5100_sipr0 , 192) 'My IP-number
Call Wiz5100_writevalue(w5100_sipr1 , 168)
Call Wiz5100_writevalue(w5100_sipr2 , 0)
Call Wiz5100_writevalue(w5100_sipr3 , 50)
End Sub


Sub Wiz5100_readvalue(reg)
Adres = Reg
Reset Wiz5100_cs
Spiout Wiz5100_opcode_read , 1
Spiout Adresh , 1
Spiout Adresl , 1
Spiin Value , 1
Set Wiz5100_cs
End Sub


Sub Wiz5100_writevalue(reg , Value )
Adres = Reg
Reset Wiz5100_cs
Spiout Wiz5100_opcode_write , 1
Spiout Adresh , 1
Spiout Adresl , 1
Spiout Value , 1
Set Wiz5100_cs
End Sub


Sub Wiz5100_reset
Waitms 250
Wiz5100_res = 1
Waitms 250
Wiz5100_res = 0
Waitms 250
Wiz5100_res = 1
End Sub


Sub Beep
Set Beeper
Waitms 2
Reset Beeper
End Sub

More examples for the WIZ810MJ can be found here: https://benshobbycorner.nl/bzijlstra/software/examples/wiz810mj.htm

Step 10: DS1307 Real Time Clock

To check if the DS1307Z+ can be found on the I2c-bus I use the I2c-scanner which I wrote a few years back.

and here the code

$regfile "m128def.dat"
$crystal = 8000000
Baud = 9600

Dim Yn As String * 1
Dim Adrx As Word
Dim Row As Byte

$lib "i2c_twi.lbx" ' we do not use software emulated I2C but the TWI

Config Scl = Portd.0 ' we need to provide the SCL pin name
Config Sda = Portd.1 ' we need to provide the SDA pin name

I2cinit ' we need to set the pins in the proper state

Print Chr(&H1b) ; "[2J"; ' ANSI goto 0/0 Print
Print "Where is the DS1307Z+?"
Print

Config Twi = 100000 ' wanted clock frequency

'will set TWBR and TWSR
'Twbr = 12 'bit rate register
'Twsr = 0 'pre scaler bits


Print "I2c-device locator 1 = no device 0 = device"
Print
Print " 0 2 4 6 8 A C E"
Print " 0000 ";
For Adrx = 0 To 254 Step 2
Row = Adrx Mod 16 ' addresses
If Row = 0 And Adrx > 0 Then
Print ' end of line?
Print " " ; Hex(adrx) ; " ";
End If
I2cstart ' generate start
I2cwbyte Adrx
Print " " ; Err ; " "; ' 1 no device, 0 device
I2cstop
Next Adrx
Print

Print

End

 

To be continued...

Thanks to:


Thanks to Mark Alberts
the creator of Bascom-AVR
www.mcselec.com

Thanks to San Bergmans
www.sbprojects.net
He created the video-routines for the
Atmega32. Can be found on the A-One and on the WebCat.

 

Ben Zijlstra - Ben's HobbyCorner - 2009