lc-i2c4bit.lua 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. local i2c, bit = i2c, bit --luacheck: read globals i2c bit
  2. return function(bus_args)
  3. local busid = bus_args.id or 0
  4. local busad = bus_args.address or 0x27
  5. local speed = bus_args.speed or i2c.SLOW
  6. local rs = bus_args.rs or 0
  7. local rw = bus_args.rw or 1
  8. local en = bus_args.en or 2
  9. local bl = bus_args.backlight or 3
  10. local d4 = bus_args.d4 or 4
  11. local d5 = bus_args.d5 or 5
  12. local d6 = bus_args.d6 or 6
  13. local d7 = bus_args.d7 or 7
  14. -- Convenience I2C setup if a pin configuration is given
  15. if bus_args.sda ~= nil and bus_args.scl ~= nil then
  16. i2c.setup(busid, bus_args.sda, bus_args.scl, speed)
  17. end
  18. -- The onus is on us to maintain the backlight state
  19. local backlight = true
  20. local function exchange(data, read)
  21. local rv = data
  22. i2c.start(busid)
  23. i2c.address(busid, busad, i2c.TRANSMITTER)
  24. i2c.write(busid, bit.set(data, en)) -- set data with en
  25. if read then
  26. i2c.start(busid) -- read 1 byte and go back to tx mode
  27. i2c.address(busid, busad, i2c.RECEIVER)
  28. rv = i2c.read(busid, 1):byte(1)
  29. i2c.start(busid)
  30. i2c.address(busid, busad, i2c.TRANSMITTER)
  31. end
  32. i2c.write(busid, data) -- lower en
  33. i2c.stop(busid)
  34. return rv
  35. end
  36. local function send4bitI2C(value, rs_en, rw_en)
  37. local meta = bit.bor(rs_en and bit.bit(rs) or 0,
  38. rw_en and bit.bit(rw) or 0,
  39. backlight and bit.bit(bl) or 0)
  40. local lo = bit.bor(bit.isset(value, 0) and bit.bit(d4) or 0,
  41. bit.isset(value, 1) and bit.bit(d5) or 0,
  42. bit.isset(value, 2) and bit.bit(d6) or 0,
  43. bit.isset(value, 3) and bit.bit(d7) or 0)
  44. local hi = bit.bor(bit.isset(value, 4) and bit.bit(d4) or 0,
  45. bit.isset(value, 5) and bit.bit(d5) or 0,
  46. bit.isset(value, 6) and bit.bit(d6) or 0,
  47. bit.isset(value, 7) and bit.bit(d7) or 0)
  48. hi = exchange(bit.bor(meta, hi), rw_en)
  49. lo = exchange(bit.bor(meta, lo), rw_en)
  50. return bit.bor(bit.lshift(bit.isset(lo, d4) and 1 or 0, 0),
  51. bit.lshift(bit.isset(lo, d5) and 1 or 0, 1),
  52. bit.lshift(bit.isset(lo, d6) and 1 or 0, 2),
  53. bit.lshift(bit.isset(lo, d7) and 1 or 0, 3),
  54. bit.lshift(bit.isset(hi, d4) and 1 or 0, 4),
  55. bit.lshift(bit.isset(hi, d5) and 1 or 0, 5),
  56. bit.lshift(bit.isset(hi, d6) and 1 or 0, 6),
  57. bit.lshift(bit.isset(hi, d7) and 1 or 0, 7))
  58. end
  59. -- init sequence from datasheet (Figure 24)
  60. local function justsend(what)
  61. i2c.start(busid)
  62. i2c.address(busid, busad, i2c.TRANSMITTER)
  63. i2c.write(busid, bit.set(what, en))
  64. i2c.write(busid, what)
  65. i2c.stop(busid)
  66. end
  67. local three = bit.bor(bit.bit(d4), bit.bit(d5))
  68. justsend(three)
  69. tmr.delay(5)
  70. justsend(three)
  71. tmr.delay(1)
  72. justsend(three)
  73. tmr.delay(1)
  74. justsend(bit.bit(d5))
  75. -- we are now primed for the FUNCTIONSET command from the liquidcrystal ctor
  76. -- Return backend object
  77. return {
  78. fourbits = true,
  79. command = function (_, cmd)
  80. return send4bitI2C(cmd, false, false)
  81. end,
  82. busy = function(_)
  83. return bit.isset(send4bitI2C(0xff, false, true), 7)
  84. end,
  85. position = function(_)
  86. return bit.clear(send4bitI2C(0xff, false, true), 7)
  87. end,
  88. write = function(_, value)
  89. return send4bitI2C(value, true, false)
  90. end,
  91. read = function(_)
  92. return send4bitI2C(0xff, true, true)
  93. end,
  94. backlight = function(_, on)
  95. backlight = on
  96. send4bitI2C(0, false, false) -- No-op
  97. return on
  98. end,
  99. }
  100. end