- renamed folder
git-svn-id: http://moon:8086/svn/projects/HendiControl@161 fda53097-d464-4ada-af97-ba876c37ca34
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* adc.c
|
||||
*
|
||||
* Created: 20.02.2019 20:46:32
|
||||
* Author: jens
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include "adc.h"
|
||||
#include "message.h"
|
||||
|
||||
static volatile uint8_t adc_ch = 0;
|
||||
static Fifo *g_pFifo = NULL;
|
||||
static Fifo g_conversionFifo;
|
||||
static int conversionBusy = 0;
|
||||
|
||||
ISR(ADC_vect)
|
||||
{
|
||||
conversionBusy = 0;
|
||||
int16_t value_low = (int16_t)ADCL;
|
||||
int16_t value_high = (int16_t)ADCH;
|
||||
ADCSRA |= (1<<ADIF);
|
||||
int16_t value = value_high << 8 | value_low;
|
||||
|
||||
Msg_t msg =
|
||||
{
|
||||
.code = AdcComplete,
|
||||
.m.adc.ch = adc_ch,
|
||||
.m.adc.data = value,
|
||||
};
|
||||
fifo_push(g_pFifo, &msg);
|
||||
if (!fifo_isEmpty(&g_conversionFifo))
|
||||
{
|
||||
uint8_t ch;
|
||||
fifo_pop(&g_conversionFifo, &ch);
|
||||
adc_start_conversion(ch);
|
||||
}
|
||||
}
|
||||
|
||||
void adc_init(Fifo *pFifo)
|
||||
{
|
||||
g_pFifo = pFifo;
|
||||
fifo_init(&g_conversionFifo, 16, sizeof(uint8_t), "ConvFifo");
|
||||
PRR &= ~(1 << PRADC);
|
||||
ADCSRA |= (1 << ADEN) | 7;
|
||||
}
|
||||
|
||||
void adc_start_conversion(uint8_t ch)
|
||||
{
|
||||
ADMUX = (ADMUX & 0xF0) | (ch & 0x0F) | (1 << REFS0);
|
||||
ADCSRA |= (1 << ADSC) | (1 << ADIE);
|
||||
adc_ch = ch & 0x0F;
|
||||
conversionBusy = 1;
|
||||
}
|
||||
|
||||
void adc_enqueue_conversion(uint8_t ch)
|
||||
{
|
||||
if (!conversionBusy)
|
||||
{
|
||||
adc_start_conversion(ch);
|
||||
}
|
||||
else
|
||||
{
|
||||
fifo_push(&g_conversionFifo, &ch);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* adc.h
|
||||
*
|
||||
* Created: 20.02.2019 20:46:44
|
||||
* Author: jens
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ADC_H_
|
||||
#define ADC_H_
|
||||
|
||||
#include "fifo.h"
|
||||
|
||||
void adc_init(Fifo *pFifo);
|
||||
void adc_start_conversion(uint8_t ch);
|
||||
void adc_enqueue_conversion(uint8_t ch);
|
||||
|
||||
#endif /* ADC_H_ */
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* fifo.c
|
||||
*
|
||||
* Created: 20.02.2019 20:33:06
|
||||
* Author: jens
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "fifo.h"
|
||||
|
||||
static volatile size_t criticalCount = 0;
|
||||
|
||||
void enterCritical()
|
||||
{
|
||||
cli();
|
||||
criticalCount++;
|
||||
}
|
||||
|
||||
void exitCritial()
|
||||
{
|
||||
if (criticalCount)
|
||||
{
|
||||
criticalCount--;
|
||||
if (!criticalCount)
|
||||
{
|
||||
sei();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fifo_init(Fifo *pObj, size_t capacity, size_t itemSize, const char *pName)
|
||||
{
|
||||
pObj->wi = 0;
|
||||
pObj->ri = 0;
|
||||
pObj->fill = 0;
|
||||
pObj->capacity = capacity;
|
||||
pObj->itemSize = itemSize;
|
||||
pObj->ppData = (uint8_t**)malloc(capacity*sizeof(uint8_t*));
|
||||
|
||||
for (int i=0; i < capacity; i++)
|
||||
{
|
||||
pObj->ppData[i] = (uint8_t*)malloc(itemSize);
|
||||
}
|
||||
pObj->pName = pName;
|
||||
}
|
||||
|
||||
void fifo_free(Fifo *pObj)
|
||||
{
|
||||
for (int i=0; i < pObj->capacity; i++)
|
||||
{
|
||||
free(pObj->ppData[i]);
|
||||
}
|
||||
free (pObj->ppData);
|
||||
pObj->itemSize = 0;
|
||||
pObj->capacity = 0;
|
||||
}
|
||||
|
||||
int fifo_push(Fifo *pObj, void *pItem)
|
||||
{
|
||||
int success = 0;
|
||||
enterCritical();
|
||||
do
|
||||
{
|
||||
if (pObj->fill >= pObj->capacity)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (size_t i=0; i < pObj->itemSize; i++)
|
||||
{
|
||||
pObj->ppData[pObj->wi][i] = ((uint8_t*)pItem)[i];
|
||||
}
|
||||
pObj->wi++;
|
||||
pObj->fill++;
|
||||
if (pObj->wi == pObj->capacity)
|
||||
{
|
||||
pObj->wi = 0;
|
||||
}
|
||||
success = 1;
|
||||
} while (0);
|
||||
exitCritial();
|
||||
return success;
|
||||
}
|
||||
|
||||
int fifo_pop(Fifo *pObj, void *pItem)
|
||||
{
|
||||
int success = 0;
|
||||
enterCritical();
|
||||
do
|
||||
{
|
||||
if (!pObj->fill)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (size_t i=0; i < pObj->itemSize; i++)
|
||||
{
|
||||
((uint8_t*)pItem)[i] = pObj->ppData[pObj->ri][i];
|
||||
}
|
||||
pObj->ri++;
|
||||
pObj->fill--;
|
||||
if (pObj->ri == pObj->capacity)
|
||||
{
|
||||
pObj->ri = 0;
|
||||
}
|
||||
success = 1;
|
||||
} while(0);
|
||||
exitCritial();
|
||||
return success;
|
||||
}
|
||||
|
||||
int fifo_isEmpty(Fifo *pObj)
|
||||
{
|
||||
enterCritical();
|
||||
int isEmpty = (pObj->fill == 0);
|
||||
exitCritial();
|
||||
|
||||
return isEmpty;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* fifo.h
|
||||
*
|
||||
* Created: 20.02.2019 20:35:48
|
||||
* Author: jens
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FIFO_H_
|
||||
#define FIFO_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
typedef struct _sFifo
|
||||
{
|
||||
uint8_t **ppData;
|
||||
size_t capacity;
|
||||
size_t itemSize;
|
||||
size_t volatile fill;
|
||||
size_t volatile wi;
|
||||
size_t volatile ri;
|
||||
const char *pName;
|
||||
} Fifo;
|
||||
|
||||
void fifo_init(Fifo *pObj, size_t capacity, size_t itemSize, const char *pName);
|
||||
void fifo_free(Fifo *pObj);
|
||||
int fifo_push(Fifo *pObj, void *pItem);
|
||||
int fifo_pop(Fifo *pObj, void *pItem);
|
||||
int fifo_isEmpty(Fifo *pObj);
|
||||
|
||||
void enterCritical();
|
||||
void exitCritial();
|
||||
|
||||
#endif /* FIFO_H_ */
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* i2c.c
|
||||
*
|
||||
* Created: 20.02.2019 20:33:30
|
||||
* Author: jens
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <avr/io.h>
|
||||
#include "i2c.h"
|
||||
|
||||
void i2c_init()
|
||||
{
|
||||
TWBR = 0xFF;
|
||||
TWSR = 0x00;
|
||||
}
|
||||
|
||||
void i2c_send(uint8_t addr, uint8_t rw, uint8_t *data, size_t size)
|
||||
{
|
||||
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
|
||||
// Send START condition
|
||||
do
|
||||
{
|
||||
while (!(TWCR &(1<<TWINT))); // Wait for TWINT Flag set. This indicates
|
||||
// that the START condition has been
|
||||
// transmitted.
|
||||
if((TWSR & 0xF8) != I2C_START)
|
||||
{
|
||||
printf("Error I2C_START\n");
|
||||
break;
|
||||
}
|
||||
TWDR = addr<<1 | rw; // Load SLA_W into TWDR Register. Clear
|
||||
// TWINT bit in TWCR to start transmission of
|
||||
// address.
|
||||
TWCR = (1<<TWINT) | (1<<TWEN);
|
||||
while (!(TWCR &(1<<TWINT))); // Wait for TWINT Flag set. This indicates
|
||||
// that the SLA+W has been transmitted, and
|
||||
// ACK/NACK has been received.
|
||||
|
||||
|
||||
if ((TWSR & 0xF8) != I2C_SLA_ACK)
|
||||
{
|
||||
printf("Error I2C_SLA_ACK\n");
|
||||
break;
|
||||
}
|
||||
// Check value of TWI Status Register. Mask
|
||||
// prescaler bits. If status different from
|
||||
// MT_SLA_ACK go to ERROR
|
||||
for (size_t i=0; i < size; i++)
|
||||
{
|
||||
|
||||
TWDR = *(data++);
|
||||
TWCR = (1<<TWINT) | (1<<TWEN);
|
||||
// Load DATA into TWDR Register. Clear
|
||||
// TWINT bit in TWCR to start transmission of
|
||||
// data.
|
||||
|
||||
while (!(TWCR & (1<<TWINT)));
|
||||
// Wait for TWINT Flag set. This indicates
|
||||
// that the DATA has been transmitted, and
|
||||
// ACK/NACK has been received}
|
||||
|
||||
if ((TWSR & 0xF8) != I2C_DATA_ACK)
|
||||
{
|
||||
printf("Error I2C_DATA_ACK\n");
|
||||
break;
|
||||
}
|
||||
// Check value of TWI Status Register. Mask
|
||||
// prescaler bits. If status different from
|
||||
// MT_DATA_ACK go to ERROR.
|
||||
}
|
||||
|
||||
} while (0);
|
||||
TWCR = (1<<TWINT)| (1<<TWEN)|(1<<TWSTO); // Transmit STOP condition.
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* i2c.h
|
||||
*
|
||||
* Created: 20.02.2019 20:40:45
|
||||
* Author: jens
|
||||
*/
|
||||
|
||||
|
||||
#ifndef I2C_H_
|
||||
#define I2C_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
enum I2C
|
||||
{
|
||||
I2C_START = 0x08,
|
||||
I2C_REPEATED_START = 0x10,
|
||||
I2C_SLA_ACK = 0x18,
|
||||
I2C_SLA_NACK = 0x20,
|
||||
I2C_DATA_ACK = 0x28,
|
||||
I2C_DATA_NACK = 0x30,
|
||||
I2C_LOST = 0x38,
|
||||
I2C_READ = 0x01,
|
||||
I2C_WRITE = 0x00
|
||||
};
|
||||
|
||||
void i2c_init();
|
||||
void i2c_send(uint8_t addr, uint8_t rw, uint8_t *data, size_t size);
|
||||
|
||||
#endif /* I2C_H_ */
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* machine.h
|
||||
*
|
||||
* Created: 03.03.2019 09:21:56
|
||||
* Author: Jens
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MACHINE_H_
|
||||
#define MACHINE_H_
|
||||
|
||||
#if ARDUINO_NANO
|
||||
#define F_CPU (16000000UL) // MHz
|
||||
#else
|
||||
#define F_CPU (18432000UL) // MHz
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* MACHINE_H_ */
|
||||
Executable
+276
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* uart_echo.c
|
||||
*
|
||||
* Created: 16.08.2018 17:39:49
|
||||
* Author : jens
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/wdt.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#include "machine.h"
|
||||
#include "fifo.h"
|
||||
#include "message.h"
|
||||
#include "adc.h"
|
||||
#include "port.h"
|
||||
#include "timer.h"
|
||||
#include "uart.h"
|
||||
#include "i2c.h"
|
||||
#include "mcp42x6.h"
|
||||
|
||||
#define PRINT(a,...) printf(a, ##__VA_ARGS__)
|
||||
#define PRINT_PROMPT putchar(0x0D);putchar(0x0A);putchar(':');
|
||||
#define USART_BAUDRATE 9600UL
|
||||
#define TIMER_HW_CLOCK (F_CPU/8)
|
||||
#define TIMER_IRQ_CLOCK 1000UL
|
||||
#define TIMER_HW_RELOAD (0xFFFF-(TIMER_HW_CLOCK/TIMER_IRQ_CLOCK))
|
||||
|
||||
#define TIMER_SW_DELAY_MS(dly) ((dly*TIMER_IRQ_CLOCK)/1000UL)
|
||||
|
||||
int16_t adc_poti = 0;
|
||||
int16_t adc_swin = 0;
|
||||
int sw_in_last = 0;
|
||||
size_t cmdStrSize = 0;
|
||||
Fifo messageFifo;
|
||||
|
||||
FILE uart_file = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
|
||||
|
||||
typedef enum _eSwitch
|
||||
{
|
||||
SwitchOff = 0,
|
||||
SwitchOn = 1
|
||||
} Switch;
|
||||
|
||||
void setSwitch(int on)
|
||||
{
|
||||
const char *sw_str[2] = {"OFF", "ON"};
|
||||
PRINT("Set switch to %s\n", sw_str[on != 0]);
|
||||
portSet(PwrSwitch_out, on != 0);
|
||||
}
|
||||
|
||||
typedef enum _ePower
|
||||
{
|
||||
PowerLow = 4095,
|
||||
PowerMax = 0
|
||||
} Power;
|
||||
|
||||
void setPower(uint16_t power)
|
||||
{
|
||||
PRINT("Set Power to %u\n", power);
|
||||
uint8_t dac_cmd[] = {0x00, 0x00}; // 6.2 Write Volatile Memory (C2:C0 = ‘010’)
|
||||
size_t res = MCP47x6_write_volatile_dac(power, dac_cmd, sizeof(dac_cmd));
|
||||
i2c_send(0x60, I2C_WRITE, dac_cmd, res);
|
||||
}
|
||||
|
||||
typedef enum _eState_t
|
||||
{
|
||||
StateNormal = 0,
|
||||
StateRemote = 1,
|
||||
StateError = 2,
|
||||
State_NumStates
|
||||
} State_t;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int hb_state = 0;
|
||||
cli();
|
||||
wdt_reset();
|
||||
wdt_disable();
|
||||
|
||||
const char *state_str[State_NumStates] = {"Normal","Remote","Error"};
|
||||
|
||||
State_t state = StateNormal;
|
||||
State_t state_next = StateNormal;
|
||||
|
||||
fifo_init(&messageFifo, 8, sizeof(Msg_t), "Fifo");
|
||||
|
||||
/* Replace with your application code */
|
||||
uart_init(&messageFifo, USART_BAUDRATE);
|
||||
timer_init(&messageFifo, TIMER_HW_RELOAD, TimerClockSel_PS_8);
|
||||
adc_init(&messageFifo);
|
||||
i2c_init();
|
||||
port_init();
|
||||
|
||||
stdout = &uart_file;
|
||||
printf("Hendi Control v1.1\n");
|
||||
|
||||
uint8_t dac_cmd[] = {0x00, 0x00, 0x00}; // 6.1 Write Volatile DAC Register (C2:C0 = ‘00x’)
|
||||
size_t res = MCP47x6_write_volatile_mem(0x0000, dac_cmd, sizeof(dac_cmd));
|
||||
i2c_send(0x60, I2C_WRITE, dac_cmd, res);
|
||||
|
||||
char cmdStr[16];
|
||||
PRINT_PROMPT;
|
||||
|
||||
// Start Timer
|
||||
timer_start(TIMER_GENERAL, 0);
|
||||
timer_start(TIMER_ADC, 0);
|
||||
setSwitch(1);
|
||||
|
||||
sei();
|
||||
while (1)
|
||||
{
|
||||
state_next = state;
|
||||
Msg_t msg;
|
||||
if (!fifo_isEmpty(&messageFifo))
|
||||
{
|
||||
fifo_pop(&messageFifo, &msg);
|
||||
switch(msg.code)
|
||||
{
|
||||
case Uart:
|
||||
{
|
||||
// Process Uart message
|
||||
cmdStr[cmdStrSize] = 0;
|
||||
char c = (char)msg.m.uart.data;
|
||||
|
||||
// Command finished with CR/LF
|
||||
if (c == 0x0A || c == 0x0D)
|
||||
{
|
||||
PRINT_PROMPT;
|
||||
if (cmdStrSize < 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (state == StateNormal || state == StateRemote)
|
||||
{
|
||||
// Power Control
|
||||
if (toupper(cmdStr[0]) == 'P')
|
||||
{
|
||||
uint16_t arg = (uint16_t)strtol(cmdStr+1, (char **)NULL, 10);
|
||||
setPower(arg);
|
||||
timer_start(TIMER_TIMEOUT, TIMER_SW_DELAY_MS(5000));
|
||||
state_next = StateRemote;
|
||||
}
|
||||
|
||||
// Switch Control
|
||||
if (toupper(cmdStr[0]) == 'S')
|
||||
{
|
||||
uint16_t arg = (uint16_t)strtol(cmdStr+1, (char **)NULL, 10);
|
||||
setSwitch(arg);
|
||||
timer_start(TIMER_TIMEOUT, TIMER_SW_DELAY_MS(5000));
|
||||
state_next = StateRemote;
|
||||
}
|
||||
|
||||
// Switch Control
|
||||
if (toupper(cmdStr[0]) == 'X')
|
||||
{
|
||||
timer_stop(TIMER_TIMEOUT);
|
||||
setPower(PowerLow);
|
||||
setSwitch(SwitchOff);
|
||||
}
|
||||
}
|
||||
cmdStrSize = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cmdStrSize < (sizeof(cmdStr)-1))
|
||||
{
|
||||
cmdStr[cmdStrSize++] = c;
|
||||
}
|
||||
putchar(c);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AdcComplete:
|
||||
{
|
||||
uint8_t adc_ch = msg.m.adc.ch;
|
||||
int16_t adc_curr = (int16_t)msg.m.adc.data;
|
||||
if (adc_ch == 0)
|
||||
{
|
||||
if (((adc_curr - adc_poti) < -1) || ((adc_curr - adc_poti) > 1))
|
||||
{
|
||||
if (state == StateNormal)
|
||||
{
|
||||
setPower(adc_curr << 2);
|
||||
}
|
||||
adc_poti = adc_curr;
|
||||
}
|
||||
}
|
||||
if (adc_ch == 2)
|
||||
{
|
||||
adc_swin = adc_curr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Timer:
|
||||
{
|
||||
int timer_id = msg.m.timer.ch;
|
||||
switch(timer_id)
|
||||
{
|
||||
case TIMER_GENERAL:
|
||||
{
|
||||
hb_state = !hb_state;
|
||||
if (hb_state)
|
||||
{
|
||||
timer_start(timer_id, TIMER_SW_DELAY_MS(50));
|
||||
}
|
||||
else
|
||||
{
|
||||
timer_start(timer_id, TIMER_SW_DELAY_MS(950));
|
||||
}
|
||||
portSet(Led_HB, hb_state);
|
||||
}
|
||||
break;
|
||||
|
||||
case TIMER_TIMEOUT:
|
||||
{
|
||||
PRINT("Timeout!\n");
|
||||
state_next = StateError;
|
||||
}
|
||||
break;
|
||||
|
||||
case TIMER_ADC:
|
||||
{
|
||||
timer_start(timer_id, TIMER_SW_DELAY_MS(50));
|
||||
int sw_in = adc_swin > 512;
|
||||
if (sw_in != sw_in_last)
|
||||
{
|
||||
PRINT ("PwrSwitch_in = %d\n", sw_in);
|
||||
if (sw_in == 0)
|
||||
{
|
||||
if (state == StateError || state == StateRemote)
|
||||
{
|
||||
setSwitch(SwitchOn);
|
||||
state_next = StateNormal;
|
||||
}
|
||||
}
|
||||
}
|
||||
sw_in_last = sw_in;
|
||||
adc_enqueue_conversion(0);
|
||||
adc_enqueue_conversion(2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NOP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (state != state_next)
|
||||
{
|
||||
PRINT("State change \"%s\" => \"%s\"\n", state_str[state], state_str[state_next]);
|
||||
if (state_next == StateError)
|
||||
{
|
||||
setPower(PowerLow);
|
||||
setSwitch(SwitchOff);
|
||||
portSet(Led_ERR, 1);
|
||||
}
|
||||
if (state_next == StateNormal)
|
||||
{
|
||||
portSet(Led_ERR, 0);
|
||||
}
|
||||
}
|
||||
state = state_next;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* mcp42x6.c
|
||||
*
|
||||
* Created: 20.02.2019 20:44:16
|
||||
* Author: jens
|
||||
*/
|
||||
|
||||
#include "mcp42x6.h"
|
||||
|
||||
size_t MCP47x6_write_volatile_dac(uint16_t dac_value, uint8_t *buffer, size_t size)
|
||||
{
|
||||
*(buffer++) = ~mask & (uint8_t)(dac_value >> 8);
|
||||
*(buffer++) = (uint8_t)(dac_value >> 0);
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
size_t MCP47x6_write_volatile_mem(uint16_t dac_value, uint8_t *buffer, size_t size)
|
||||
{
|
||||
*(buffer++) = mask & 0x40;
|
||||
dac_value <<= 4;
|
||||
*(buffer++) = (uint8_t)(dac_value >> 8);
|
||||
*(buffer++) = (uint8_t)(dac_value >> 0);
|
||||
|
||||
return 3;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* mcp42x6.h
|
||||
*
|
||||
* Created: 20.02.2019 20:44:33
|
||||
* Author: jens
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MCP42X6_H_
|
||||
#define MCP42X6_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
enum MCP47x6_flags
|
||||
{
|
||||
C0 = 0x20,
|
||||
C1 = 0x40,
|
||||
C2 = 0x80,
|
||||
PDN0 = 0x10,
|
||||
PDN1 = 0x20,
|
||||
mask = 0xF0
|
||||
};
|
||||
|
||||
size_t MCP47x6_write_volatile_dac(uint16_t dac_value, uint8_t *buffer, size_t size);
|
||||
size_t MCP47x6_write_volatile_mem(uint16_t dac_value, uint8_t *buffer, size_t size);
|
||||
|
||||
#endif /* MCP42X6_H_ */
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* message.h
|
||||
*
|
||||
* Created: 02.03.2019 09:30:53
|
||||
* Author: Jens
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MESSAGE_H_
|
||||
#define MESSAGE_H_
|
||||
|
||||
typedef enum _eMsgCode
|
||||
{
|
||||
NOP = 0,
|
||||
Uart,
|
||||
AdcComplete,
|
||||
Timer,
|
||||
|
||||
} MsgCode;
|
||||
|
||||
typedef struct _sMsg_t
|
||||
{
|
||||
MsgCode code;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t data;
|
||||
} uart;
|
||||
struct
|
||||
{
|
||||
uint8_t ch;
|
||||
uint16_t data;
|
||||
} adc;
|
||||
struct
|
||||
{
|
||||
uint8_t ch;
|
||||
} timer;
|
||||
} m;
|
||||
} Msg_t;
|
||||
|
||||
#endif /* MESSAGE_H_ */
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* port.c
|
||||
*
|
||||
* Created: 20.02.2019 20:54:33
|
||||
* Author: jens
|
||||
*/
|
||||
|
||||
#include <avr/io.h>
|
||||
#include "port.h"
|
||||
|
||||
void port_init()
|
||||
{
|
||||
DDRD = 0xFC;
|
||||
DDRB = 0x06;
|
||||
PORTD = 0xC0;
|
||||
PORTB = 0x04;
|
||||
}
|
||||
|
||||
typedef struct _sPort_t
|
||||
{
|
||||
uint8_t port;
|
||||
uint8_t pin;
|
||||
uint8_t pol;
|
||||
} Port_t;
|
||||
|
||||
const Port_t portItems[NUM_ITEMS] =
|
||||
{
|
||||
{0x05, 2, 1},
|
||||
{0x0B, 6, 1},
|
||||
{0x0B, 7, 1},
|
||||
{0x0B, 2, 1},
|
||||
{0x0B, 3, 1},
|
||||
{0x0B, 4, 1},
|
||||
{0x0B, 5, 1},
|
||||
{0x05, 1, 1},
|
||||
};
|
||||
|
||||
void portSet(int portItem, int enable)
|
||||
{
|
||||
uint8_t addr = portItems[portItem].port;
|
||||
uint8_t pin_mask = 1 << portItems[portItem].pin;
|
||||
|
||||
if (enable ^ portItems[portItem].pol)
|
||||
{
|
||||
_SFR_IO8(addr) |= pin_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
_SFR_IO8(addr) &= ~pin_mask;
|
||||
}
|
||||
}
|
||||
|
||||
int portGet(int portItem)
|
||||
{
|
||||
uint8_t addr = portItems[portItem].port;
|
||||
uint8_t pin_mask = 1 << portItems[portItem].pin;
|
||||
int enable = (_SFR_IO8(addr) & pin_mask) != pin_mask;
|
||||
return enable ^ portItems[portItem].pol;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* port.h
|
||||
*
|
||||
* Created: 20.02.2019 20:54:45
|
||||
* Author: jens
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORT_H_
|
||||
#define PORT_H_
|
||||
|
||||
enum PortItem
|
||||
{
|
||||
Led_HB = 0,
|
||||
Led_MODE = 1,
|
||||
Led_ERR = 2,
|
||||
Led_0 = 3,
|
||||
Led_1 = 4,
|
||||
Led_2 = 5,
|
||||
Led_3 = 6,
|
||||
PwrSwitch_out = 7,
|
||||
NUM_ITEMS
|
||||
};
|
||||
|
||||
void port_init();
|
||||
void portSet(int portItem, int enable);
|
||||
int portGet(int portItem);
|
||||
|
||||
#endif /* PORT_H_ */
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* timer.c
|
||||
*
|
||||
* Created: 20.02.2019 20:56:18
|
||||
* Author: jens
|
||||
*/
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include "timer.h"
|
||||
#include "message.h"
|
||||
|
||||
static uint16_t timer_reload = 0;
|
||||
static Timer_t user_timer[16];
|
||||
static Fifo *g_pFifo = NULL;
|
||||
|
||||
ISR (TIMER1_OVF_vect) // Timer1 ISR
|
||||
{
|
||||
TCNT1 = timer_reload;
|
||||
|
||||
for (int i=0; i < 16; i++)
|
||||
{
|
||||
if (user_timer[i].isRunning)
|
||||
{
|
||||
if (user_timer[i].count > 0)
|
||||
{
|
||||
user_timer[i].count--;
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg_t msg =
|
||||
{
|
||||
.code = Timer,
|
||||
.m.timer.ch = i
|
||||
};
|
||||
if (fifo_push(g_pFifo, &msg))
|
||||
{
|
||||
user_timer[i].isRunning = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void timer_init(Fifo *pFifo, uint16_t TIMER_RELOAD, TimerClockSel clockSel)
|
||||
{
|
||||
g_pFifo = pFifo;
|
||||
timer_reload = TIMER_RELOAD;
|
||||
TCNT1 = TIMER_RELOAD;
|
||||
|
||||
TCCR1A = 0x00;
|
||||
TCCR1B = (TCCR1B & TimerClockSel_mask) | clockSel;
|
||||
TIMSK1 = (1 << TOIE1) ; // Enable timer1 overflow interrupt(TOIE1)
|
||||
}
|
||||
|
||||
void timer_start(TimerId timerId, uint16_t count)
|
||||
{
|
||||
enterCritical();
|
||||
user_timer[timerId].count = count;
|
||||
user_timer[timerId].isRunning = 1;
|
||||
exitCritial();
|
||||
}
|
||||
|
||||
void timer_stop(TimerId timerId)
|
||||
{
|
||||
enterCritical();
|
||||
user_timer[timerId].isRunning = 0;
|
||||
exitCritial();
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* timer.h
|
||||
*
|
||||
* Created: 20.02.2019 20:56:07
|
||||
* Author: jens
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TIMER_H_
|
||||
#define TIMER_H_
|
||||
|
||||
#include "fifo.h"
|
||||
|
||||
typedef enum _eTimerId
|
||||
{
|
||||
TIMER_GENERAL = 0,
|
||||
TIMER_TIMEOUT = 1,
|
||||
TIMER_ADC = 2
|
||||
} TimerId;
|
||||
|
||||
typedef struct _sTimer_t
|
||||
{
|
||||
volatile int isRunning;
|
||||
volatile uint16_t count;
|
||||
} Timer_t;
|
||||
|
||||
typedef enum _eTimerClockSel
|
||||
{
|
||||
TimerClockSel_none = 0,
|
||||
TimerClockSel_PS_1 = (1<<CS10),
|
||||
TimerClockSel_PS_8 = (1<<CS11),
|
||||
TimerClockSel_PS_64 = (1<<CS11) | (1<<CS10),
|
||||
TimerClockSel_PS_256 = (1<<CS12),
|
||||
TimerClockSel_PS_1024 = (1<<CS12) | (1<<CS10),
|
||||
TimerClockSel_ext_T1_neg = (1<<CS12) | (1<<CS11),
|
||||
TimerClockSel_ext_T1_pos = (1<<CS12) | (1<<CS11) | (1<<CS10),
|
||||
TimerClockSel_mask = (1<<CS12) | (1<<CS11) | (1<<CS10),
|
||||
} TimerClockSel;
|
||||
|
||||
void timer_init(Fifo *pFifo, uint16_t TIMER_RELOAD, TimerClockSel clockSel);
|
||||
void timer_start(TimerId timerId, uint16_t count);
|
||||
void timer_stop(TimerId timerId);
|
||||
#endif /* TIMER_H_ */
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* uart.c
|
||||
*
|
||||
* Created: 20.02.2019 20:50:13
|
||||
* Author: jens
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include "uart.h"
|
||||
#include "message.h"
|
||||
|
||||
static Fifo *g_pFifo = NULL;
|
||||
ISR(USART_UDRE_vect)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ISR(USART_TX_vect)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ISR(USART_RX_vect)
|
||||
{
|
||||
uint8_t status = UCSR0A;
|
||||
if (status & (1 << RXC0))
|
||||
{
|
||||
uint8_t rx_data = UDR0;
|
||||
Msg_t msg =
|
||||
{
|
||||
.code = Uart,
|
||||
.m.uart.data = rx_data
|
||||
};
|
||||
fifo_push(g_pFifo, &msg);
|
||||
}
|
||||
}
|
||||
|
||||
void uart_init(Fifo *pFifo, uint32_t baudrate)
|
||||
{
|
||||
g_pFifo = pFifo;
|
||||
|
||||
uint16_t prescale8 = UART_PRESCALE(baudrate, 8UL);
|
||||
uint16_t prescale16 = UART_PRESCALE(baudrate, 16UL);
|
||||
|
||||
uint32_t baud8 = ((prescale8+1) * 8);
|
||||
uint32_t baud16 = ((prescale16+1) * 16);
|
||||
|
||||
uint32_t err8 = abs(baudrate - baud8);
|
||||
uint32_t err16 = abs(baudrate - baud16);
|
||||
|
||||
uint16_t prescale = prescale16;
|
||||
if (err8 < err16)
|
||||
{
|
||||
prescale = prescale8;
|
||||
|
||||
// Double UART speed
|
||||
UCSR0A |= 1 << U2X0;
|
||||
}
|
||||
|
||||
// Set baud rate
|
||||
UBRR0L = (uint8_t)prescale;
|
||||
UBRR0H = (uint8_t)(prescale >> 8);
|
||||
|
||||
// Enable receiver and transmitter
|
||||
UCSR0B = (1<<TXEN0)|(1<<RXEN0);
|
||||
|
||||
// Enable RX interrupt
|
||||
UCSR0B |= (1<<RXCIE0);
|
||||
|
||||
}
|
||||
|
||||
void uart_putc(char c)
|
||||
{
|
||||
while((UCSR0A & (1<<UDRE0)) == 0)
|
||||
{
|
||||
}
|
||||
UDR0 = c;
|
||||
}
|
||||
|
||||
int uart_putchar(char c, FILE *stream)
|
||||
{
|
||||
uart_putc(c);
|
||||
if (c == 0x0A)
|
||||
{
|
||||
uart_putc(0x0D);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uart_puts(char const *str)
|
||||
{
|
||||
while(*str)
|
||||
{
|
||||
char c = *(str++);
|
||||
uart_putc(c);
|
||||
if (c == 0x0A)
|
||||
{
|
||||
uart_putc(0x0D);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* uart.h
|
||||
*
|
||||
* Created: 20.02.2019 20:50:01
|
||||
* Author: jens
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UART_H_
|
||||
#define UART_H_
|
||||
|
||||
#include "machine.h"
|
||||
#include "fifo.h"
|
||||
|
||||
#define UART_PRESCALE(baudrate, smpPerBit) ((5+ 10*F_CPU / (baudrate*smpPerBit) - 1)/10)
|
||||
|
||||
void uart_init(Fifo *pFifo, uint32_t baudrate);
|
||||
void uart_putc(char c);
|
||||
int uart_putchar(char c, FILE *stream);
|
||||
void uart_puts(char const *str);
|
||||
|
||||
|
||||
#endif /* UART_H_ */
|
||||
Reference in New Issue
Block a user