Files
examples/stm8-driver/src/main.c

440 lines
11 KiB
C
Raw Normal View History

2018-01-23 14:35:52 +08:00
/**************************************************************************************
Filename: main.c
Revised: Date: 2018-01-23
Revision: Revision: 1.0
Description: This file provides driver for IR decode
Revision log:
* 2018-01-23: created by strawmanbobi
**************************************************************************************/
#include <iostm8s207k8.h>
#define UARTPORT(flag) UART3_##flag
#include <intrinsics.h>
#include <stdlib.h>
//
// Define where we will be working in the EEPROM.
//
#define EEPROM_BASE_ADDRESS 0x4000
#define EEPROM_INITIAL_OFFSET 0x0040
#define EEPROM_PULSE_DATA ((unsigned char *) (EEPROM_BASE_ADDRESS + EEPROM_INITIAL_OFFSET))
#define EEPROM_CARRIER_FREQUENCY
//
// Data ready for the pulse timer ISR's to use.
//
int _numberOfPulses = 0;
int _currentPulse = 0;
char *_pulseDataAddress = NULL;
//
// Prescalar for the timer.
//
int _prescalar = 1;
//
// Some control variables to indicate if we are running or not.
//
#define STATE_WAITING_FOR_USER 0
#define STATE_RUNNING 1
int _currentState = STATE_WAITING_FOR_USER;
//
// Working variables for the UART.
//
unsigned char *_currentTxByte;
unsigned short _currentTxCount;
unsigned short _txBufferLength;
#define UART_TX_BUFFER_SIZE 258
unsigned char _txBuffer[UART_TX_BUFFER_SIZE];
//
unsigned char *_currentRxByte;
unsigned short _currentRxCount;
unsigned short _rxBufferLength;
#define UART_RX_BUFFER_SIZE 20
unsigned char _rxBuffer[UART_RX_BUFFER_SIZE];
//
unsigned char *_textMessage = "OpenIR\r\n";
//
#define UART_MODE_WAITING_FOR_DATA 0
#define UART_MODE_RECEIVING_DATA 1
unsigned char _uartMode = UART_MODE_WAITING_FOR_DATA;
//
// Commands which this remote control can understand.
//
#define COMMAND_GET_ID 1
#define COMMAND_SET_ID 2
#define COMMAND_GET_CARRIER_FREQUENCY 3
#define COMMAND_SET_CARRIER_FREQUENCY 4
#define COMMAND_GET_PULSE_DATA 5
#define COMMAND_SET_PULSE_DATA 6
#define COMMAND_TRANSMIT_PULSE_DATA 7
#define COMMAND_TRANSMIT_THIS_DATA 8
#define COMMAND_TIME_LAPSE 9
#define COMMAND_RESET 10
#define COMMAND_POWER_LED_ENABLED 11
//
// Error codes whch can be sent back to the calling application.
//
#define EC_OK 0
#define EC_UNKNOWN_COMMAND 1
#define EC_RX_BUFFER_OVERFLOW 2
//
// Generic method for sending a response.
//
void SendResponse(unsigned char *buffer, unsigned char length)
2018-01-19 19:22:57 +08:00
{
2018-01-23 14:35:52 +08:00
_txBufferLength = length;
_currentTxByte = buffer;
_currentTxCount = 0;
UARTPORT(DR = _txBufferLength + 1);
UARTPORT(CR2_TIEN = 1);
2018-01-19 19:22:57 +08:00
}
2018-01-23 14:35:52 +08:00
//
// Send a negative acknowledgement to the requester along with an error code.
//
void SendNAK(unsigned char errorCode)
{
2018-01-23 14:35:52 +08:00
_txBuffer[0] = errorCode;
SendResponse(_txBuffer, 1);
}
2018-01-23 14:35:52 +08:00
//
// Send an acknowledgement to the requester.
//
void SendACK()
{
2018-01-23 14:35:52 +08:00
_txBuffer[0] = EC_OK;
SendResponse(_txBuffer, 1);
}
2018-01-23 14:35:52 +08:00
//--------------------------------------------------------------------------------
//
// Write the a block of data into EEPROM.
//
void WriteDataToEEPROM(unsigned char *data, int length, unsigned char *destination)
{
2018-01-23 14:35:52 +08:00
//
// Check if the EEPROM is write-protected. If it is then unlock the EEPROM.
//
if (FLASH_IAPSR_DUL == 0)
{
2018-01-23 14:35:52 +08:00
FLASH_DUKR = 0xae;
FLASH_DUKR = 0x56;
}
2018-01-23 14:35:52 +08:00
//
// Write the data to the EEPROM.
//
for (int index = 0; index < length; index++)
{
*destination++ = *data++;
}
//
// Now write protect the EEPROM.
//
FLASH_IAPSR_DUL = 0;
}
2018-01-23 14:35:52 +08:00
//
// Setup the Rx buffers/counters ready to receive data.
//
void SetupRxBuffer()
{
2018-01-23 14:35:52 +08:00
_currentRxByte = _rxBuffer;
_currentRxCount = 0;
_rxBufferLength = UART_RX_BUFFER_SIZE;
_uartMode = UART_MODE_WAITING_FOR_DATA;
}
2018-01-23 14:35:52 +08:00
//
// Transmit the IR pulse data.
//
void TransmitPulseData()
{
2018-01-23 14:35:52 +08:00
_currentState = STATE_RUNNING;
_currentPulse = 0;
_pulseDataAddress = (char *) (EEPROM_PULSE_DATA + 1);
TIM2_ARRH = *_pulseDataAddress++;
TIM2_ARRL = *_pulseDataAddress++;
PD_ODR_ODR3 = *_pulseDataAddress++;
//
// Now we have everything ready we need to force the Timer 2 counters to
// reload and enable Timers 1 & 2.
//
TIM2_CR1_URS = 1;
TIM2_EGR_UG = 1;
TIM1_CR1_CEN = 1;
TIM2_CR1_CEN = 1;
}
2018-01-23 14:35:52 +08:00
//
// Process the data in the Rx buffer.
//
void ProcessUARTData()
{
2018-01-23 14:35:52 +08:00
switch (_rxBuffer[1])
{
2018-01-23 14:35:52 +08:00
case COMMAND_GET_ID:
break;
case COMMAND_SET_ID:
break;
2018-01-23 14:35:52 +08:00
case COMMAND_GET_CARRIER_FREQUENCY:
break;
2018-01-23 14:35:52 +08:00
case COMMAND_SET_CARRIER_FREQUENCY:
break;
case COMMAND_GET_PULSE_DATA:
SendResponse(EEPROM_PULSE_DATA, ((*EEPROM_PULSE_DATA) * 3) + 1);
break;
case COMMAND_SET_PULSE_DATA:
break;
case COMMAND_TRANSMIT_PULSE_DATA:
TransmitPulseData();
SendACK();
break;
default:
2018-01-23 14:35:52 +08:00
SendNAK(EC_UNKNOWN_COMMAND);
break;
}
2018-01-23 14:35:52 +08:00
_uartMode = UART_MODE_WAITING_FOR_DATA;
}
2018-01-23 14:35:52 +08:00
//--------------------------------------------------------------------------------
//
// Process the interrupt generated by the pressing of the button.
//
// This ISR makes the assumption that we only have on incoming interrupt on Port D.
//
#pragma vector = 8
__interrupt void EXTI_PORTD_IRQHandler(void)
{
2018-01-23 14:35:52 +08:00
if (_currentState != STATE_RUNNING)
{
TransmitPulseData();
}
}
2018-01-23 14:35:52 +08:00
//--------------------------------------------------------------------------------
//
// Timer 2 Overflow handler.
//
#pragma vector = TIM2_OVR_UIF_vector
__interrupt void TIM2_UPD_OVF_IRQHandler(void)
{
2018-01-23 14:35:52 +08:00
_currentPulse++;
if (_currentPulse == _numberOfPulses)
{
2018-01-23 14:35:52 +08:00
//
// We have processed the pulse data so stop now.
//
PD_ODR_ODR3 = 0;
TIM2_CR1_CEN = 0;
TIM1_CR1_CEN = 0; // Stop Timer 1.
_currentState = STATE_WAITING_FOR_USER;
}
else
{
2018-01-23 14:35:52 +08:00
TIM2_ARRH = *_pulseDataAddress++;
TIM2_ARRL = *_pulseDataAddress++;
PD_ODR_ODR3 = *_pulseDataAddress++;
TIM2_CR1_URS = 1;
TIM2_EGR_UG = 1;
}
2018-01-23 14:35:52 +08:00
//
// Reset the interrupt otherwise it will fire again straight away.
//
TIM2_SR1_UIF = 0;
}
2018-01-23 14:35:52 +08:00
//--------------------------------------------------------------------------------
//
// UART Transmit Buffer Empty handler.
//
#pragma vector = UARTPORT(T_TXE_vector)
__interrupt void UART_T_TXE_IRQHandler(void)
{
2018-01-23 14:35:52 +08:00
if (_currentTxCount < _txBufferLength)
{
2018-01-23 14:35:52 +08:00
UARTPORT(DR = *_currentTxByte++);
_currentTxCount++;
}
else
{
2018-01-23 14:35:52 +08:00
UARTPORT(CR2_TIEN = 0);
}
}
2018-01-23 14:35:52 +08:00
//--------------------------------------------------------------------------------
//
// UART Receive Buffer Not Empty handler.
//
#pragma vector = UARTPORT(R_RXNE_vector)
__interrupt void UART_R_RXNE_IRQHandler(void)
{
2018-01-23 14:35:52 +08:00
unsigned char dataByte = UARTPORT(DR);
if ((_uartMode == UART_MODE_WAITING_FOR_DATA) && (dataByte == 0xaa))
{
2018-01-23 14:35:52 +08:00
SetupRxBuffer();
_uartMode = UART_MODE_RECEIVING_DATA;
}
2018-01-23 14:35:52 +08:00
else
{
2018-01-23 14:35:52 +08:00
if (_uartMode == UART_MODE_RECEIVING_DATA)
{
2018-01-23 14:35:52 +08:00
if (_currentRxCount < (UART_RX_BUFFER_SIZE - 1))
{
*_currentRxByte++ = dataByte;
_currentRxCount++;
if (_currentRxCount > 1)
{
if ((_rxBuffer[0] - 1) == _currentRxCount)
{
ProcessUARTData();
}
}
}
else
{
//
// If we get here we have filled the UART Rx buffer.
// Not a lot we can do really so reset the system to
// wait for a new command.
//
SendNAK(EC_RX_BUFFER_OVERFLOW);
_uartMode = UART_MODE_WAITING_FOR_DATA;
}
}
}
}
2018-01-23 14:35:52 +08:00
//--------------------------------------------------------------------------------
//
// Setup Timer 2 ready to process the pulse data.
//
void SetupTimer2()
{
2018-01-23 14:35:52 +08:00
TIM2_PSCR = _prescalar;
TIM2_IER_UIE = 1; // Enable the update interrupts.
}
2018-01-23 14:35:52 +08:00
//--------------------------------------------------------------------------------
//
// Now set up the ports.
//
// PD3 - IR Pulse signal.
// PD4 - Input pin indicating that the user wishes to trigger the camera.
//
void SetupPorts()
{
2018-01-23 14:35:52 +08:00
PD_ODR = 0; // All pins are turned off.
//
// PD3 is the output for the IR control.
//
PD_DDR_DDR3 = 1;
PD_CR1_C13 = 1;
PD_CR2_C23 = 1;
//
// Now configure the input pin.
//
PD_DDR_DDR4 = 0; // PD4 is input.
PD_CR1_C14 = 1; // PD4 is floating input.
PD_CR2_C24 = 1;
//
// Set up the interrupt.
//
EXTI_CR1_PDIS = 1; // Interrupt on rising edge.
EXTI_CR2_TLIS = 1; // Rising edge only.
}
2018-01-23 14:35:52 +08:00
//--------------------------------------------------------------------------------
//
// Set up Timer 1, channel 4 to output a PWM signal (the carrier signal).
//
void SetupTimer1()
{
2018-01-23 14:35:52 +08:00
TIM1_ARRH = 0x00; // Reload counter = 51
TIM1_ARRL = 0x33;
TIM1_PSCRH = 0; // Prescalar = 0 (i.e. 1)
TIM1_PSCRL = 0;
//
// Now configure Timer 1, channel 4.
//
TIM1_CCMR4_OC4M = 7; // Set up to use PWM mode 2.
TIM1_CCER2_CC4E = 1; // Output is enabled.
TIM1_CCER2_CC4P = 0; // Active is defined as high.
TIM1_CCR4H = 0x00; // 26 = 50% duty cycle (based on TIM1_ARR).
TIM1_CCR4L = 0x1a;
TIM1_BKR_MOE = 1; // Enable the main output.
}
2018-01-23 14:35:52 +08:00
//--------------------------------------------------------------------------------
//
// Setup the UART to run at 57600 baud, no parity, one stop bit, 8 data bits.
//
// Important: This relies upon the system clock being set to run at 2 MHz.
//
void SetupUART()
{
unsigned char tmp = UARTPORT(SR);
tmp = UARTPORT(DR);
//
// Reset the UART registers to the reset values.
//
UARTPORT(CR1 = 0);
UARTPORT(CR2 = 0);
UARTPORT(CR4 = 0);
UARTPORT(CR3 = 0);
2018-01-24 11:00:46 +08:00
#if defined USE_UART1
2018-01-23 14:35:52 +08:00
UARTPORT(GTR = 0);
UARTPORT(PSCR = 0);
2018-01-24 11:00:46 +08:00
#endif
2018-01-23 14:35:52 +08:00
//
// Now setup the port to 57600,n,8,1.
//
UARTPORT(CR1_M = 0); // 8 Data bits.
UARTPORT(CR1_PCEN = 0); // Disable parity.
UARTPORT(CR3_STOP = 0); // 1 stop bit.
UARTPORT(BRR2 = 0x03); // Set the baud rate registers to 57600 baud
UARTPORT(BRR1 = 0x02); // based upon a 2 MHz system clock.
//
// Disable the transmitter and receiver.
//
UARTPORT(CR2_TEN = 0); // Disable transmit.
UARTPORT(CR2_REN = 0); // Disable receive.
SetupRxBuffer();
//
// Turn on the UART transmit, receive and the UART clock.
//
UARTPORT(CR2_TEN = 1);
UARTPORT(CR2_RIEN = 1);
UARTPORT(CR2_REN = 1);
}
2018-01-23 14:35:52 +08:00
//--------------------------------------------------------------------------------
//
// Main program loop.
//
void main()
{
2018-01-23 14:35:52 +08:00
__disable_interrupt();
_pulseDataAddress = (char *) EEPROM_PULSE_DATA;
_numberOfPulses = *_pulseDataAddress++;
SetupPorts();
SetupUART();
SetupTimer2();
SetupTimer1();
__enable_interrupt();
while (1)
{
2018-01-23 14:35:52 +08:00
__wait_for_interrupt();
}
}