Skip to content

Instantly share code, notes, and snippets.

@olebowle
Last active August 29, 2015 14:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save olebowle/3d1ecbc1adae2e344b38 to your computer and use it in GitHub Desktop.
Save olebowle/3d1ecbc1adae2e344b38 to your computer and use it in GitHub Desktop.
STM32F103C8-010_new
/*
* IR receiver, sender, USB wakeup, motherboard switch wakeup, wakeup timer,
* USB HID device, eeprom emulation
*
* Copyright (C) 2014 Jörg Riechardt
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include "stm32f10x.h"
#include "core_cm3.h"
#include "usb_hid.h"
#include "irmpmain.h"
#include "irsndmain.h"
#include "eeprom.h"
/* uncomment this, if you use a ST-Link */
/*#define ST_Link*/
/*
* only if you want to use CLK and DIO on the blue ST-Link Emulator with mistakenly connected Pins
* WARNING: further firmware updates will become difficult!
* better use TMS and TCK instead, and leave this commented out
*/
/*#define BlueLink*/
#ifdef BlueLink
#define OUT_PORT GPIOA
#define LED_PIN GPIO_Pin_14
#define WAKEUP_PIN GPIO_Pin_13
#else
#define OUT_PORT GPIOB
#define LED_PIN GPIO_Pin_13
#define WAKEUP_PIN GPIO_Pin_14
#endif /* BlueLink */
#define SND_MAX 2
__IO uint8_t PrevXferComplete = 1;
uint8_t PA9_state = 0;
uint8_t buf[HID_OUT_BUFFER_SIZE];
uint16_t VirtAddVarTab[NB_OF_VAR] = { 0x0000, 0x1111, 0x2222, 0x3333, 0x4444, \
0x5555, 0x6666, 0x7777, 0x8888, 0x9999, \
0xAAAA, 0xBBBB, 0xCCCC, 0xDDDD, 0xEEEE};
uint32_t timestamp = 0;
uint32_t AlarmValue = 0xFFFFFFFF;
volatile unsigned int systicks = 0;
volatile unsigned int systicks2 = 0;
void delay_ms(unsigned int msec)
{
systicks = 0;
while (systicks <= msec);
}
void LED_Switch_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
#ifdef BlueLink
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
/* disable SWD, so pins are available */
GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);
#else
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
#endif /* BlueLink */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(OUT_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_Init(OUT_PORT, &GPIO_InitStructure);
}
#ifdef ST_Link
void LED_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* PA9 (red + yellow LED on ST-Link Emus) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void LED_deinit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* PA9 (red + yellow LED) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/* red + yellow fast toggle */
void fast_toggle(void)
{
LED_init();
systicks2 = 0;
while (systicks2 <= 500) {
GPIO_WriteBit(GPIOA, GPIO_Pin_9, Bit_SET);
delay_ms(50);
GPIO_WriteBit(GPIOA, GPIO_Pin_9, Bit_RESET);
delay_ms(50);
}
/* off */
LED_deinit();
PA9_state = 0;
/* red on */
/*GPIO_WriteBit(GPIOA, GPIO_Pin_9, Bit_SET);*/
}
/* red + yellow both on */
void both_on(void)
{
LED_init();
systicks2 = 0;
while (systicks2 <= 500) {
GPIO_WriteBit(GPIOA, GPIO_Pin_9, Bit_SET);
delay_ms(1);
GPIO_WriteBit(GPIOA, GPIO_Pin_9, Bit_RESET);
delay_ms(1);
}
/* red on */
/*GPIO_WriteBit(GPIOA, GPIO_Pin_9, Bit_SET);*/
/* off */
LED_deinit();
}
/* yellow on */
void yellow_on(void)
{
LED_init();
GPIO_WriteBit(GPIOA, GPIO_Pin_9, Bit_RESET);
delay_ms(100);
/* red on */
/*GPIO_WriteBit(GPIOA, GPIO_Pin_9, Bit_SET);*/
/* off */
LED_deinit();
}
#else
void LED_init(void) {}
void LED_deinit(void) {}
void fast_toggle(void) {}
void both_on(void) {}
void yellow_on(void) {}
#endif /* ST_Link */
/* toggle red [/ yellow] and external LED */
void toggle_LED(void)
{
#ifdef ST_Link
if (!PA9_state) {
LED_init();
GPIO_WriteBit(GPIOA, GPIO_Pin_9, Bit_SET);
PA9_state = 1;
} else {
LED_deinit();
PA9_state = 0;
}
/*GPIOA->ODR ^= GPIO_Pin_9;*/
#endif /* ST_Link */
OUT_PORT->ODR ^= LED_PIN;
}
/*
* eeprom: after writing 0xABCD into virtual address 0x6666,
* you have CDAB 6666 in flash 2 halfwords in reverse order, little endian
*/
/* buf[BufIdx ... (BufIdx+5)] -> eeprom[TabNr ... (TabNr+2)] */
void Store_buf_to_Eeprom(uint8_t BufIdx, uint8_t TabNr)
{
/* reverse order */
EE_WriteVariable(VirtAddVarTab[TabNr], ((buf[(BufIdx + 1)] << 8) | (buf[BufIdx])));
EE_WriteVariable(VirtAddVarTab[(TabNr + 1)], ((buf[(BufIdx + 3)] << 8) | (buf[(BufIdx + 2)])));
EE_WriteVariable(VirtAddVarTab[(TabNr + 2)], ((buf[(BufIdx + 5)] << 8) | (buf[(BufIdx + 4)])));
}
/* eeprom[TabNr ... (TabNr+2)] -> buf[0-5] */
void Restore_Eeprom_to_buf(uint8_t TabNr)
{
uint16_t EE_Data;
EE_ReadVariable(VirtAddVarTab[TabNr], &EE_Data);
/* reverse order */
memcpy(&buf[0], &EE_Data, 2);
EE_ReadVariable(VirtAddVarTab[(TabNr + 1)], &EE_Data);
memcpy(&buf[2], &EE_Data, 2);
EE_ReadVariable(VirtAddVarTab[(TabNr + 2)], &EE_Data);
memcpy(&buf[4], &EE_Data, 2);
}
/*
* IRData -> buf[0-5], irmplircd expects dummy as first byte (Report ID),
* so start with buf[0], adapt endianness for irmplircd
*/
void IRData_to_buf(IRMP_DATA *IRData)
{
buf[0] = IRData->protocol;
buf[2] = ((IRData->address) >> 8) & 0xFF;
buf[1] = (IRData->address) & 0xFF;
buf[4] = ((IRData->command) >> 8) & 0xFF;
buf[3] = (IRData->command) & 0xFF;
buf[5] = IRData->flags;
}
/* buf[BufIdx...(BufIdx+5)] -> IRData */
void buf_to_IRData(uint8_t buf[6], uint8_t BufIdx, IRMP_DATA *IRData)
{
IRData->protocol = buf[BufIdx];
IRData->address = ((buf[(BufIdx + 1)] << 8) | (buf[(BufIdx + 2)]));
IRData->command = ((buf[(BufIdx + 3)] << 8) | (buf[(BufIdx + 4)]));
IRData->flags = buf[(BufIdx + 5)];
}
/* buf[0-5] <-> IRData */
uint8_t cmp_buf_IRData(uint8_t buf[6], IRMP_DATA *IRData)
{
return IRData->protocol == buf[0] && \
IRData->address == ((buf[1] << 8) | buf[2]) && \
IRData->command == ((buf[3] << 8) | buf[4]) && \
IRData->flags == buf[5];
}
void Systick_Init(void)
{
/* 1ms */
SysTick_Config((SysCtlClockGet()/1000));
}
void SysTick_Handler(void)
{
static uint16_t i = 0;
systicks++;
systicks2++;
timestamp++;
if (i == 1000) {
if (AlarmValue)
AlarmValue--;
i = 0;
} else {
i++;
}
}
/* Val -> buf[BufIdx...BufIdx+3] */
void uint32_to_buf(uint32_t Val, uint8_t BufIdx)
{
buf[BufIdx] = ((Val) >> 24) & 0xFF;
buf[BufIdx+1] = ((Val) >> 16) & 0xFF;
buf[BufIdx+2] = ((Val) >> 8) & 0xFF;
buf[BufIdx+3] = Val & 0xFF;
}
void Wakeup(void)
{
/* USB wakeup */
/* TODO blockt früher oder später, kein wakeup, ESOF?? */
Resume(RESUME_INTERNAL);
/* motherboard switch: WAKEUP_PIN short high */
GPIO_WriteBit(OUT_PORT, WAKEUP_PIN, Bit_SET);
delay_ms(500);
GPIO_WriteBit(OUT_PORT, WAKEUP_PIN, Bit_RESET);
/* both_on(); */
fast_toggle();
}
int main(void)
{
uint8_t k, wakeup_buf[6], trigger_send_buf[6], send_buf[SND_MAX][6];
IRMP_DATA myIRData, lastIRData, loopIRData, sendIRData;
LED_Switch_init();
LED_init();
/* red LED on */
/*GPIO_WriteBit(GPIOA, GPIO_Pin_9, Bit_SET);*/
USB_HID_Init();
IRMP_Init();
IRSND_Init();
FLASH_Unlock();
EE_Init();
Systick_Init();
/* read wakeup IR-data from eeprom: eeprom[0-2] -> wakeup_buf */
Restore_Eeprom_to_buf(0);
memcpy(wakeup_buf, buf, sizeof(wakeup_buf));
/* read trigger IR-data from eeprom: eeprom[3-5] -> trigger_send_buf */
Restore_Eeprom_to_buf(3);
memcpy(trigger_send_buf, buf, sizeof(trigger_send_buf));
/* read IR-data to send from eeprom: eeprom[6-8] -> send_buf[0], eeprom[9-11] -> send_buf[1], etc */
for (k=0; k<SND_MAX; k++) {
Restore_Eeprom_to_buf(6+k*3);
memcpy(send_buf[k], buf, sizeof(send_buf[k]));
}
while (1) {
if (!AlarmValue)
Wakeup();
/* test if USB is connected to PC, sendtransfer is complete (TODO) and data is received */
if (USB_HID_GetStatus() == CONFIGURED && PrevXferComplete && USB_HID_ReceiveData(buf) == RX_READY) {
if (!(buf[1] == 0xF3 || buf[1] == 0xF4))
memset(buf, 0, sizeof(buf));
switch(buf[1]) {
/* set wakeup IRData */
case 0xFF:
/* buf[2-7] -> eeprom[0-2]*/
Store_buf_to_Eeprom(2, 0);
/* eeprom[0-2] -> buf[0-5] */
Restore_Eeprom_to_buf(0);
memcpy(wakeup_buf, buf, sizeof(wakeup_buf));
break;
/* set trigger_send IRData */
case 0xFE:
/* buf[2-7] -> eeprom[3-5] */
Store_buf_to_Eeprom(2, 3);
/* eeprom[3-5] -> buf[0-5] */
Restore_Eeprom_to_buf(3);
memcpy(trigger_send_buf, buf, sizeof(trigger_send_buf));
break;
/* set send[0] IRData */
case 0xFD:
/* buf[2-7] -> eeprom[6-8] */
Store_buf_to_Eeprom(2, 6);
/* eeprom[6-8] -> buf[0-5] */
Restore_Eeprom_to_buf(6);
memcpy(send_buf[0], buf, sizeof(send_buf[0]));
break;
/* set send[1] IRData */
case 0xFC:
/* buf[2-7] -> eeprom[9-11] */
Store_buf_to_Eeprom(2, 9);
/* eeprom[9-11] -> buf[0-5] */
Restore_Eeprom_to_buf(9);
memcpy(send_buf[1], buf, sizeof(send_buf[1]));
break;
/* get wakeup IRData */
case 0xFB:
memcpy(buf, wakeup_buf, sizeof(wakeup_buf));
break;
/* get trigger_send IRData */
case 0xFA:
memcpy(buf, trigger_send_buf, sizeof(trigger_send_buf));
break;
/* get send[0] IRData */
case 0xF9:
memcpy(buf, send_buf[0], sizeof(send_buf[0]));
break;
/* get send[1] IRData */
case 0xF8:
memcpy(buf, send_buf[1], sizeof(send_buf[1]));
break;
/* IR send command */
case 0xF4:
/* buf[2-7] -> sendIRData */
buf_to_IRData(buf, 2, &sendIRData);
/* 0|1: don't|do wait until send finished */
irsnd_send_data(&sendIRData, 1);
yellow_on();
memset(buf, 0, sizeof(buf));
/* sendIRData -> buf[0-5] */
IRData_to_buf(&sendIRData);
/* timestamp -> buf[6-19] */
uint32_to_buf(timestamp, 6);
break;
/* 4 halfwords in reverse order, little endian */
/* set systick alarm */
case 0xF3:
/* buf[2-5] -> AlarmValue */
AlarmValue = (buf[2]<<24)|(buf[3]<<16)|(buf[4]<<8)|buf[5];
memset(buf, 0, sizeof(buf));
/* AlarmValue -> buf[0-5] */
uint32_to_buf(AlarmValue, 0);
break;
/* get systick alarm */
case 0xF2:
/* AlarmValue -> buf[0-5] */
uint32_to_buf(AlarmValue, 0);
break;
}
/* send (modified) data (for verify) */
USB_HID_SendData(buf, 11);
toggle_LED();
}
/* poll IR-data */
if (irmp_get_data(&myIRData) == TRUE) {
/* new IR-Data? */
/* omit flags */
if (!( myIRData.protocol == lastIRData.protocol && \
myIRData.address == lastIRData.address && \
myIRData.command == lastIRData.command )) {
toggle_LED();
lastIRData.protocol = myIRData.protocol;
lastIRData.address = myIRData.address;
lastIRData.command = myIRData.command;
}
/* wakeup IR-data? */
if (cmp_buf_IRData(wakeup_buf, &myIRData))
Wakeup();
/* trigger send IR-data? */
if (cmp_buf_IRData(trigger_send_buf, &myIRData)) {
for (k=0; k < SND_MAX; k++) {
/* ?? (100 zu wenig, 150, 125 ok) -- RC5 ist 114ms */
delay_ms(115);
/* send_buf[k] -> sendIRData */
buf_to_IRData(send_buf[k], 0, &sendIRData);
/* 0/1: don't/wait until send finished */
irsnd_send_data(&sendIRData, 1);
yellow_on();
/* ?? */
delay_ms(300);
/* receive sent by myself too -- TODO */
if (irmp_get_data(&loopIRData) == TRUE) {
memset(buf, 0, sizeof(buf));
/* loopIRData -> buf[0-5] */
IRData_to_buf(&loopIRData);
/* timestamp -> buf[6-9] */
uint32_to_buf(timestamp, 6);
USB_HID_SendData(buf,11);
}
}
}
/* send IR-data via USB-HID */
memset(buf, 0, sizeof(buf));
/* myIRData -> buf[0-5] */
IRData_to_buf(&myIRData);
/* timestamp -> buf[6-9] */
uint32_to_buf(timestamp, 6);
USB_HID_SendData(buf, 11);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment