JM 9 Dec 2023 - I2C bitbang with parallel port and lpttcl
Based on: http://www.bitbanging.space/posts/bitbang-i2c and Example #2 from Firmata
Windows XP, parallel port:
bit 0 = DB25 pin 2 = SDA
bit 1 = DB25 pin 3 = SCL
2K pull up resistors to 5V
Write to LCD with I2C backpack
### console show set pin_state 0 load lpttcl set ver [package require lpttcl] lpt_wrdata 0x00 puts [lpt_rdstat] set val 0 lpt_rdstat proc clearBit {n} { global val set val [expr $val & [expr ~$n]] lpt_wrdata $val } proc setBit {n} { global val set val [expr $val | $n] lpt_wrdata $val } proc SDA_ON {} { # bit 0 (DB25 pin 2) weight 1 set pinSDA 1 #set pin_state [expr $pin_state|(1<<$pinSDA)] setBit $pinSDA puts -nonewline "1" update } proc SDA_OFF {} { # bit 0 (DB25 pin 2) weight 1 set pinSDA 1 #set pin_state [expr $pin_state&~(1<<$pinSDA)] puts -nonewline "0" clearBit $pinSDA update } proc SCL_ON {} { # bit 1 (DB25 pin 3) weight 2 set pinSCL 2 #set pin_state [expr $pin_state|(1<<$pinSCL)] #puts -nonewline "_" #puts ">>>HIGH" setBit $pinSCL update } proc SCL_OFF {} { # bit 1 (DB25 pin 3) weight 2 set pinSCL 2 #set pin_state [expr $pin_state&~(1<<$pinSCL)] #puts -nonewline "." #puts "<<<LOW" clearBit $pinSCL update } proc DLY {} { after 1 } proc start {} { SDA_ON DLY SCL_ON DLY SDA_OFF DLY SCL_OFF DLY } proc stop {} { SDA_OFF DLY SCL_ON DLY SDA_ON DLY } proc TX {dat} { for {set i 8} {$i > 0} {incr i -1} { # (dat & 0x80) ? SDA_ON : SDA_OFF; //Mask for the eigth bit set mask8 [expr $dat & 0x80] if $mask8 { #puts "$i = SDA_ON" SDA_ON } else { #puts "$i = SDA_OFF" SDA_OFF } # dat<<=1; //Move set dat [expr $dat <<1] DLY SCL_ON DLY SCL_OFF DLY } SDA_ON; #puts "extra SDA_ON" SCL_ON; DLY # bool ack = !SDA_READ; // Acknowledge bit # tk_messageBox -message "ACK bit" SCL_OFF puts "=" #return ack; } # to LCD with I2C module # proc sendX {hexString} { start puts ">" foreach byte $hexString { TX $byte } stop puts "<" } proc send_data {byte} { global addr set byte [string range $byte end-1 end] puts "byte: $byte" foreach {n1 n2} [split $byte ""] break sendX [list $addr 0x${n1}5 0x${n1}1 0x${n2}5 0x${n2}1] } #set addr 0x27 set addr 0x4e # LCD Initialization for 4-BIT bus sendX [list $addr 0x34 0x30] after 50 # LCD Initialization for 4-BIT bus sendX [list $addr 0x34 0x30 0x34 0x30 0x24 0x20 0x24 0x20] # 2 Line LCD, 5x10 character sendX [list $addr 0xc4 0xc0] # 01 = Clear Display sendX [list $addr 0x04 0x00 0x14 0x10] # ^ ^ ^ ^ # 0C = Display Control,Display ON sendX [list $addr 0x04 0x00 0xc4 0xc0] # 06 = Entry Mode Set, Auto Increment of cursor position sendX [list $addr 0x04 0x00 0x64 0x60] # foreach letter [split "Tcl/Tk lptt I2C" ""] { binary scan $letter "H2" valor send_data $valor } puts "*** DONE!"