forked from CalcProgrammer1/Stepper-Motor-Controller
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.c
136 lines (108 loc) · 2.87 KB
/
main.c
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*! \file
This file implements a simple i2c to pwm converter.
Initial state is 0% duty cycle for the PWM (on PWM_PIN).
You send a single byte where 255 is the maximum duty cycle.
copyright (c) 2015 Joerg Albert <[email protected]>
*/
#include <stdbool.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "usi_i2c_slave.h"
#if defined(__AVR_ATtiny85__)
/* pin config for ATtiny85:
PB0 - SDA (DIL: pin 5)
PB1 - PWM (OC0B) (DIL: pin 6)
PB2 - SCL (DIL: pin 7)
PB3 - LED (DIL: pin 2)
*/
#define LED_PIN PB3
#define PWM_PIN PB1
#else
# error "no pin config provided"
#endif
/* 8bit slave address */
#define SLAVE_ADDR 0x56
#ifndef F_CPU
# error "F_CPU undefined"
#endif
volatile static uint8_t new_pwm_level; /*!< new pwm duty cycle set in the IRQ handler */
static uint8_t pwm_level; /*!< last pwm duty cycle seen in the main loop */
uint8_t led_on; /* if > 0 the LED is on */
static void init_pwm(void)
{
DDRB |= (1<<PWM_PIN);
TCCR0A = (1<<COM0B1)|(1<<WGM00); // mode #1
TCCR0B = (1<<CS01); // div8 (any speed would do)
OCR0B = 0; // off at init
}
/*! init LED */
static void init_led(void)
{
/* led off */
PORTB &= ~(1<<LED_PIN);
/* output */
DDRB |= (1<<LED_PIN);
}
/*! set LED on/off
LED on == pin high, i.e. connect LED to ground.
*/
static inline void set_led(bool on)
{
if (on)
PORTB |= (1 << LED_PIN);
else
PORTB &= ~(1 << LED_PIN);
}
/*! set PWM level
\param[in] lvl PWM level (0...255)
*/
static inline set_pwm(uint8_t lvl)
{
OCR0B = lvl;
}
/*! procedure called for a i2c master read access.
Be aware that it is called in IRQ context, so be fast here!
\param index the number of the data byte requested, starting with 0
\return data byte to be passed to the i2c master
*/
static uint8_t master_read(uint8_t index)
{
return new_pwm_level;
}
/*! procedure called for a i2c master write access.
Be aware that it is called in IRQ context, so be fast here!
\param data the data byte
\param index the number of the data byte in the current master write access
\return true if we will assert ACK on the i2c bus after the next data byte written by the master
*/
static bool master_write(uint8_t data, uint8_t index)
{
new_pwm_level = data;
return false;
}
int main(void)
{
int i;
cli();
USI_I2C_Slave_Init(SLAVE_ADDR, master_read, master_write);
init_pwm();
init_led();
sei();
while (1) {
if (pwm_level != new_pwm_level) {
/* a new level was set by a write from twi master */
pwm_level = new_pwm_level;
set_led(true);
set_pwm(pwm_level);
led_on=9; /* with a delay of 250ms, the LED will be on for 2s for each change in the PWM value */
}
if (led_on > 0)
led_on--;
else
set_led(false);
_delay_ms(250);
}
return 0;
}