aboutsummaryrefslogtreecommitdiffstats
path: root/LUFA/Drivers/Peripheral/TWI.c
blob: b8aec48522f47cbcf1da220e2b659370f61b2b0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*
     Copyright (C) Dean Camera, 2010.
              
  dean [at] fourwalledcubicle [dot] com
      www.fourwalledcubicle.com
*/

#include "TWI.h"

bool TWI_StartTransmission(const uint8_t SlaveAddress,
                           const uint8_t TimeoutMS)
{
	for (;;)
	{
		bool     BusCaptured = false;
		uint16_t TimeoutRemaining;

		TWCR = ((1 << TWINT) | (1 << TWSTA) | (1 << TWEN));	

		TimeoutRemaining = (TimeoutMS * 100);
		while (TimeoutRemaining-- && !(BusCaptured))
		{
			if (TWCR & (1 << TWINT))
			{
				switch (TWSR & TW_STATUS_MASK)
				{
					case TW_START:
					case TW_REP_START:
						BusCaptured = true;
						break;
					case TW_MT_ARB_LOST:
						TWCR = ((1 << TWINT) | (1 << TWSTA) | (1 << TWEN));	
						continue;
					default:
						TWCR = (1 << TWEN);
						return false;
				}
			}
			
			_delay_us(10);
		}
		
		if (!(BusCaptured))
		{
			TWCR = (1 << TWEN);
			return false;
		}
		
		TWDR = SlaveAddress;
		TWCR = ((1 << TWINT) | (1 << TWEN));
		
		TimeoutRemaining = (TimeoutMS * 100);
		while (TimeoutRemaining--)
		{
			if (TWCR & (1 << TWINT))
			  break;
			  
			_delay_us(10);
		}
		
		if (!(TimeoutRemaining))
		  return false;

		switch (TWSR & TW_STATUS_MASK)
		{
			case TW_MT_SLA_ACK:
			case TW_MR_SLA_ACK:
				return true;
			default:
				TWCR = ((1 << TWINT) | (1 << TWSTO) | (1 << TWEN));
				return false;
		}
	}
}