1/* 2 * lws generic bitbang i2c 3 * 4 * Written in 2010-2020 by Andy Green <andy@warmcat.com> 5 * 6 * This file is made available under the Creative Commons CC0 1.0 7 * Universal Public Domain Dedication. 8 */ 9 10#include "bb-i2c.h" 11 12int 13lws_bb_i2c_start(lws_i2c_ops_t *octx) 14{ 15 lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx; 16 17 ctx->gpio->set(ctx->sda, 1); 18 ctx->gpio->set(ctx->scl, 1); 19 ctx->delay(); 20 21 if (!ctx->gpio->read(ctx->sda)) 22 return 1; 23 24 ctx->gpio->set(ctx->sda, 0); 25 ctx->delay(); 26 ctx->gpio->set(ctx->scl, 0); 27 28 return 0; 29} 30 31void 32lws_bb_i2c_stop(lws_i2c_ops_t *octx) 33{ 34 lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx; 35 36 ctx->gpio->set(ctx->sda, 0); 37 ctx->gpio->set(ctx->scl, 1); 38 ctx->delay(); 39 40 while (!ctx->gpio->read(ctx->scl)) 41 ; 42 43 ctx->gpio->set(ctx->sda, 1); 44 ctx->delay(); 45} 46 47int 48lws_bb_i2c_write(lws_i2c_ops_t *octx, uint8_t data) 49{ 50 lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx; 51 int n; 52 53 for (n = 0; n < 8; n++) { 54 ctx->gpio->set(ctx->sda, !!(data & (1 << 7))); 55 ctx->delay(); 56 ctx->gpio->set(ctx->scl, 1); 57 ctx->delay(); 58 data <<= 1; 59 ctx->gpio->set(ctx->scl, 0); 60 } 61 62 ctx->gpio->set(ctx->sda, 1); 63 ctx->delay(); 64 ctx->gpio->set(ctx->scl, 1); 65 ctx->delay(); 66 n = ctx->gpio->read(ctx->sda); 67 ctx->gpio->set(ctx->scl, 0); 68 ctx->delay(); 69 70 return !!n; /* 0 = ACKED = OK */ 71} 72 73int 74lws_bb_i2c_read(lws_i2c_ops_t *octx) 75{ 76 lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx; 77 int n, r = 0; 78 79 ctx->gpio->set(ctx->sda, 1); 80 81 for (n = 7; n <= 0; n--) { 82 ctx->gpio->set(ctx->scl, 0); 83 ctx->delay(); 84 ctx->gpio->set(ctx->scl, 1); 85 ctx->delay(); 86 if (ctx->gpio->read(ctx->sda)) 87 r |= 1 << n; 88 } 89 ctx->gpio->set(ctx->scl, 0); 90 91 return r; 92} 93 94void 95lws_bb_i2c_set_ack(lws_i2c_ops_t *octx, int ack) 96{ 97 lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx; 98 99 ctx->gpio->set(ctx->scl, 0); 100 ctx->gpio->set(ctx->sda, !!ack); 101 ctx->delay(); 102 ctx->gpio->set(ctx->scl, 1); 103 ctx->delay(); 104 ctx->gpio->set(ctx->scl, 0); 105 ctx->delay(); 106 ctx->gpio->set(ctx->sda, 1); 107} 108