Initial port of STM32L100 code
This code was originally written for use with the CooCox IDE back in 2014. It uses ST StdPeriphLib (SPL) as opposed to HAL. I have ported this using the built-in board definition for a board that supports the SPL. After making some small changes (mostly to include paths, but also un-inlining a couple function calls) and removing dead code, it appears to compile cleanly. Actual binary is untested.
This commit is contained in:
parent
1182c9b578
commit
03376cc654
|
@ -0,0 +1,5 @@
|
|||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
"ms-vscode.cpptools-extension-pack"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the usual convention is to give header files names that end with `.h'.
|
||||
It is most portable to use only letters, digits, dashes, and underscores in
|
||||
header file names, and at most one dot.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* pirate.h: half-assed piracy-enabling features for drunken, brazen pirates
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: pirate.h 505 2021-09-05 19:07:51Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_PIRATE_H
|
||||
#define __PIRATE_PIRATE_H
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* cmsis req'd */
|
||||
#include "stm32l1xx_conf.h"
|
||||
|
||||
|
||||
#define PIRATE_PROG_SAVED_MAX 15
|
||||
|
||||
|
||||
/* helper macros */
|
||||
#define sizeof_array(x) sizeof(x) / sizeof(x[0])
|
||||
|
||||
|
||||
/* pirate settings */
|
||||
#define PIRATE_PROG_MATRIX 0
|
||||
#define PIRATE_PROG_BONES 1
|
||||
#define PIRATE_PROG_EYES 2
|
||||
|
||||
|
||||
typedef struct PirateProg {
|
||||
uint8_t type; // bit0 = pattern(high)/program(low), bit1 = always init, bit7 = enabled
|
||||
uint8_t progidx;
|
||||
uint16_t wait;
|
||||
uint16_t level;
|
||||
uint32_t offset;
|
||||
uint32_t option;
|
||||
uint16_t dwell;
|
||||
} PirateProg;
|
||||
|
||||
typedef struct PirateSettings {
|
||||
char name[32];
|
||||
uint8_t fav_color[3];
|
||||
uint8_t beeper;
|
||||
uint8_t beep_type[8];
|
||||
uint8_t contrast;
|
||||
uint8_t autorun;
|
||||
uint8_t led_autoadjust;
|
||||
uint8_t led_autogain_lev_min;
|
||||
uint8_t led_autogain_lev_max;
|
||||
uint8_t led_autothresh[5];
|
||||
uint8_t light_setgain;
|
||||
uint8_t lcd_autobrite;
|
||||
uint8_t lcd_brightness;
|
||||
PirateProg led_prog[3][PIRATE_PROG_SAVED_MAX];
|
||||
uint8_t led_prog_mode;
|
||||
uint16_t mic_cal[2];
|
||||
} PirateSettings;
|
||||
|
||||
extern PirateSettings settings;
|
||||
#define PIRATE_SETTINGS_EEPROM_ADDR (uint32_t)0x8080000
|
||||
|
||||
|
||||
/* misc extras */
|
||||
extern uint8_t temperature;
|
||||
extern int8_t temperature_cal;
|
||||
extern uint8_t light_level;
|
||||
extern uint8_t light_gain;
|
||||
extern uint16_t mic_peak;
|
||||
|
||||
extern uint8_t dc23_nametx;
|
||||
|
||||
|
||||
/* pirate variables */
|
||||
extern uint32_t pirate_prng_val;
|
||||
|
||||
|
||||
/* pirate functions */
|
||||
void pirate_shutdown(uint16_t type);
|
||||
|
||||
uint8_t pirate_prng();
|
||||
void pirate_delay(uint16_t ms);
|
||||
int16_t pirate_scale(int16_t value, int16_t src_min, int16_t src_max, int16_t dest_min, int16_t dest_max);
|
||||
char * pirate_itoa(uint32_t val, uint8_t base, uint8_t leftpad);
|
||||
char * pirate_sitoa(int32_t val, uint8_t base, uint8_t leftpad);
|
||||
|
||||
uint16_t pirate_batt_voltage();
|
||||
void pirate_batt_log(uint16_t rawvalue);
|
||||
|
||||
uint16_t pirate_thermometer(uint8_t deg_f);
|
||||
void pirate_thermometer_log(uint8_t temp);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file USART/USART_TwoBoards/DataExchangeDMA/stm32l1xx_conf.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.2.0
|
||||
* @date 16-May-2014
|
||||
* @brief Library configuration file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __STM32L1xx_CONF_H
|
||||
#define __STM32L1xx_CONF_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Uncomment/Comment the line below to enable/disable peripheral header file inclusion */
|
||||
#include "stm32l1xx_adc.h"
|
||||
//#include "stm32l1xx_aes.h"
|
||||
//#include "stm32l1xx_comp.h"
|
||||
#include "stm32l1xx_crc.h"
|
||||
#include "stm32l1xx_dac.h"
|
||||
//#include "stm32l1xx_dbgmcu.h"
|
||||
#include "stm32l1xx_dma.h"
|
||||
#include "stm32l1xx_exti.h"
|
||||
#include "stm32l1xx_flash.h"
|
||||
//#include "stm32l1xx_fsmc.h"
|
||||
#include "stm32l1xx_gpio.h"
|
||||
#include "stm32l1xx_i2c.h"
|
||||
//#include "stm32l1xx_iwdg.h"
|
||||
//#include "stm32l1xx_lcd.h"
|
||||
//#include "stm32l1xx_opamp.h"
|
||||
#include "stm32l1xx_pwr.h"
|
||||
#include "stm32l1xx_rcc.h"
|
||||
//#include "stm32l1xx_rtc.h"
|
||||
//#include "stm32l1xx_sdio.h"
|
||||
#include "stm32l1xx_spi.h"
|
||||
#include "stm32l1xx_syscfg.h"
|
||||
#include "stm32l1xx_tim.h"
|
||||
#include "stm32l1xx_usart.h"
|
||||
//#include "stm32l1xx_wwdg.h"
|
||||
#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Uncomment the line below to expanse the "assert_param" macro in the
|
||||
Standard Peripheral Library drivers code */
|
||||
/* #define USE_FULL_ASSERT 1 */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
#ifdef USE_FULL_ASSERT
|
||||
|
||||
/**
|
||||
* @brief The assert_param macro is used for function's parameters check.
|
||||
* @param expr: If expr is false, it calls assert_failed function which reports
|
||||
* the name of the source file and the source line number of the call
|
||||
* that failed. If expr is true, it returns no value.
|
||||
* @retval None
|
||||
*/
|
||||
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void assert_failed(uint8_t* file, uint32_t line);
|
||||
#else
|
||||
#define assert_param(expr) ((void)0)
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
#endif /* __STM32L1xx_CONF_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file ADC/ADC1_AnalogWatchdog/stm32l1xx_it.h
|
||||
* @author MCD Application Team
|
||||
* @version V1.2.2
|
||||
* @date 17-November-2021
|
||||
* @brief This file contains the headers of the interrupt handlers.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2015 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __STM32L1xx_IT_H
|
||||
#define __STM32L1xx_IT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32l1xx.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
void NMI_Handler(void);
|
||||
void HardFault_Handler(void);
|
||||
void MemManage_Handler(void);
|
||||
void BusFault_Handler(void);
|
||||
void UsageFault_Handler(void);
|
||||
void SVC_Handler(void);
|
||||
void DebugMon_Handler(void);
|
||||
void PendSV_Handler(void);
|
||||
void SysTick_Handler(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __STM32L1xx_IT_H */
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_conf.h
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 21-January-2013
|
||||
* @brief Virtual COM Port Demo configuration header
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USB_CONF_H
|
||||
#define __USB_CONF_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
/* External variables --------------------------------------------------------*/
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/* EP_NUM */
|
||||
/* defines how many endpoints are used by the device */
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
#define EP_NUM (4)
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/* -------------- Buffer Description Table -----------------*/
|
||||
/*-------------------------------------------------------------*/
|
||||
/* buffer table base address */
|
||||
/* buffer table base address */
|
||||
#define BTABLE_ADDRESS (0x00)
|
||||
|
||||
/* EP0 */
|
||||
/* rx/tx buffer base address */
|
||||
#define ENDP0_RXADDR (0x40)
|
||||
#define ENDP0_TXADDR (0x80)
|
||||
|
||||
/* EP1 */
|
||||
/* tx buffer base address */
|
||||
#define ENDP1_TXADDR (0xC0)
|
||||
#define ENDP2_TXADDR (0x100)
|
||||
#define ENDP3_RXADDR (0x110)
|
||||
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/* ------------------- ISTR events -------------------------*/
|
||||
/*-------------------------------------------------------------*/
|
||||
/* IMR_MSK */
|
||||
/* mask defining which events has to be handled */
|
||||
/* by the device application software */
|
||||
// #define IMR_MSK (CNTR_CTRM | CNTR_WKUPM | CNTR_SUSPM | CNTR_ERRM | CNTR_SOFM | CNTR_ESOFM | CNTR_RESETM )
|
||||
#define IMR_MSK (CNTR_CTRM | CNTR_WKUPM | CNTR_ERRM | CNTR_SOFM | CNTR_RESETM)
|
||||
|
||||
/*#define CTR_CALLBACK*/
|
||||
/*#define DOVR_CALLBACK*/
|
||||
/*#define ERR_CALLBACK*/
|
||||
/*#define WKUP_CALLBACK*/
|
||||
/*#define SUSP_CALLBACK*/
|
||||
/*#define RESET_CALLBACK*/
|
||||
#define SOF_CALLBACK
|
||||
/*#define ESOF_CALLBACK*/
|
||||
/* CTR service routines */
|
||||
/* associated to defined endpoints */
|
||||
/*#define EP1_IN_Callback NOP_Process*/
|
||||
#define EP2_IN_Callback NOP_Process
|
||||
#define EP3_IN_Callback NOP_Process
|
||||
#define EP4_IN_Callback NOP_Process
|
||||
#define EP5_IN_Callback NOP_Process
|
||||
#define EP6_IN_Callback NOP_Process
|
||||
#define EP7_IN_Callback NOP_Process
|
||||
|
||||
#define EP1_OUT_Callback NOP_Process
|
||||
#define EP2_OUT_Callback NOP_Process
|
||||
/*#define EP3_OUT_Callback NOP_Process*/
|
||||
#define EP4_OUT_Callback NOP_Process
|
||||
#define EP5_OUT_Callback NOP_Process
|
||||
#define EP6_OUT_Callback NOP_Process
|
||||
#define EP7_OUT_Callback NOP_Process
|
||||
|
||||
#endif /* __USB_CONF_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into executable file.
|
||||
|
||||
The source code of each library should be placed in a an own separate directory
|
||||
("lib/your_library_name/[here are source files]").
|
||||
|
||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
and a contents of `src/main.c`:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
|
@ -0,0 +1,51 @@
|
|||
/* improved reference xxtea implementation */
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define DELTA 0x9e3779b9
|
||||
#define MX ( (((z>>5)^(y<<2))+((y>>3)^(z<<4)))^((sum^y)+(key[(p&3)^e]^z)) );
|
||||
|
||||
/* btea usage:
|
||||
* uint32_t *v is the pointer to the data
|
||||
* int n is word count of v to en/decode. positive to encode, negative to decode
|
||||
* const key[4] is the 128-bit key
|
||||
*/
|
||||
void btea(uint32_t *v, int n, uint32_t const key[4]) {
|
||||
uint32_t y, z, sum;
|
||||
int32_t p, rounds, e;
|
||||
|
||||
if (n > 1) { /* Coding Part */
|
||||
rounds = 6 + 52/n;
|
||||
sum = 0;
|
||||
z = v[n-1];
|
||||
|
||||
do {
|
||||
sum += DELTA;
|
||||
e = (sum >> 2) & 3;
|
||||
for (p = 0; p < n - 1; p++) {
|
||||
y = v[p + 1];
|
||||
z = v[p] += MX;
|
||||
}
|
||||
y = v[0];
|
||||
z = v[n - 1] += MX;
|
||||
} while (--rounds);
|
||||
} else if (n < -1) { /* Decoding Part */
|
||||
n = -n;
|
||||
rounds = 6 + 52/n;
|
||||
sum = rounds * DELTA;
|
||||
y = v[0];
|
||||
|
||||
do {
|
||||
e = (sum >> 2) & 3;
|
||||
for (p = n - 1; p > 0; p--) {
|
||||
z = v[p - 1];
|
||||
y = v[p] -= MX;
|
||||
}
|
||||
z = v[n - 1];
|
||||
y = v[0] -= MX;
|
||||
sum -= DELTA;
|
||||
} while (--rounds);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/* improved reference xxtea implementation */
|
||||
|
||||
|
||||
void btea(uint32_t *v, int n, uint32_t const key[4]);
|
|
@ -0,0 +1,19 @@
|
|||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:wp_dc22_stm32l]
|
||||
platform = ststm32
|
||||
board = disco_l152rb
|
||||
framework = spl
|
||||
|
||||
board_build.mcu = stm32l100rbt6
|
||||
board_build.f_cpu = 32000000L
|
||||
|
||||
build_flags = -DPDLIB_SPI
|
|
@ -0,0 +1,182 @@
|
|||
/**
|
||||
* attiny.c: interface to attiny88's features
|
||||
* 2014 true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: attiny.c 375 2015-07-06 02:52:40Z true $
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* attiny88's I2C address is 0x73 - see led_eyes.h for define
|
||||
*
|
||||
**/
|
||||
|
||||
#include <pirate.h> // for settings
|
||||
|
||||
#include "attiny.h"
|
||||
#include "../interface/i2c.h"
|
||||
#include "../interface/gpio.h"
|
||||
#include "../device/lightsensor.h"
|
||||
|
||||
// led mode
|
||||
static uint8_t led_eyes_mode;
|
||||
|
||||
// led brightness
|
||||
static uint8_t led_level[2][4];
|
||||
|
||||
// led programs
|
||||
#include "../led/led_eyes_prog.h"
|
||||
static void (*led_program)();
|
||||
static void (*led_program_list[])() = {
|
||||
led_prog_candle_flicker,
|
||||
led_prog_candle_flicker_favcolor,
|
||||
led_prog_randflasher,
|
||||
led_prog_mic_spl,
|
||||
led_prog_fader
|
||||
};
|
||||
const char led_eyes_prog_name[LED_EYES_PROG_COUNT][16] = {
|
||||
{"CandleFlicker"},
|
||||
{"Candle+FavColor"},
|
||||
{"RandFlasher"},
|
||||
{"MicSPL"},
|
||||
{"CFader"}
|
||||
};
|
||||
|
||||
|
||||
/* functions */
|
||||
void attiny_write(uint16_t cmd, void *data, uint8_t bytes)
|
||||
{
|
||||
uint8_t cmdlen;
|
||||
uint8_t *d;
|
||||
|
||||
cmdlen = (cmd > 0xff) ? 2 : 1;
|
||||
d = ((uint8_t *)data);
|
||||
|
||||
if (bytes) {
|
||||
I2C_WriteTransfer(ATTINY_I2C_ADDR, d, bytes, cmd, cmdlen);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t attiny_read(uint16_t cmd, uint8_t bytes)
|
||||
{
|
||||
uint8_t cmdlen;
|
||||
uint8_t fb[4] = {0, 0, 0, 0};
|
||||
|
||||
cmdlen = (cmd > 0xff) ? 2 : 1;
|
||||
|
||||
if (bytes && bytes <= 4) {
|
||||
I2C_ReadTransfer(ATTINY_I2C_ADDR, fb, bytes, cmd, cmdlen);
|
||||
}
|
||||
|
||||
return fb[0] | fb[1] << 8 | fb[2] << 16 | fb[3] << 24;
|
||||
}
|
||||
|
||||
uint8_t attiny_read_temp()
|
||||
{
|
||||
return (uint8_t)attiny_read(ATTINY_CMD_READ_TEMP, 1);
|
||||
}
|
||||
|
||||
uint8_t attiny_read_light_level(uint8_t led_idx)
|
||||
{
|
||||
return (uint8_t)attiny_read(ATTINY_CMD_READ_LIGHT + (led_idx & 0x03), 1);
|
||||
}
|
||||
|
||||
void attiny_write_light_sensitivity(uint8_t led, uint8_t sensitivity)
|
||||
{
|
||||
uint8_t buf[2];
|
||||
|
||||
buf[0] = led;
|
||||
buf[1] = sensitivity;
|
||||
|
||||
attiny_write(ATTINY_CMD_LIGHTSENSOR_SENS, buf, 2);
|
||||
}
|
||||
|
||||
void attiny_sleep()
|
||||
{
|
||||
I2C_WriteTransfer(ATTINY_I2C_ADDR, 0, 0, ATTINY_CMD_SLEEP, 1);
|
||||
}
|
||||
|
||||
/* rgbled-related functions */
|
||||
void led_eyes_tx()
|
||||
{
|
||||
uint8_t buf[12];
|
||||
uint16_t scaler;
|
||||
uint8_t i, j;
|
||||
|
||||
// build up the packet
|
||||
i = j = 0;
|
||||
while (i < 12) {
|
||||
buf[i++] = ATTINY_CMD_LED_LEVEL + j;
|
||||
|
||||
scaler = (settings.led_autoadjust & 0x80) ? lightsensor_get_scalerval(LIGHTSENS_SCALED_EYES) : 256;
|
||||
buf[i++] = ((led_level[j >> 2][j % 4]) * scaler) >> 8;
|
||||
if (i == 6) {
|
||||
j = 4;
|
||||
} else {
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
// and send it
|
||||
I2C_WriteTransfer(ATTINY_I2C_ADDR, buf, 12, 0, 0);
|
||||
}
|
||||
|
||||
void led_eyes_set_level(uint8_t idx, uint8_t level)
|
||||
{
|
||||
led_level[idx >> 2][idx & 0x03] = level;
|
||||
}
|
||||
|
||||
void led_eyes_set_mode(uint8_t mode)
|
||||
{
|
||||
led_eyes_mode = mode;
|
||||
}
|
||||
|
||||
void led_eyes_set_program(uint8_t program_idx, uint8_t init,
|
||||
uint16_t wait, uint16_t level, uint32_t offset, uint32_t settings)
|
||||
{
|
||||
// we need to be in program mode
|
||||
led_eyes_set_mode(LED_EYES_MODE_PROGRAM);
|
||||
// update the program pointer
|
||||
led_program = led_program_list[program_idx];
|
||||
|
||||
// set initial program variables
|
||||
led_prog_set_wait = wait;
|
||||
led_prog_set_level = level;
|
||||
led_prog_set_offset = offset;
|
||||
led_prog_set_option = settings;
|
||||
|
||||
// is this a new set? if so, initialize program parameters
|
||||
if (init) {
|
||||
uint8_t i;
|
||||
|
||||
led_prog_wait = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
led_prog_state[i] = 0;
|
||||
led_prog_work[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void led_eyes_mode_update()
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
switch (led_eyes_mode) {
|
||||
case LED_EYES_MODE_PROGRAM: {
|
||||
// if we have a valid program loaded, run it
|
||||
if (led_program != NULL) {
|
||||
led_program();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LED_EYES_MODE_OFF: {
|
||||
led_program = NULL;
|
||||
for (i = 0; i < 4; i++) {
|
||||
led_level[0][i] = 0;
|
||||
led_level[1][i] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* attiny.h: interface to attiny88's RGBLED eyes prototypes
|
||||
* 2014 true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: attiny.h 375 2015-07-06 02:52:40Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_DEV_ATTINY_H
|
||||
#define __PIRATE_DEV_ATTINY_H
|
||||
|
||||
|
||||
|
||||
/* interface */
|
||||
#define ATTINY_I2C_DEV I2C1
|
||||
#define ATTINY_I2C_ADDR 0x73
|
||||
|
||||
// write register commands, last 4 bits = data, >1 packet
|
||||
#define ATTINY_CMD_EXT_CMD 0x10 // pkt = ext command (bit[7:4] must NOT == 0)
|
||||
#define ATTINY_CMD_LED_LEVEL 0x20 // cmd[3:0] = led, pkt = level (0-250)
|
||||
#define ATTINY_CMD_TEMP_CAL 0x30 // pkt = current temperature
|
||||
#define ATTINY_CMD_EEPROM_READ 0x40 // pkt = address, read 1 byte after this command
|
||||
#define ATTINY_CMD_EEPROM_WRITE 0x50 // pkt[0] = address, pkt[1] = data
|
||||
// write register commands, last 4 bits = data, immediate processing 1 packet
|
||||
#define ATTINY_CMD_READ_TEMP 0x80 // read 1 byte after this command
|
||||
#define ATTINY_CMD_READ_LIGHT 0x90 // cmd[3:0] = led (from 0-3), read 1 byte after this command
|
||||
#define ATTINY_CMD_SLEEP 0xF0 // no data
|
||||
// write register commands, extended
|
||||
#define ATTINY_CMD_LIGHTSENSOR_SENS 0x1019 // 2 bytes data - led, new sensitivity value
|
||||
|
||||
|
||||
/* leds */
|
||||
#define LED_EYES_LEFT 0
|
||||
#define LED_EYES_RIGHT 1
|
||||
|
||||
|
||||
/* programs */
|
||||
#define LED_EYES_MODE_OFF 0
|
||||
#define LED_EYES_MODE_PROGRAM 2
|
||||
|
||||
#define LED_EYES_PROG_COUNT 5
|
||||
#define LED_EYES_PTRN_COUNT 0
|
||||
|
||||
|
||||
/* prototypes */
|
||||
void led_eyes_tx();
|
||||
void led_eyes_set_level(uint8_t idx, uint8_t level);
|
||||
|
||||
void led_eyes_mode_update();
|
||||
void led_eyes_set_mode(uint8_t mode); // used for disabling
|
||||
void led_eyes_set_program(uint8_t program_idx, uint8_t init,
|
||||
uint16_t wait, uint16_t level, uint32_t offset, uint32_t settings);
|
||||
|
||||
uint8_t attiny_read_temp();
|
||||
uint8_t attiny_read_light_level(uint8_t led_idx);
|
||||
|
||||
void attiny_write_light_sensitivity(uint8_t led, uint8_t sensitivity);
|
||||
|
||||
void attiny_sleep();
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,118 @@
|
|||
/**
|
||||
* beep.c: beeper fuckin musicality bitches, beep buzz boop
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: beep.c 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* TODO: remove freq lookup table, replace with freq defines by note (A4 = 440 for example)
|
||||
* TODO: let you know that the device we chose cannot play music; it is a buzzer.
|
||||
* TODO: do what you want 'cause a pirate is free
|
||||
**/
|
||||
|
||||
#include <pirate.h>
|
||||
|
||||
#include "beep.h"
|
||||
#include "../interface/gpio.h"
|
||||
|
||||
|
||||
const tGPIO beep_pin = {GPIOA, GPIO_Pin_4, 4};
|
||||
|
||||
uint8_t beep_buf_idx;
|
||||
uint8_t beep_play_idx;
|
||||
uint16_t beep_dur_buf[BEEP_BUF_SIZE];
|
||||
uint16_t beep_lev_buf[BEEP_BUF_SIZE];
|
||||
|
||||
|
||||
/* beeper bullshit */
|
||||
void beep_init()
|
||||
{
|
||||
GPIO_InitTypeDef gpio;
|
||||
|
||||
// set up beeper gpio struct
|
||||
gpio.GPIO_Mode = GPIO_Mode_OUT;
|
||||
gpio.GPIO_OType = GPIO_OType_PP;
|
||||
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
gpio.GPIO_Speed = GPIO_Speed_400KHz;
|
||||
gpio.GPIO_Pin = beep_pin.pin;
|
||||
|
||||
// and set it up
|
||||
GPIO_Init(beep_pin.port, &gpio);
|
||||
|
||||
// reset buffer index
|
||||
beep_buf_idx = 0;
|
||||
}
|
||||
|
||||
void beep_update()
|
||||
{
|
||||
uint16_t duration;
|
||||
uint16_t level;
|
||||
|
||||
// do we have an active tone?
|
||||
if (beep_buf_idx & 0x80) {
|
||||
duration = beep_dur_buf[beep_play_idx];
|
||||
level = beep_lev_buf[beep_play_idx];
|
||||
|
||||
if (duration) {
|
||||
if (level == 0) { // loudest
|
||||
GPIO_SetBits(beep_pin.port, beep_pin.pin);
|
||||
} else if (level == 32) { // silent
|
||||
GPIO_ResetBits(beep_pin.port, beep_pin.pin);
|
||||
} else if (duration % level == 0) { // tones
|
||||
GPIO_SetBits(beep_pin.port, beep_pin.pin);
|
||||
} else {
|
||||
GPIO_ResetBits(beep_pin.port, beep_pin.pin);
|
||||
}
|
||||
|
||||
// count down the times
|
||||
beep_dur_buf[beep_play_idx]--;
|
||||
} else {
|
||||
// stop the tone
|
||||
GPIO_ResetBits(beep_pin.port, beep_pin.pin);
|
||||
|
||||
// move to the next buffer
|
||||
beep_play_idx++;
|
||||
|
||||
// is there any more? need to reset buffer if there isn't any more
|
||||
if (((beep_buf_idx & 0x7f) == beep_play_idx) || beep_play_idx >= BEEP_BUF_SIZE) {
|
||||
// nope, no more
|
||||
beep_buf_idx = 0;
|
||||
beep_play_idx = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* beep control */
|
||||
void beep_clear_queue()
|
||||
{
|
||||
beep_buf_idx = 0;
|
||||
GPIO_ResetBits(beep_pin.port, beep_pin.pin);
|
||||
}
|
||||
|
||||
uint16_t beep(uint16_t tone_id, uint16_t duration)
|
||||
{
|
||||
if ((beep_buf_idx & 0x7f) < BEEP_BUF_SIZE) {
|
||||
// if not in use, reset the playback index
|
||||
if (beep_buf_idx == 0) {
|
||||
beep_play_idx = 0;
|
||||
}
|
||||
|
||||
// mark the beeper as being used
|
||||
beep_buf_idx |= 0x80;
|
||||
|
||||
// set the desired tone and duration
|
||||
beep_lev_buf[beep_buf_idx & 0x7f] = (tone_id < 32) ? 32 - tone_id : 0;
|
||||
beep_dur_buf[beep_buf_idx & 0x7f] = duration * 5;
|
||||
|
||||
// prepare for the next buffer location
|
||||
beep_buf_idx++;
|
||||
|
||||
return (beep_buf_idx & 0x7f);
|
||||
}
|
||||
|
||||
return 0xff;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* beep.h: beeper fuckin musicality bitches
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: beep.h 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
* do what you want 'cause a pirate is free
|
||||
* you are a pirate
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_DEV_BEEP_H
|
||||
#define __PIRATE_DEV_BEEP_H
|
||||
|
||||
|
||||
|
||||
/* constants */
|
||||
#define BEEP_BUF_SIZE 8 // max 127
|
||||
|
||||
|
||||
/* prototypes */
|
||||
void beep_init();
|
||||
void beep_update();
|
||||
|
||||
void beep_clear_queue();
|
||||
uint16_t beep(uint16_t tone_id, uint16_t duration);
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* beep_music.h: musical scores for pirates
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: beep_song.h 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
static MusicSong you_are_a_pirate[] = {
|
||||
{5, NOTE_E, 200},
|
||||
{5, NOTE_C, 200},
|
||||
{5, NOTE_C, 200},
|
||||
{5, NOTE_C, 200},
|
||||
{4, NOTE_G, 200},
|
||||
{4, NOTE_A, 200},
|
||||
{5, NOTE_C, 200},
|
||||
{4, NOTE_B, 200},
|
||||
{4, NOTE_D, 200},
|
||||
{4, NOTE_A, 250},
|
||||
{0, NOTE_NONE, 350},
|
||||
{4, NOTE_G, 600},
|
||||
{5, NOTE_C, 600},
|
||||
{5, NOTE_C, 200},
|
||||
{5, NOTE_D, 360},
|
||||
{4, NOTE_A, 360}
|
||||
};
|
||||
|
||||
static MusicPlaylist you_are_a_pirate_s = {you_are_a_pirate, 16};
|
|
@ -0,0 +1,225 @@
|
|||
/**
|
||||
* lcd.c: lcd menuing and support functions
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: lcd.c 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#include <pirate.h>
|
||||
|
||||
#include "lcd.h"
|
||||
|
||||
#include "../interface/i2c.h"
|
||||
#include "../interface/gpio.h"
|
||||
|
||||
|
||||
// led backlight
|
||||
uint16_t lcd_led_level = 0;
|
||||
uint16_t lcd_led_level_set = 0;
|
||||
uint8_t lcd_led_rate;
|
||||
uint8_t lcd_led_upd;
|
||||
|
||||
// lcd control
|
||||
uint8_t lcd_height;
|
||||
uint8_t lcd_cursor_pos;
|
||||
uint8_t lcd_cursor_type;
|
||||
uint8_t (*lcd_cgram)[8];
|
||||
uint8_t lcd_cgram_len;
|
||||
|
||||
// lcd display
|
||||
char lcd_line[2][9];
|
||||
|
||||
// lcd hardware
|
||||
const tGPIO lcd_led_pin = {GPIOA, GPIO_Pin_6, 6};
|
||||
|
||||
|
||||
/* functions */
|
||||
void lcd_init()
|
||||
{
|
||||
static const uint8_t cmd_init[] = {
|
||||
0x38, // set to i2c
|
||||
0x39, // set to i2c
|
||||
0x1d, // 1/4 bias, osc ~220hz
|
||||
0x78, // contrast low 4 bits
|
||||
0x5d, // icon enable, voltage boost enable, contrast high 2 bits
|
||||
0x6d, // internal follower enable,
|
||||
0x0c, // display on
|
||||
0x01, // clear display
|
||||
0x06 //
|
||||
};
|
||||
|
||||
uint8_t *cmdptr = (uint8_t *)cmd_init;
|
||||
|
||||
I2C_WriteTransfer(LCD_I2C_ADDR, cmdptr, 9, LCD_CMD, 1);
|
||||
|
||||
// set stored contrast
|
||||
lcd_set_contrast(settings.contrast);
|
||||
}
|
||||
|
||||
void lcd_led_init()
|
||||
{
|
||||
TIM_TimeBaseInitTypeDef tim_tb;
|
||||
TIM_OCInitTypeDef tim_oc;
|
||||
GPIO_InitTypeDef gpio;
|
||||
|
||||
// enable clocks
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10, ENABLE);
|
||||
|
||||
// set up with 250 levels of brightness, with a bit of empty
|
||||
tim_tb.TIM_Prescaler = 5 - 1; // 6.4MHz
|
||||
tim_tb.TIM_Period = 320 - 1; // 25KHz PWM
|
||||
tim_tb.TIM_ClockDivision = 0;
|
||||
tim_tb.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_TimeBaseInit(LCD_LED_TIMER, &tim_tb);
|
||||
|
||||
// configure outputs as pwm
|
||||
tim_oc.TIM_OCMode = TIM_OCMode_PWM1;
|
||||
tim_oc.TIM_OutputState = TIM_OutputState_Enable;
|
||||
tim_oc.TIM_Pulse = 0;
|
||||
tim_oc.TIM_OCPolarity = LCD_LED_OC_POLARITY;
|
||||
TIM_OC1Init(LCD_LED_TIMER, &tim_oc);
|
||||
TIM_OC1PreloadConfig(LCD_LED_TIMER, TIM_OCPreload_Enable);
|
||||
|
||||
TIM_ARRPreloadConfig(LCD_LED_TIMER, ENABLE);
|
||||
TIM_Cmd(LCD_LED_TIMER, ENABLE);
|
||||
|
||||
// configure output pin as timer AF
|
||||
GPIO_StructInit(&gpio);
|
||||
gpio.GPIO_Mode = GPIO_Mode_AF;
|
||||
gpio.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
gpio.GPIO_Pin = lcd_led_pin.pin;
|
||||
GPIO_Init(lcd_led_pin.port, &gpio);
|
||||
|
||||
GPIO_PinAFConfig(lcd_led_pin.port, lcd_led_pin.pinsource, GPIO_AF_TIM10);
|
||||
}
|
||||
|
||||
void lcd_print(uint8_t pos, uint8_t *msg, uint8_t msg_len)
|
||||
{
|
||||
uint8_t len;
|
||||
|
||||
// which line/pos to print to?
|
||||
I2C_WriteTransfer(LCD_I2C_ADDR, &pos, 1, LCD_CMD, 1);
|
||||
|
||||
// length to print
|
||||
len = msg_len < LCD_MAX_LINE_LENGTH ? msg_len : LCD_MAX_LINE_LENGTH;
|
||||
|
||||
// send it
|
||||
I2C_WriteTransfer(LCD_I2C_ADDR, msg, len, LCD_DATA, 1);
|
||||
}
|
||||
|
||||
void lcd_linebuf_send()
|
||||
{
|
||||
lcd_print(LCD_LINE_1, (uint8_t *)lcd_line[0], 8);
|
||||
|
||||
if (lcd_get_height() != LCD_CMD_DOUBLEHEIGHT) {
|
||||
lcd_print(LCD_LINE_2, (uint8_t *)lcd_line[1], 8);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void lcd_cmd(uint8_t cmd)
|
||||
{
|
||||
I2C_WriteTransfer(LCD_I2C_ADDR, &cmd, 1, LCD_CMD, 1);
|
||||
// pirate_delay(1);
|
||||
}
|
||||
|
||||
void lcd_set_contrast(uint8_t level) {
|
||||
settings.contrast = level & 0x3f;
|
||||
}
|
||||
|
||||
void lcd_apply_contrast()
|
||||
{
|
||||
// contrast is 6 bits; can be between 0 and 63
|
||||
uint8_t cmd[2] = {0};
|
||||
|
||||
// form command
|
||||
cmd[0] = 0x5c | (settings.contrast >> 4);
|
||||
cmd[1] = 0x70 | (settings.contrast & 0x0f);
|
||||
|
||||
I2C_WriteTransfer(LCD_I2C_ADDR, cmd, 2, LCD_CMD, 1);
|
||||
}
|
||||
|
||||
void lcd_set_height(uint8_t height)
|
||||
{
|
||||
if (height)
|
||||
lcd_height = height;
|
||||
}
|
||||
|
||||
uint8_t lcd_get_height()
|
||||
{
|
||||
return lcd_height;
|
||||
}
|
||||
|
||||
void lcd_set_cursor(uint8_t pos, uint8_t type)
|
||||
{
|
||||
if (pos)
|
||||
lcd_cursor_pos = pos;
|
||||
|
||||
if (type)
|
||||
lcd_cursor_type = type;
|
||||
}
|
||||
|
||||
uint8_t lcd_get_cursor_pos()
|
||||
{
|
||||
return lcd_cursor_pos;
|
||||
}
|
||||
|
||||
uint8_t lcd_get_cursor_type()
|
||||
{
|
||||
return lcd_cursor_type;
|
||||
}
|
||||
|
||||
void lcd_set_cgram_load(const uint8_t (*cgram)[8], const uint8_t len)
|
||||
{
|
||||
lcd_cgram = (uint8_t (*)[8])cgram;
|
||||
lcd_cgram_len = (uint8_t)len;
|
||||
}
|
||||
|
||||
void lcd_led_set_level(uint8_t level, uint8_t ramp_speed)
|
||||
{
|
||||
lcd_led_level_set = level;
|
||||
lcd_led_rate = ramp_speed;
|
||||
lcd_led_upd = LCD_LED_UPD_RATE;
|
||||
|
||||
// force an update now
|
||||
lcd_led_update();
|
||||
}
|
||||
|
||||
void lcd_led_update()
|
||||
{
|
||||
if (lcd_led_upd) {
|
||||
lcd_led_upd--;
|
||||
if (!lcd_led_upd) {
|
||||
// are we done?
|
||||
if (lcd_led_level == lcd_led_level_set) {
|
||||
return;
|
||||
}
|
||||
// nope, check and see if we are increasing level
|
||||
if (lcd_led_level_set > lcd_led_level) {
|
||||
lcd_led_level += lcd_led_rate;
|
||||
// level higher than target? then force to target
|
||||
if (lcd_led_level > lcd_led_level_set) {
|
||||
lcd_led_level = lcd_led_level_set;
|
||||
}
|
||||
}
|
||||
// nope, check and see if we are decreasing level
|
||||
if (lcd_led_level_set < lcd_led_level) {
|
||||
// rate lower than target? if so, force to target
|
||||
if ((lcd_led_level - lcd_led_level_set) > lcd_led_rate) {
|
||||
lcd_led_level = lcd_led_level_set;
|
||||
} else {
|
||||
lcd_led_level -= lcd_led_rate;
|
||||
}
|
||||
}
|
||||
|
||||
// set OC
|
||||
LCD_LED_TIMER->CCR1 = lcd_led_level;
|
||||
|
||||
// and reset countdown timer
|
||||
lcd_led_upd = LCD_LED_UPD_RATE;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* lcd.c: lcd menuing and support function prototypes
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: lcd.h 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_DEV_LCD_H
|
||||
#define __PIRATE_DEV_LCD_H
|
||||
|
||||
|
||||
|
||||
#define LCD_I2C_DEV I2C1
|
||||
#define LCD_I2C_ADDR 0x3e
|
||||
|
||||
#define LCD_MAX_LINE_LENGTH 8 // we use an 8x2 LCD in this project
|
||||
|
||||
#define LCD_LED_TIMER TIM10
|
||||
#define LCD_LED_OC_POLARITY TIM_OCPolarity_High
|
||||
#define LCD_LED_UPD_RATE 100 // updates every 5000/100 = 50ms update rate
|
||||
|
||||
#define LCD_LINE_1 0x80
|
||||
#define LCD_LINE_2 0xc0
|
||||
|
||||
#define LCD_CMD 0x00
|
||||
#define LCD_DATA 0x40
|
||||
|
||||
#define LCD_CMD_CLEAR_SCREEN 0x01
|
||||
#define LCD_CMD_SINGLEHEIGHT 0x39
|
||||
#define LCD_CMD_DOUBLEHEIGHT 0x35
|
||||
#define LCD_CMD_NO_CURSOR_FLASH 0x0c
|
||||
#define LCD_CMD_CURSOR_FLASH 0x0d
|
||||
#define LCD_CMD_CURSOR_UNDER 0x0e
|
||||
#define LCD_CMD_CURSOR_UNDER_FLASH 0x0f
|
||||
|
||||
|
||||
/* variables */
|
||||
extern char lcd_line[2][9];
|
||||
|
||||
extern uint8_t (*lcd_cgram)[8];
|
||||
extern uint8_t lcd_cgram_len;
|
||||
|
||||
|
||||
/* prototypes */
|
||||
void lcd_init();
|
||||
void lcd_led_init();
|
||||
|
||||
void lcd_cmd(uint8_t command);
|
||||
void lcd_print(uint8_t pos, uint8_t *msg, uint8_t msg_len);
|
||||
void lcd_linebuf_send();
|
||||
|
||||
void lcd_set_contrast(uint8_t level);
|
||||
void lcd_apply_contrast();
|
||||
|
||||
void lcd_set_height(uint8_t height);
|
||||
uint8_t lcd_get_height();
|
||||
|
||||
void lcd_set_cursor(uint8_t pos, uint8_t type);
|
||||
uint8_t lcd_get_cursor_pos();
|
||||
uint8_t lcd_get_cursor_type();
|
||||
|
||||
void lcd_set_cgram_load(const uint8_t (*cgram)[8], const uint8_t len);
|
||||
|
||||
void lcd_led_set_level(uint8_t level, uint8_t ramp_speed);
|
||||
void lcd_led_update();
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,110 @@
|
|||
/**
|
||||
* lightsensor.c: control of the attiny's light sensor output plus helper functions
|
||||
* 2014 true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: lightsensor.c 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#include <pirate.h>
|
||||
|
||||
#include "lightsensor.h"
|
||||
#include "attiny.h"
|
||||
|
||||
|
||||
// light variables
|
||||
uint8_t light_level;
|
||||
uint8_t light_gain;
|
||||
|
||||
static uint8_t wait = 0;
|
||||
|
||||
// target brightness
|
||||
// TODO: make this adjustable?
|
||||
static uint8_t lev_target[5][5] = {
|
||||
{0x00, 0xff, 0xe0, 0x55, 0x0d}, // skull (white)
|
||||
{0x00, 0x38, 0xff, 0xff, 0xff}, // skull (purple)
|
||||
{0x00, 0xff, 0xe0, 0x55, 0x0d}, // bones
|
||||
{0xff, 0xff, 0xf0, 0xe0, 0xc0}, // eyes
|
||||
{0x00, 0xff, 0xe0, 0x55, 0x14} // backlight
|
||||
};
|
||||
|
||||
static uint8_t lev_set[5];
|
||||
|
||||
|
||||
/* functions */
|
||||
// gain
|
||||
uint8_t lightsensor_gainvalue_update()
|
||||
{
|
||||
if (light_level <= settings.led_autogain_lev_min) {
|
||||
if (light_gain > LIGHTSENS_GAIN_MIN) {
|
||||
light_gain--;
|
||||
return 1;
|
||||
}
|
||||
} else if (light_level >= settings.led_autogain_lev_max) {
|
||||
if (light_gain < LIGHTSENS_GAIN_MAX) {
|
||||
light_gain++;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// scaling
|
||||
void lightsensor_scale_level(uint8_t idx)
|
||||
{
|
||||
int16_t scaled = 0;
|
||||
uint8_t i = 5;
|
||||
|
||||
if (light_gain) {
|
||||
if (light_gain == settings.led_autothresh[0]) {
|
||||
scaled = lev_target[idx][0];
|
||||
i = 1;
|
||||
} else {
|
||||
for (i = 1; i < 5; i++) {
|
||||
if (light_gain <= settings.led_autothresh[i]) {
|
||||
scaled = pirate_scale(light_gain,
|
||||
settings.led_autothresh[i - 1],
|
||||
settings.led_autothresh[i],
|
||||
lev_target[idx][i - 1],
|
||||
lev_target[idx][i]);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i < 5) {
|
||||
if (lev_set[idx] > scaled) {
|
||||
lev_set[idx]--;
|
||||
} else if (lev_set[idx] < scaled) {
|
||||
lev_set[idx]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lightsensor_scaler_update()
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!wait) {
|
||||
wait = settings.led_autoadjust & 0x7f;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
lightsensor_scale_level(i);
|
||||
}
|
||||
|
||||
// if the scaling speed isn't set, set it fast
|
||||
if (!wait) wait = 1;
|
||||
}
|
||||
|
||||
wait--;
|
||||
}
|
||||
|
||||
uint8_t lightsensor_get_scalerval(uint8_t which)
|
||||
{
|
||||
if (which <= LIGHTSENS_SCALED_BACKLIGHT) return lev_set[which]; else return 0;
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* lightsensor.h: control of the attiny's light sensor output plus helper functions
|
||||
* 2014 true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: lightsensor.h 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
|
||||
#ifndef __PIRATE_DEV_LIGHTSENSOR_H
|
||||
#define __PIRATE_DEV_LIGHTSENSOR_H
|
||||
|
||||
|
||||
|
||||
extern uint8_t light_level;
|
||||
extern uint8_t light_gain;
|
||||
|
||||
|
||||
#define LIGHTSENS_GAIN_MIN 1 // brightest
|
||||
#define LIGHTSENS_GAIN_MAX 64 // darkest
|
||||
|
||||
#define LIGHTSENS_AUTOGAIN_LEVEL_MIN 108 // threshold levels for gain
|
||||
#define LIGHTSENS_AUTOGAIN_LEVEL_MAX 114 // should be a range of ~6-10
|
||||
|
||||
#define LIGHTSENS_THRESH_DAY 1
|
||||
#define LIGHTSENS_THRESH_TOP_BRIGHT 4
|
||||
#define LIGHTSENS_THRESH_TOP_NORM 30
|
||||
#define LIGHTSENS_THRESH_TOP_DIM 48
|
||||
#define LIGHTSENS_THRESH_TOP_DARK 64
|
||||
|
||||
#define LIGHTSENS_SCALED_SKULL_WHT 0
|
||||
#define LIGHTSENS_SCALED_SKULL_PUR 1
|
||||
#define LIGHTSENS_SCALED_BONES 2
|
||||
#define LIGHTSENS_SCALED_EYES 3
|
||||
#define LIGHTSENS_SCALED_BACKLIGHT 4
|
||||
|
||||
|
||||
/* prototypes */
|
||||
uint8_t lightsensor_gainvalue_update();
|
||||
|
||||
void lightsensor_scaler_update();
|
||||
uint8_t lightsensor_get_scalerval(uint8_t which);
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* radio/address.c: address buffers and lookups
|
||||
* 2015 by true
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
**/
|
||||
|
||||
static char dc22_name[32][8];
|
||||
static char dc23_name[300][3];
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* radio/address.h: address buffers and lookups
|
||||
* 2015 by true
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
**/
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* radio/irq.c: nrf irq handler
|
||||
* 2015 by true
|
||||
|
||||
* ----
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
**/
|
||||
|
||||
#include <pirate.h>
|
||||
#include "nrf.h"
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
/**
|
||||
* radio/nrf.c: interface to radiowaves
|
||||
* 2015 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* This is a nasty hack implementation of the NRF24L01+.
|
||||
* Modify as necessary if using on another STM32; see nrf.h
|
||||
* and the NRF24L01 library.
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: nrf.c 375 2015-07-06 02:52:40Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#include <pirate.h>
|
||||
#include "nrf.h"
|
||||
|
||||
|
||||
/* variables */
|
||||
// general radio
|
||||
uint8_t nrf_detected;
|
||||
uint8_t nrf_myaddr;
|
||||
|
||||
static uint8_t nrf_tx_addr[5] = {0x00, '8', 'r', 'i', 'P'};
|
||||
uint8_t nrf_tx_buf[NRF_PAYLOAD_LEN];
|
||||
|
||||
static uint8_t nrf_rx_addr_p0[5] = {0x00, '8', 'r', 'i', 'P'};
|
||||
static uint8_t nrf_rx_addr_p1[5] = {0x01, '8', 'r', 'i', 'P'};
|
||||
|
||||
|
||||
// pingpong
|
||||
uint8_t nrf_last_ping_id; // sender's last byte
|
||||
uint8_t nrf_last_ping_idx; // index byte
|
||||
|
||||
|
||||
// encryption
|
||||
static uint32_t xxtea_key[2][4];
|
||||
static uint8_t xxtea_key_done[2];
|
||||
|
||||
|
||||
/* functions */
|
||||
uint8_t nrf_checksum(uint8_t *data, uint8_t len, int32_t offset) {
|
||||
int32_t ret = 0;
|
||||
|
||||
while (len) {
|
||||
ret += *data++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return (ret + offset);
|
||||
}
|
||||
|
||||
void nrf_process_data(uint8_t pipe, uint8_t *pBuf, uint8_t len)
|
||||
{
|
||||
int32_t w = 0;
|
||||
|
||||
if (len != NRF_PAYLOAD_LEN) return;
|
||||
|
||||
// first see if there are any unencrypted commands
|
||||
// TODO: verify checksum to see if packet is valid
|
||||
switch (pBuf[0]) {
|
||||
case NRF_CMD_GETKEY: {
|
||||
// check to see if the message is formatted correctly
|
||||
// we will oblige and send out the keys we have
|
||||
// TODO: send key
|
||||
break;
|
||||
}
|
||||
case NRF_CMD_SETKEY: {
|
||||
// check to see if the message is formatted correctly
|
||||
// we are a DC22 badge, so we have the keys already
|
||||
break;
|
||||
}
|
||||
|
||||
case NRF_CMD_PING: {
|
||||
// get received address for this packet
|
||||
nrf_last_ping_id = pipe;
|
||||
|
||||
// and pull the index
|
||||
nrf_last_ping_idx = pBuf[2];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// decode with dc22 public key and see if checksum matches
|
||||
if (xxtea_key_done[0]) {
|
||||
btea((uint32_t *)pBuf, -2, xxtea_key[0]);
|
||||
if (!nrf_checksum(pBuf, 7, pBuf[7])) {
|
||||
w = 22;
|
||||
}
|
||||
}
|
||||
|
||||
// decode with dc22 shared key and see if it matches
|
||||
if (xxtea_key_done[1] && !w) {
|
||||
btea((uint32_t *)pBuf, -2, xxtea_key[1]);
|
||||
if (!nrf_checksum(pBuf, 7, pBuf[7])) {
|
||||
w = 23;
|
||||
}
|
||||
}
|
||||
|
||||
// try to process this data
|
||||
if (w) {
|
||||
// yes, we can
|
||||
// TODO: process radio data
|
||||
switch (pBuf[0]) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nrf_init()
|
||||
{
|
||||
// initialize nRF24 library
|
||||
nRF24_init(SystemCoreClock);
|
||||
// clear any pending interrupts, we don't give a shit about them
|
||||
nRF24_clear_irq_flags();
|
||||
|
||||
// set nrf data callbacks
|
||||
nRF24_rx_cb = nrf_process_data;
|
||||
|
||||
|
||||
nrf_myaddr = *(uint8_t *)NRF_MYADDR_EEPROM;
|
||||
|
||||
nrf_detected = 0;
|
||||
if (nRF24_is_present()) {
|
||||
nrf_detected = 1;
|
||||
}
|
||||
|
||||
// and finally, configure the radio and turn it on in listen mode
|
||||
nRF24_set_payload_size(0, NRF_PAYLOAD_LEN);
|
||||
nRF24_set_payload_size(1, NRF_PAYLOAD_LEN);
|
||||
nRF24_set_autoack(1, 0); // no autoack on general receive pipe
|
||||
nRF24_set_dynack(1); // allows us to NO_ACK packets
|
||||
nRF24_update_config(_TRNRF_UPDATE_ALL);
|
||||
|
||||
nRF24_set_txaddr(nrf_tx_addr);
|
||||
nRF24_set_rxaddr(0, nrf_rx_addr_p0);
|
||||
nRF24_set_rxaddr(1, nrf_rx_addr_p1);
|
||||
|
||||
nRF24_mode_rx();
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* radio/nrf.h: interface to radiowaves prototypes
|
||||
* 2015 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: nrf.h 505 2021-09-05 19:07:51Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_DEV_NRF24L01_H
|
||||
#define __PIRATE_DEV_NRF24L01_H
|
||||
|
||||
|
||||
/* libraries */
|
||||
#include "nrf24l01/true_nRF24L01.h"
|
||||
#include <xxtea.h>
|
||||
|
||||
|
||||
/* defines */
|
||||
#define NRF_PAYLOAD_LEN 8 // 1 byte command, 1 byte class, 1 byte byte index, 4 bytes data, 1 byte checksum
|
||||
#define NRF_MYADDR_EEPROM (uint32_t)0x080807fc // 4 bytes, only using highest byte right now
|
||||
|
||||
|
||||
/* commands (main channel) */
|
||||
#define NRF_CMD_GETKEY 0x00 // TODO: devices query for a key until they get one
|
||||
#define NRF_CMD_SETKEY 0x01 // TODO: sends a key for devices to use
|
||||
#define NRF_CMD_REQ_SUBADDR 0x08 // TODO: asks for subaddress in use
|
||||
#define NRF_CMD_PAGEDC22 0x19 // TODO: pages a dc22-style badge, index is block num, 3 blocks to send, 8 char name, 4 char nonce. index >=0x80 = direct
|
||||
#define NRF_CMD_PAGEDC23 0x1a // TODO: pages a dc23-style badge, index is block num, 2 blocks to send, 3 char name, 4 char nonce. index >=0x80 = direct
|
||||
#define NRF_CMD_MUSICNOTES 0x40 // TODO: queues and plays the desired music notes. 2 bytes per note, one for note to play (or start play cmd), one for duration of note
|
||||
#define NRF_CMD_MUSICLIBRARY 0x42 // TODO: queues playing a song from the music library. if index = 0xff, badges will repeat with countdown information.
|
||||
#define NRF_CMD_ANIMATION 0x8D
|
||||
#define NRF_CMD_DC22_23GREET 0x8F
|
||||
#define NRF_CMD_PING 0x91 // TODO: sends ping. dest waits the amount of milliseconds of its ID times two before responding. index is this badge's P1
|
||||
#define NRF_CMD_PONG 0x92 // TODO: reply sent to target in response to ping. sends to P1 as specified in ping.
|
||||
|
||||
|
||||
/* variables */
|
||||
extern uint8_t nrf_detected;
|
||||
extern uint8_t nrf_myaddr;
|
||||
|
||||
extern uint8_t nrf_tx_buf[NRF_PAYLOAD_LEN];
|
||||
|
||||
extern uint8_t nrf_last_ping_id; // sender's last byte
|
||||
extern uint8_t nrf_last_ping_idx; // index byte
|
||||
|
||||
|
||||
/* prototypes */
|
||||
void nrf_init();
|
||||
uint8_t nrf_checksum(uint8_t *data, uint8_t len, int32_t offset);
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,186 @@
|
|||
/* nRF24L01.h
|
||||
* Register definitions for manipulating the Nordic Semiconductor
|
||||
* nRF24L01+ RF transceiver chipsets.
|
||||
*
|
||||
|
||||
Copyright (c) 2007 Stefan Engelke <mbox@stefanengelke.de>
|
||||
Some parts copyright (c) 2012 Eric Brundick <spirilis [at] linux dot com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef _NRF24L01_H
|
||||
#define _NRF24L01_H
|
||||
|
||||
|
||||
#define NRF_BIT0 1 << 0
|
||||
#define NRF_BIT1 1 << 1
|
||||
#define NRF_BIT2 1 << 2
|
||||
#define NRF_BIT3 1 << 3
|
||||
#define NRF_BIT4 1 << 4
|
||||
#define NRF_BIT5 1 << 5
|
||||
#define NRF_BIT6 1 << 6
|
||||
#define NRF_BIT7 1 << 7
|
||||
|
||||
|
||||
/* Register Map */
|
||||
#define RF24_CONFIG 0x00 // Configuration register
|
||||
#define RF24_EN_AA 0x01 // Enable "Auto acknowledgment"
|
||||
#define RF24_EN_RXADDR 0x02 // Enable RX addresses
|
||||
#define RF24_SETUP_AW 0x03 // Setup of address widths
|
||||
#define RF24_SETUP_RETR 0x04 // Setup of automatic retranslation
|
||||
#define RF24_RF_CH 0x05 // RF channel
|
||||
#define RF24_RF_SETUP 0x06 // RF setup register
|
||||
#define RF24_STATUS 0x07 // Status register
|
||||
#define RF24_OBSERVE_TX 0x08 // Transmit observe register
|
||||
#define RF24_CD 0x09 // Carrier detect
|
||||
#define RF24_RPD 0x09
|
||||
#define RF24_RX_ADDR_P0 0x0A // Receive address data pipe 0
|
||||
#define RF24_RX_ADDR_P1 0x0B // ..
|
||||
#define RF24_RX_ADDR_P2 0x0C // ..
|
||||
#define RF24_RX_ADDR_P3 0x0D // ..
|
||||
#define RF24_RX_ADDR_P4 0x0E // ..
|
||||
#define RF24_RX_ADDR_P5 0x0F // Receive address data pipe 5
|
||||
#define RF24_TX_ADDR 0x10 // Transmit address
|
||||
#define RF24_RX_PW_P0 0x11 // Number of bytes in RX payload id data pipe 0
|
||||
#define RF24_RX_PW_P1 0x12 // ..
|
||||
#define RF24_RX_PW_P2 0x13 // ..
|
||||
#define RF24_RX_PW_P3 0x14 // ..
|
||||
#define RF24_RX_PW_P4 0x15 // ..
|
||||
#define RF24_RX_PW_P5 0x16 // Number of bytes in RX payload id data pipe 5
|
||||
#define RF24_FIFO_STATUS 0x17 // FIFO status register
|
||||
#define RF24_DYNPD 0x1C // Enable dynamic payload length
|
||||
#define RF24_FEATURE 0x1D // Feature register
|
||||
|
||||
|
||||
/* Register NRF_BITs */
|
||||
#define RF24_MASK_RX_DR NRF_BIT6 // Mask interrupt caused by RX_DR
|
||||
#define RF24_MASK_TX_DS NRF_BIT5 // Mask interrupt caused by TX_DS
|
||||
#define RF24_MASK_MAX_RT NRF_BIT4 // Mask interrupt caused by MAX_RT
|
||||
#define RF24_EN_CRC NRF_BIT3
|
||||
#define RF24_CRCO NRF_BIT2
|
||||
#define RF24_PWR_UP NRF_BIT1
|
||||
#define RF24_PRIM_RX NRF_BIT0
|
||||
#define RF24_ENAA_P5 NRF_BIT5
|
||||
#define RF24_ENAA_P4 NRF_BIT4
|
||||
#define RF24_ENAA_P3 NRF_BIT3
|
||||
#define RF24_ENAA_P2 NRF_BIT2
|
||||
#define RF24_ENAA_P1 NRF_BIT1
|
||||
#define RF24_ENAA_P0 NRF_BIT0
|
||||
#define RF24_ERX_P5 NRF_BIT5
|
||||
#define RF24_ERX_P4 NRF_BIT4
|
||||
#define RF24_ERX_P3 NRF_BIT3
|
||||
#define RF24_ERX_P2 NRF_BIT2
|
||||
#define RF24_ERX_P1 NRF_BIT1
|
||||
#define RF24_ERX_P0 NRF_BIT0
|
||||
#define RF24_DYNPL_P5 NRF_BIT5
|
||||
#define RF24_DYNPL_P4 NRF_BIT4
|
||||
#define RF24_DYNPL_P3 NRF_BIT3
|
||||
#define RF24_DYNPL_P2 NRF_BIT2
|
||||
#define RF24_DYNPL_P1 NRF_BIT1
|
||||
#define RF24_DYNPL_P0 NRF_BIT0
|
||||
#define RF24_AW NRF_BIT0
|
||||
#define RF24_ARD NRF_BIT4
|
||||
#define RF24_ARC NRF_BIT0
|
||||
#define RF24_PLL_LOCK NRF_BIT4
|
||||
#define RF24_CONT_WAVE NRF_BIT7
|
||||
#define RF24_RF_DR NRF_BIT3
|
||||
#define RF24_RF_DR_LOW NRF_BIT5
|
||||
#define RF24_RF_DR_HIGH NRF_BIT3
|
||||
#define RF24_RF_PWR NRF_BIT1
|
||||
#define RF24_LNA_HCURR NRF_BIT0
|
||||
#define RF24_RX_DR NRF_BIT6
|
||||
#define RF24_TX_DS NRF_BIT5
|
||||
#define RF24_MAX_RT NRF_BIT4
|
||||
#define RF24_RX_P_NO NRF_BIT1
|
||||
#define RF24_TX_FULL NRF_BIT0
|
||||
#define RF24_PLOS_CNT NRF_BIT4
|
||||
#define RF24_ARC_CNT NRF_BIT0
|
||||
#define RF24_TX_REUSE NRF_BIT6
|
||||
#define RF24_FIFO_FULL NRF_BIT5
|
||||
#define RF24_TX_EMPTY NRF_BIT4
|
||||
#define RF24_RX_FULL NRF_BIT1 // RX FIFO full flag
|
||||
#define RF24_RX_EMPTY NRF_BIT0 // RX FIFO empty flag
|
||||
#define RF24_EN_DPL NRF_BIT2
|
||||
#define RF24_EN_ACK_PAY NRF_BIT1
|
||||
#define RF24_EN_DYN_ACK NRF_BIT0
|
||||
|
||||
#define RF24_SPEED_250 NRF_BIT5
|
||||
#define RF24_SPEED_1000 0
|
||||
#define RF24_SPEED_2000 NRF_BIT3
|
||||
|
||||
#define RF24_POWER_FULL NRF_BIT2 | NRF_BIT1
|
||||
#define RF24_POWER_HIGH NRF_BIT2
|
||||
#define RF24_POWER_MED NRF_BIT1
|
||||
#define RF24_POWER_LOW 0
|
||||
|
||||
#define RF24_RETRY_250US 0x00
|
||||
#define RF24_RETRY_500US 0x10
|
||||
#define RF24_RETRY_750US 0x20
|
||||
#define RF24_RETRY_1000US 0x30
|
||||
#define RF24_RETRY_1250US 0x40
|
||||
#define RF24_RETRY_1500US 0x50
|
||||
#define RF24_RETRY_1750US 0x60
|
||||
#define RF24_RETRY_2000US 0x70
|
||||
#define RF24_RETRY_2250US 0x80
|
||||
#define RF24_RETRY_2500US 0x90
|
||||
#define RF24_RETRY_2750US 0xa0
|
||||
#define RF24_RETRY_3000US 0xb0
|
||||
#define RF24_RETRY_3250US 0xc0
|
||||
#define RF24_RETRY_3500US 0xd0
|
||||
#define RF24_RETRY_3750US 0xe0
|
||||
#define RF24_RETRY_4000US 0xf0
|
||||
|
||||
#define RF24_RETRANS_OFF 0
|
||||
#define RF24_RETRANS_1X 1
|
||||
#define RF24_RETRANS_2X 2
|
||||
#define RF24_RETRANS_3X 3
|
||||
#define RF24_RETRANS_4X 4
|
||||
#define RF24_RETRANS_5X 5
|
||||
#define RF24_RETRANS_6X 6
|
||||
#define RF24_RETRANS_7X 7
|
||||
#define RF24_RETRANS_8X 8
|
||||
#define RF24_RETRANS_9X 9
|
||||
#define RF24_RETRANS_10X 10
|
||||
#define RF24_RETRANS_11X 11
|
||||
#define RF24_RETRANS_12X 12
|
||||
#define RF24_RETRANS_13X 13
|
||||
#define RF24_RETRANS_14X 14
|
||||
#define RF24_RETRANS_15X 15
|
||||
|
||||
|
||||
/* Instructions */
|
||||
#define RF24_RREG 0x00 // R_REGISTER -> Read command and status registers
|
||||
#define RF24_WREG 0x20 // W_REGISTER -> Write command and status registers
|
||||
#define RF24_REGISTER_MASK 0x1F
|
||||
#define RF24_R_RX_PAYLOAD 0x61 // R_RX_PAYLOAD -> Read RX payload
|
||||
#define RF24_W_TX_PAYLOAD 0xA0 // W_TX_PAYLOAD -> Write TX payload
|
||||
#define RF24_FLUSH_TX 0xE1 // FLUSH_TX -> Flush TX FIFO
|
||||
#define RF24_FLUSH_RX 0xE2 // FLUSH_RX -> Flush RX FIFO
|
||||
#define RF24_REUSE_TX_PL 0xE3 // REUSE_TX_PL -> Reuse last transmitted payload
|
||||
#define RF24_R_RX_PL_WID 0x60
|
||||
#define RF24_W_ACK_PAYLOAD 0xA8
|
||||
#define RF24_W_TX_PAYLOAD_NOACK 0xB0
|
||||
#define RF24_ACTIVATE 0x50
|
||||
#define RF24_NOP 0xFF // No operation (to read status register)
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,766 @@
|
|||
/*
|
||||
* true's NRF24L01+ C library
|
||||
* shamelessly stolen and modified heavily from some other shit
|
||||
* basically: it's better than nothing
|
||||
*
|
||||
* $Id: true_nRF24L01.c 505 2021-09-05 19:07:51Z true $
|
||||
* ====
|
||||
*
|
||||
* general instructions to set up:
|
||||
* - Edit any shit necessary for your driver to work, update "true_nRF24L01.h"
|
||||
* with your driver include file
|
||||
* - #include "true_nRF24L01.h" in your radio setup code source file
|
||||
* - for RX devices, you should set nRF24_rx_cb to your data handler. this
|
||||
* handler is called with the data buffer / buffer length and received pipe.
|
||||
* - call nRF24_init() which sets defaults, calls nRF24_driver_init() which
|
||||
* sets up hardware tasks, peripherals, and interrupts
|
||||
* - set and update your configuration, tx/rx addresses in your code
|
||||
* - in your IRQ pin ISR, call nRF24_interrupt(). this might be in your driver.
|
||||
* - if you did not set nRF24_rx_cb, check for new data by reading status
|
||||
* and RX FIFO, and receive data manually however you decide to do it
|
||||
* - no special shit for transmit, just set up and go
|
||||
*/
|
||||
|
||||
|
||||
/* nrf24 library includes */
|
||||
#include "true_nRF24L01.h"
|
||||
|
||||
|
||||
/* nrf24 configuration */
|
||||
static uint32_t txdelay;
|
||||
static nrfConfig config;
|
||||
|
||||
|
||||
/* nrf24 data handling */
|
||||
static uint8_t nRF24_pbuf[_TRNRF_MAX_PACKET_SIZE];
|
||||
void (*nRF24_rx_cb)(uint8_t pipe, uint8_t *pBuf, uint8_t len);
|
||||
void (*nRF24_tx_done_cb)();
|
||||
void (*nRF24_tx_max_rt_cb)();
|
||||
|
||||
|
||||
/* nrf24 feedback */
|
||||
static uint8_t nrf_mode = _TRNRF_MODE_OFF;
|
||||
static uint8_t rx_received_pipe;
|
||||
|
||||
|
||||
|
||||
/*********************************/
|
||||
/**** NRF SETUP AND INTERRUPT ****/
|
||||
|
||||
/**
|
||||
* Initializes nRF24 config and hardware layer abstracted shit.
|
||||
*/
|
||||
void nRF24_init(uint32_t cpu_freq_hz) {
|
||||
// TX pin delay factor
|
||||
txdelay = cpu_freq_hz >> 19;
|
||||
|
||||
// set some defaults
|
||||
config.channel = 2;
|
||||
config.rate_power = RF24_SPEED_1000 | RF24_POWER_FULL;
|
||||
config.addr_width = 5;
|
||||
config.payload_size[0] = 8;
|
||||
config.payload_size[1] = 8;
|
||||
config.crc = RF24_EN_CRC | RF24_CRCO;
|
||||
config.pipe_ena = RF24_ERX_P0 | RF24_ERX_P1; // this is NRF power-up default
|
||||
config.autoack_ena = 0x3f; // this is NRF power-up default
|
||||
config.retry = RF24_RETRY_500US | RF24_RETRANS_10X;
|
||||
config.tx_config = _TRNRF_MAX_RT_AUTOFLUSH | _TRNRF_MODE_RX;
|
||||
|
||||
// start up the hardware shit
|
||||
nRF24_driver_init();
|
||||
|
||||
// clear the RX/TX FIFOs
|
||||
nRF24_reg_write(RF24_FLUSH_RX);
|
||||
nRF24_reg_write(RF24_FLUSH_TX);
|
||||
// and clear interrupt sources
|
||||
nRF24_clear_irq_flags();
|
||||
}
|
||||
|
||||
|
||||
/* Note: at this time, this code requires the IRQ pin to operate */
|
||||
|
||||
/**
|
||||
* Handles doing shit (receive data, clear IRQ flags) when IRQ is asserted.
|
||||
*
|
||||
* Call this function from your IRQ handler.
|
||||
*
|
||||
* @return NRF status
|
||||
*/
|
||||
uint8_t nRF24_interrupt()
|
||||
{
|
||||
uint8_t status;
|
||||
uint8_t pipe;
|
||||
uint8_t len;
|
||||
|
||||
status = nRF24_reg_write(RF24_NOP);
|
||||
|
||||
if (status & RF24_TX_DS) {
|
||||
// packet sent successfully and should not be in our FIFO
|
||||
if (nRF24_tx_done_cb != 0) {
|
||||
nRF24_tx_done_cb();
|
||||
}
|
||||
}
|
||||
|
||||
if (status & RF24_MAX_RT) {
|
||||
// packet not sent successfully and IS still in our FIFO
|
||||
if (config.tx_config & _TRNRF_MAX_RT_AUTOFLUSH) {
|
||||
nRF24_reg_write(RF24_FLUSH_TX);
|
||||
}
|
||||
|
||||
if (nRF24_tx_max_rt_cb != 0) {
|
||||
nRF24_tx_max_rt_cb();
|
||||
}
|
||||
}
|
||||
|
||||
if (status & RF24_RX_DR) {
|
||||
// process data
|
||||
if ((status & RF24_RX_P_NO) == RF24_RX_P_NO) {
|
||||
// fifo done interrupt, so what? we don't care
|
||||
} else {
|
||||
if (nRF24_data_is_ready()) {
|
||||
// looks like we have some data waiting for us
|
||||
// if no callback is set, assume we are handling this manually elsewhere
|
||||
if (nRF24_rx_cb != 0) {
|
||||
// but our callback is set, so receive data
|
||||
len = nRF24_packet_rx(status, nRF24_pbuf);
|
||||
pipe = nRF24_rx_received_pipe();
|
||||
// process data
|
||||
if (len <= _TRNRF_MAX_PACKET_SIZE) {
|
||||
nRF24_rx_cb(pipe, nRF24_pbuf, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clear all pending interrupt flags
|
||||
nRF24_clear_irq_flags();
|
||||
|
||||
// resume wtf we needed to do
|
||||
if (nrf_mode & _TRNRF_MODE_TX) {
|
||||
switch (config.tx_config & _TRNRF_MODE_MASK) {
|
||||
case _TRNRF_MODE_RX: {
|
||||
nRF24_mode_rx();
|
||||
break;
|
||||
}
|
||||
case _TRNRF_MODE_OFF: {
|
||||
nRF24_mode_off();
|
||||
break;
|
||||
}
|
||||
case _TRNRF_MODE_TX: {
|
||||
// this will put us into standby-ii. this mode is not recommended.
|
||||
_TRNRF_CE_H();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (nrf_mode & _TRNRF_MODE_RX) {
|
||||
nRF24_mode_rx();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/***************************/
|
||||
/**** NRF SPI FUNCTIONS ****/
|
||||
|
||||
/**
|
||||
* Writes a value to NRF register or a single-byte argument to a command,
|
||||
* and reads the following byte (usually the result, see the datasheet)
|
||||
*
|
||||
* @param reg register / command to write to
|
||||
* @param value value to write to register / command
|
||||
*
|
||||
* @return value of the STATUS register
|
||||
*/
|
||||
uint8_t nRF24_reg_rw(uint8_t reg, uint8_t value) {
|
||||
uint8_t status;
|
||||
|
||||
_TRNRF_CSN_L();
|
||||
|
||||
status = nRF24_spi_rw(reg); // Select register/command
|
||||
nRF24_spi_rw(value); // Write value to register
|
||||
|
||||
_TRNRF_CSN_H();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a command byte to the NRF, and returns STATUS.
|
||||
*
|
||||
* @param cmd command to write
|
||||
*
|
||||
* @return value of the STATUS register
|
||||
*/
|
||||
uint8_t nRF24_reg_write(uint8_t cmd) {
|
||||
uint8_t status;
|
||||
|
||||
_TRNRF_CSN_L();
|
||||
|
||||
status = nRF24_spi_rw(cmd);
|
||||
|
||||
_TRNRF_CSN_H();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a byte from the NRF register or command.
|
||||
*
|
||||
* @param reg register / command to read from
|
||||
*
|
||||
* @return value of this register / command
|
||||
*/
|
||||
uint8_t nRF24_reg_read(uint8_t reg) {
|
||||
uint8_t value;
|
||||
|
||||
_TRNRF_CSN_L();
|
||||
|
||||
nRF24_spi_rw(reg);
|
||||
value = nRF24_spi_rw(0x00);
|
||||
|
||||
_TRNRF_CSN_H();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a buffer to NRF.
|
||||
*
|
||||
* @param reg register (buffer) to write info
|
||||
* @param *pBuf source buffer contents to read from
|
||||
* @param len bytes to read
|
||||
*
|
||||
* @return value of the STATUS register
|
||||
*/
|
||||
uint8_t nRF24_buf_write(uint8_t reg, void *pBuf, uint8_t bytes) {
|
||||
uint8_t status;
|
||||
uint8_t i;
|
||||
|
||||
_TRNRF_CSN_L();
|
||||
|
||||
status = nRF24_spi_rw(reg);
|
||||
|
||||
for (i = 0; i < bytes; i++)
|
||||
nRF24_spi_rw(((uint8_t *)pBuf)[i]);
|
||||
|
||||
_TRNRF_CSN_H();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a buffer from NRF.
|
||||
*
|
||||
* @param reg register (buffer) to read from
|
||||
* @param *pBuf buffer to read register into
|
||||
* @param bytes bytes to read
|
||||
*
|
||||
* @return value of the STATUS register
|
||||
*/
|
||||
uint8_t nRF24_buf_read(uint8_t reg, void *pBuf, uint8_t bytes) {
|
||||
uint8_t status;
|
||||
uint8_t i;
|
||||
|
||||
_TRNRF_CSN_L();
|
||||
|
||||
status = nRF24_spi_rw(reg);
|
||||
|
||||
for (i = 0; i < bytes; i++)
|
||||
((uint8_t *)pBuf)[i] = nRF24_spi_rw(0x00);
|
||||
|
||||
_TRNRF_CSN_H();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/***********************************/
|
||||
/**** NRF USER CONFIG FUNCTIONS ****/
|
||||
|
||||
/**
|
||||
* Updates the TX address to the radio.
|
||||
*/
|
||||
void nRF24_update_txaddr()
|
||||
{
|
||||
_TRNRF_CE_L();
|
||||
|
||||
if (config.tx_addr) {
|
||||
nRF24_buf_write(RF24_WREG | RF24_TX_ADDR, config.tx_addr, config.addr_width);
|
||||
}
|
||||
|
||||
// were we in RX mode? yeah? then start listening again
|
||||
if ((nrf_mode & _TRNRF_MODE_MASK) == _TRNRF_MODE_RX) {
|
||||
_TRNRF_CE_H();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the TX address buffer pointer, and updates the radio with this address.
|
||||
* Make sure this buffer is at least config.addr_width in size.
|
||||
*
|
||||
* @param *addr pointer to tx buffer
|
||||
*/
|
||||
void nRF24_set_txaddr(const uint8_t *addr)
|
||||
{
|
||||
config.tx_addr = (uint8_t *)addr;
|
||||
nRF24_update_txaddr();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates the specified RX address to the radio.
|
||||
*
|
||||
* Please remember, auto-acknowledge requires pipe 0's address to match the
|
||||
* transmit address.
|
||||
*
|
||||
* Please remember, pipes 2 through 5 copy pipe 1's most significant bytes.
|
||||
*/
|
||||
void nRF24_update_rxaddr(uint8_t pipe)
|
||||
{
|
||||
_TRNRF_CE_L();
|
||||
|
||||
if (pipe == 0 && config.rx_addr_p0) {
|
||||
nRF24_buf_write(RF24_WREG | RF24_RX_ADDR_P0, config.rx_addr_p0, config.addr_width);
|
||||
} else if (pipe == 1 && config.rx_addr_p1) {
|
||||
nRF24_buf_write(RF24_WREG | RF24_RX_ADDR_P1, config.rx_addr_p1, config.addr_width);
|
||||
} else if (pipe <= 5) {
|
||||
nRF24_reg_rw(RF24_WREG | (RF24_RX_ADDR_P0 + pipe), config.rx_pipe[pipe - 2]);
|
||||
}
|
||||
|
||||
// were we in RX mode? yeah? then start listening again
|
||||
if ((nrf_mode & _TRNRF_MODE_MASK) == _TRNRF_MODE_RX) {
|
||||
_TRNRF_CE_H();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the RX address buffer pointer for pipes 0 and 1, and sets the
|
||||
* unique byte for pipes 2 through 5. Afterwards, updates the radio
|
||||
* with the new address.
|
||||
*
|
||||
* For pipes 0 and 1, make sure this buffer is at least config.addr_width in size.
|
||||
*
|
||||
* @param *addr pointer to rx buffer (can be temporary for pipes 2 through 5)
|
||||
*/
|
||||
void nRF24_set_rxaddr(uint8_t pipe, const uint8_t *addr)
|
||||
{
|
||||
if (pipe == 0) {
|
||||
config.rx_addr_p0 = (uint8_t *)addr;
|
||||
} else if (pipe == 1) {
|
||||
config.rx_addr_p1 = (uint8_t *)addr;
|
||||
} else if (pipe <= 5) {
|
||||
config.rx_pipe[pipe - 2] = *addr;
|
||||
}
|
||||
|
||||
nRF24_update_rxaddr(pipe);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the active channel between 2400MHz (0) and 2.525MHz (125).
|
||||
* At 2Mbps channel width is larger than 1MHz, so use 2MHz spacings
|
||||
* if you have multiple channels with multiple devices in use.
|
||||
*/
|
||||
void nRF24_set_channel(uint8_t chan)
|
||||
{
|
||||
if (chan > 125) chan = 125;
|
||||
config.channel = chan;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data rate between RF_SPEED_250, RF_SPEED_1000, and RF_SPEED_2000.
|
||||
*/
|
||||
void nRF24_set_rate(uint8_t rate)
|
||||
{
|
||||
config.rate_power &= ~(RF24_SPEED_250 | RF24_SPEED_1000 | RF24_SPEED_2000);
|
||||
config.rate_power |= (rate & (RF24_SPEED_250 | RF24_SPEED_1000 | RF24_SPEED_2000));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the output power level.
|
||||
*/
|
||||
void nRF24_set_power(uint8_t power)
|
||||
{
|
||||
config.rate_power &= ~(RF24_POWER_FULL);
|
||||
config.rate_power |= (power & (RF24_POWER_FULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the address width from 3 to 5 bytes wide.
|
||||
*/
|
||||
void nRF24_set_addr_width(uint8_t width)
|
||||
{
|
||||
if (width < 3) width = 3;
|
||||
if (width > 5) width = 5;
|
||||
config.addr_width = width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the payload size.
|
||||
*/
|
||||
void nRF24_set_payload_size(uint8_t pipe, uint8_t size)
|
||||
{
|
||||
if (pipe <= 5) {
|
||||
config.payload_size[pipe] = size;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the CRC options.
|
||||
*/
|
||||
void nRF24_set_crc(uint8_t crc)
|
||||
{
|
||||
config.crc = crc & (RF24_EN_CRC | RF24_CRCO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables and disables receive pipes.
|
||||
*/
|
||||
void nRF24_set_pipe(uint8_t pipe, uint8_t onoff)
|
||||
{
|
||||
if (pipe <= 5) {
|
||||
if (onoff) {
|
||||
config.pipe_ena |= (1 << pipe);
|
||||
} else {
|
||||
config.pipe_ena &= ~(1 << pipe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables and disables Shockburst (auto-acknowledge) per pipe.
|
||||
*/
|
||||
void nRF24_set_autoack(uint8_t pipe, uint8_t onoff)
|
||||
{
|
||||
if (pipe <= 5) {
|
||||
if (onoff) {
|
||||
config.autoack_ena |= (1 << pipe);
|
||||
} else {
|
||||
config.autoack_ena &= ~(1 << pipe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the Dynamic ACK transmit option.
|
||||
*/
|
||||
void nRF24_set_dynack(uint8_t onoff)
|
||||
{
|
||||
if (onoff) {
|
||||
config.autoack_ena |= 0x80;
|
||||
} else {
|
||||
config.autoack_ena &= 0x7f;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the active configuration to the radio.
|
||||
*/
|
||||
void nRF24_update_config(uint8_t mask)
|
||||
{
|
||||
uint8_t set[3];
|
||||
uint8_t bit;
|
||||
uint8_t i;
|
||||
|
||||
set[0] = set[1] = set[2] = 0;
|
||||
|
||||
_TRNRF_CE_L();
|
||||
|
||||
// set SETUP_AW address width
|
||||
if (mask & _TRNRF_UPDATE_SETUP_AW) {
|
||||
nRF24_reg_rw(RF24_WREG | RF24_SETUP_AW, config.addr_width - 2);
|
||||
}
|
||||
|
||||
// set up various per-pipe configurations
|
||||
if (mask & (_TRNRF_UPDATE_EN_RXADDR | _TRNRF_UPDATE_EN_AA | _TRNRF_UPDATE_DYNPD | _TRNRF_UPDATE_FEATURE)) {
|
||||
for (i = 0; i <= 5; i++) {
|
||||
bit = 1 << i;
|
||||
|
||||
if (config.pipe_ena & bit) {
|
||||
set[0] |= bit;
|
||||
|
||||
nRF24_reg_rw(RF24_WREG | (RF24_RX_PW_P0 + i),
|
||||
(config.payload_size[i] > 32 ? 32 : config.payload_size[i]));
|
||||
}
|
||||
if (config.autoack_ena & bit) {
|
||||
set[1] |= bit;
|
||||
}
|
||||
if (config.payload_size[i] == _TRNRF_DYN_PAYLOAD) {
|
||||
set[2] |= bit;
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & _TRNRF_UPDATE_EN_AA) nRF24_reg_rw(RF24_WREG | RF24_EN_AA, set[1]);
|
||||
if (mask & _TRNRF_UPDATE_EN_RXADDR) nRF24_reg_rw(RF24_WREG | RF24_EN_RXADDR, set[0]);
|
||||
|
||||
if (mask & (_TRNRF_UPDATE_DYNPD | _TRNRF_UPDATE_FEATURE)) {
|
||||
nRF24_reg_rw(RF24_WREG | RF24_DYNPD, set[2]);
|
||||
|
||||
// set up FEATURE register (dynamic payload length, ack payload, dynamic ack [noack])
|
||||
set[0] = ((set[2] ? RF24_EN_DPL : 0) | ((config.autoack_ena & 0x80) ? RF24_EN_DYN_ACK : 0));
|
||||
nRF24_reg_rw(RF24_WREG | RF24_FEATURE, set[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// set SETUP_RETR auto-ack retry settings
|
||||
if (mask & _TRNRF_UPDATE_SETUP_RETR) {
|
||||
nRF24_reg_rw(RF24_WREG | RF24_SETUP_RETR, config.retry);
|
||||
}
|
||||
|
||||
// set RF_CH channel
|
||||
if (mask & _TRNRF_UPDATE_RF_CH) {
|
||||
nRF24_reg_rw(RF24_WREG | RF24_RF_CH, config.channel);
|
||||
}
|
||||
|
||||
// set RF_SETUP data rate, power output
|
||||
if (mask & _TRNRF_UPDATE_RF_SETUP) {
|
||||
nRF24_reg_rw(RF24_WREG | RF24_RF_SETUP, config.rate_power);
|
||||
}
|
||||
|
||||
// set CONFIG crc
|
||||
if (mask & _TRNRF_UPDATE_CRC) {
|
||||
set[0] = nRF24_reg_read(RF24_CONFIG) & (RF24_PWR_UP | RF24_PRIM_RX);
|
||||
nRF24_reg_rw(RF24_WREG | RF24_CONFIG, config.crc | set[0]);
|
||||
}
|
||||
|
||||
// were we in RX mode? yeah? then start listening again
|
||||
if ((nrf_mode & _TRNRF_MODE_MASK) == _TRNRF_MODE_RX) {
|
||||
_TRNRF_CE_H();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state to go into after transmit is done.
|
||||
* This mode is applied after a TX is complete in the interrupt handler.
|
||||
*/
|
||||
void nRF24_set_tx_config(uint8_t max_rt_flush, uint8_t new_done_state)
|
||||
{
|
||||
config.tx_config = (max_rt_flush & 0x80) | (new_done_state & 0x7f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks to see if an NRF24L01 is present by setting and reading a fake address.
|
||||
* After completion, it resets to the configured address parameters.
|
||||
*
|
||||
* @return nRF24 is present (1 = yes, 0 = no)
|
||||
*/
|
||||
uint8_t nRF24_is_present(void) {
|
||||
uint8_t buf[3];
|
||||
|
||||
// write address length and fake address
|
||||
buf[2] = 0xa9;
|
||||
nRF24_reg_rw(RF24_WREG | RF24_SETUP_AW, 0x01); // 3 bytes
|
||||
nRF24_buf_write(RF24_WREG | RF24_TX_ADDR, buf, 3);
|
||||
// clear some address data
|
||||
buf[2] = 0x00;
|
||||
|
||||
// try to read TX_ADDR register back
|
||||
nRF24_buf_read(RF24_TX_ADDR, buf, 3);
|
||||
|
||||
// reset SETUP_AW and TX addr
|
||||
nRF24_reg_rw(RF24_WREG | RF24_SETUP_AW, config.addr_width - 2);
|
||||
nRF24_update_txaddr();
|
||||
|
||||
// verify address matches fake address
|
||||
if (buf[2] == 0xa9)
|
||||
return 1;
|
||||
|
||||
// seems to be missing...
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*************************/
|
||||
/**** OPERATING MODES ****/
|
||||
|
||||
/**
|
||||
* Puts the NRF into RX mode, turns on the radio, and starts listening.
|
||||
*
|
||||
* Only sets registers necessary to do this. Configure the radio
|
||||
* with nRF24_update_rxaddr, nRF24_update_config before putting
|
||||
* it into RX mode.
|
||||
*/
|
||||
void nRF24_mode_rx() {
|
||||
_TRNRF_CE_L();
|
||||
|
||||
nRF24_reg_rw(RF24_WREG | RF24_CONFIG, config.crc | RF24_PWR_UP | RF24_PRIM_RX);
|
||||
|
||||
// put into active receive mode immediately
|
||||
_TRNRF_CE_H();
|
||||
nrf_mode = _TRNRF_MODE_RX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares for standby, then puts the NRF into TX mode and turns on the radio.
|
||||
*
|
||||
* This is called from nRF24_packet_tx() automatically if the mode is
|
||||
* currently not in a transmit mode. Transmit will occur when
|
||||
* nRF24_packet_tx() is used.
|
||||
*
|
||||
* Only sets registers necessary to complete changing the mode. Configure any
|
||||
* other settings for the radio with nRF24_update_rxaddr (if auto-ack is on),
|
||||
* nRF24_update_txaddr, nRF24_update_config before putting it into TX mode.
|
||||
*/
|
||||
void nRF24_mode_tx() {
|
||||
// we will set high when ready to transmit
|
||||
_TRNRF_CE_L();
|
||||
|
||||
nRF24_reg_rw(RF24_WREG | RF24_CONFIG, config.crc | RF24_PWR_UP);
|
||||
nrf_mode = _TRNRF_MODE_TX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the radio into standby (useful when in RX mode to save power).
|
||||
*/
|
||||
void nRF24_mode_standby()
|
||||
{
|
||||
_TRNRF_CE_L();
|
||||
nrf_mode |= _TRNRF_MODE_STANDBY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Powers down the NRF24L01.
|
||||
*/
|
||||
void nRF24_mode_off()
|
||||
{
|
||||
_TRNRF_CE_L();
|
||||
|
||||
nRF24_reg_rw(RF24_WREG | RF24_CONFIG, nRF24_reg_read(RF24_CONFIG) & ~(RF24_PWR_UP));
|
||||
nrf_mode = _TRNRF_MODE_OFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently operating NRF mode.
|
||||
*/
|
||||
uint8_t nRF24_mode_get()
|
||||
{
|
||||
return nrf_mode;
|
||||
}
|
||||
|
||||
|
||||
/**************************/
|
||||
/**** DATA TRANSCIEVER ****/
|
||||
|
||||
/**
|
||||
* Checks if data is ready by seeing if there is anything in the RX FIFO.
|
||||
*/
|
||||
uint8_t nRF24_data_is_ready(void) {
|
||||
uint8_t status;
|
||||
|
||||
status = nRF24_reg_read(RF24_FIFO_STATUS);
|
||||
return (status & RF24_RX_EMPTY) ? 0 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a packet for transmit, puts the radio into transmit mode, then signals
|
||||
* radio to begin transmitting.
|
||||
*
|
||||
* @param *pBuf pointer to transmit buffer
|
||||
* @param bytes bytes to send
|
||||
* @param noack if not zero, and if dynack enabled, flags the packet NO_ACK
|
||||
*/
|
||||
void nRF24_packet_tx(void *pBuf, uint8_t bytes, uint8_t noack) {
|
||||
int i;
|
||||
|
||||
// make sure we are in TX mode
|
||||
if ((nrf_mode & _TRNRF_MODE_TX) == 0) {
|
||||
nRF24_mode_tx();
|
||||
}
|
||||
|
||||
// write TX buffer to FIFO
|
||||
// note: noack mode will only work if nRF24_set_dynack(1); nRF24_config_update(); has been done
|
||||
// also make sure that you have nRF24_set_rxaddr(0, txaddr) if using shockburst
|
||||
nRF24_buf_write((noack && config.autoack_ena & 0x80) ?
|
||||
RF24_W_TX_PAYLOAD_NOACK : RF24_W_TX_PAYLOAD, pBuf, bytes);
|
||||
|
||||
// CE pin high => start transmit
|
||||
_TRNRF_CE_H();
|
||||
|
||||
// if we're going into standard standby-I mode, need to do a little more
|
||||
if (!(config.tx_config & _TRNRF_MODE_TX)) {
|
||||
// needs to be high for at least 10us for tx to function, per datasheet
|
||||
// this keeps it high for about 16us
|
||||
for (i = txdelay; i; i--) {
|
||||
asm volatile ("nop");
|
||||
}
|
||||
|
||||
_TRNRF_CE_L();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives a packet.
|
||||
*
|
||||
* @param status nRF24 status (please get with nRF24_reg_read(RF24_STATUS))
|
||||
* @param *pBuf pointer to receive buffer
|
||||
*
|
||||
* @return length of data received
|
||||
*/
|
||||
int8_t nRF24_packet_rx(uint8_t status, void *pBuf) {
|
||||
uint8_t pipe;
|
||||
uint8_t payload_len;
|
||||
|
||||
// status must indicate RX ready and RX FIFO not empty
|
||||
if ((status & RF24_RX_DR) && ((status & RF24_RX_P_NO) != RF24_RX_P_NO)) {
|
||||
// get pipe
|
||||
pipe = (status & RF24_RX_P_NO) >> 1;
|
||||
|
||||
// payload is static, unless it isn't, in which case get the received payload length
|
||||
payload_len = config.payload_size[pipe];
|
||||
if (payload_len == _TRNRF_DYN_PAYLOAD) {
|
||||
payload_len = nRF24_reg_read(RF24_R_RX_PL_WID);
|
||||
|
||||
// is it valid?
|
||||
if (payload_len > 32) {
|
||||
// no, flush buffer and quit
|
||||
nRF24_reg_write(RF24_FLUSH_RX);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// everything else done, so set pipe, clear buffer, read payload from RX FIFO buffer
|
||||
// NRF automatically removes this data from FIFO per datasheet
|
||||
rx_received_pipe = pipe;
|
||||
nRF24_buf_read(RF24_R_RX_PAYLOAD, pBuf, payload_len);
|
||||
return payload_len;
|
||||
}
|
||||
|
||||
// requests to receive that are not ready will clear RX FIFO
|
||||
nRF24_reg_write(RF24_FLUSH_RX);
|
||||
return -2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last received data's pipe number.
|
||||
*/
|
||||
uint8_t nRF24_rx_received_pipe()
|
||||
{
|
||||
return rx_received_pipe;
|
||||
}
|
||||
|
||||
uint8_t nRF24_packet_ackreply(uint8_t *pBuf, uint8_t tx_payload_len)
|
||||
{
|
||||
if (config.payload_size[0] != _TRNRF_DYN_PAYLOAD) {
|
||||
// ack reply payloads require dynamic payload to be enabled
|
||||
return 0;
|
||||
}
|
||||
|
||||
// not yet implemented
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*****************/
|
||||
/**** IRQ PIN ****/
|
||||
|
||||
/**
|
||||
* Clear all IRQ status flags.
|
||||
*/
|
||||
void nRF24_clear_irq_flags(void) {
|
||||
// Clear RX_DR, TX_DS, MAX_RT flags. cleared by writing 1 to these bits
|
||||
nRF24_reg_rw(RF24_WREG | RF24_STATUS, (RF24_RX_DR | RF24_TX_DS | RF24_MAX_RT));
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* true's NRF24L01+ C library
|
||||
* shamelessly stolen and modified heavily from some other shit
|
||||
* basically: it's better than nothing
|
||||
*
|
||||
* $Id: true_nRF24L01.h 505 2021-09-05 19:07:51Z true $
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __TRUE_NRF24L01_LIB_H
|
||||
#define __TRUE_NRF24L01_LIB_H
|
||||
|
||||
|
||||
/* common libraries */
|
||||
#include <stdint.h>
|
||||
#include "nRF24L01.h"
|
||||
|
||||
|
||||
/* user compile-time configuration */
|
||||
#define _TRNRF_MAX_PACKET_SIZE 32 // 32 is the max the radio can handle
|
||||
// set lower to save memory
|
||||
|
||||
|
||||
/* platform driver select */
|
||||
#include "true_nRF24L01_stm32l1xx.h"
|
||||
|
||||
|
||||
/* compile-time user configuration */
|
||||
#define _TRNRF_USE_INTERRUPT_PIN // enables the use of interrupt pin
|
||||
// only interrupt-mode implemented, currently mandatory
|
||||
|
||||
|
||||
/* nrf library constants */
|
||||
#define _TRNRF_MODE_OFF 0x00
|
||||
#define _TRNRF_MODE_STANDBY 0x01
|
||||
#define _TRNRF_MODE_RX 0x10
|
||||
#define _TRNRF_MODE_TX 0x20
|
||||
#define _TRNRF_MODE_MASK 0x3f
|
||||
|
||||
#define _TRNRF_UPDATE_ALL 0xff
|
||||
#define _TRNRF_UPDATE_EN_RXADDR 0x01
|
||||
#define _TRNRF_UPDATE_EN_AA 0x02
|
||||
#define _TRNRF_UPDATE_SETUP_AW 0x04
|
||||
#define _TRNRF_UPDATE_SETUP_RETR 0x08
|
||||
#define _TRNRF_UPDATE_RF_CH 0x10
|
||||
#define _TRNRF_UPDATE_RF_SETUP 0x20
|
||||
#define _TRNRF_UPDATE_CRC 0x40
|
||||
#define _TRNRF_UPDATE_DYNPD 0x80 // this and
|
||||
#define _TRNRF_UPDATE_FEATURE 0x80 // this should be updated together anyway
|
||||
|
||||
#define _TRNRF_ACK 0
|
||||
#define _TRNRF_NO_ACK 1
|
||||
|
||||
#define _TRNRF_MAX_RT_AUTOFLUSH 0x80
|
||||
#define _TRNRF_MAX_RT_NO_FLUSH 0x00
|
||||
|
||||
#define _TRNRF_DYN_PAYLOAD 0xff
|
||||
|
||||
|
||||
/* config struct */
|
||||
typedef struct nrfConfig {
|
||||
uint8_t channel; // 0-125, 2400MHz to 2525MHz
|
||||
uint8_t rate_power; // data rate, tx power
|
||||
uint8_t addr_width; // width of address, from 2-5 bytes
|
||||
uint8_t payload_size[6]; // per-pipe RX payload length, from 1-32 bytes, 0=variable payload
|
||||
uint8_t crc; // crc enable and crc mode bits
|
||||
uint8_t pipe_ena; // rx pipe enable bits
|
||||
uint8_t autoack_ena; // per-pipe autoack (enhanced shockburst) on/off
|
||||
uint8_t retry; // global autoack retry config
|
||||
uint8_t *tx_addr; // pointer to tx address, addr_width long
|
||||
uint8_t tx_config; // state to go into after transmitting a packet, flush max_rt FIFO automatically?
|
||||
uint8_t *rx_addr_p0; // pointer to rxp0 address, addr_width long
|
||||
uint8_t *rx_addr_p1; // pointer to rxp1 address, addr_width long
|
||||
uint8_t rx_pipe[4]; // rxp2-rxp5 last byte of address
|
||||
} nrfConfig;
|
||||
|
||||
|
||||
/* data handling */
|
||||
void (*nRF24_rx_cb)(uint8_t pipe, uint8_t *pBuf, uint8_t len);
|
||||
void (*nRF24_tx_done_cb)();
|
||||
void (*nRF24_tx_max_rt_cb)();
|
||||
|
||||
|
||||
/* function prototypes */
|
||||
void nRF24_init(uint32_t cpu_freq);
|
||||
uint8_t nRF24_interrupt();
|
||||
|
||||
uint8_t nRF24_reg_rw(uint8_t reg, uint8_t value);
|
||||
uint8_t nRF24_reg_write(uint8_t cmd);
|
||||
uint8_t nRF24_reg_read(uint8_t reg);
|
||||
uint8_t nRF24_buf_write(uint8_t reg, void *pBuf, uint8_t bytes);
|
||||
uint8_t nRF24_buf_read(uint8_t reg, void *pBuf, uint8_t bytes);
|
||||
|
||||
uint8_t nRF24_is_present(void);
|
||||
|
||||
void nRF24_set_txaddr(const uint8_t *addr);
|
||||
void nRF24_set_rxaddr(uint8_t pipe, const uint8_t *addr);
|
||||
|
||||
void nRF24_set_channel(uint8_t chan);
|
||||
void nRF24_set_rate(uint8_t rate);
|
||||
void nRF24_set_power(uint8_t power);
|
||||
void nRF24_set_addr_width(uint8_t width);
|
||||
void nRF24_set_payload_size(uint8_t pipe, uint8_t size);
|
||||
void nRF24_set_crc(uint8_t crc);
|
||||
void nRF24_set_pipe(uint8_t pipe, uint8_t onoff);
|
||||
void nRF24_set_autoack(uint8_t pipe, uint8_t onoff);
|
||||
void nRF24_set_dynack(uint8_t onoff);
|
||||
|
||||
void nRF24_update_config(uint8_t mask);
|
||||
|
||||
void nRF24_set_tx_config(uint8_t max_rt_flush, uint8_t new_done_state);
|
||||
|
||||
void nRF24_mode_rx();
|
||||
void nRF24_mode_tx();
|
||||
void nRF24_mode_standby();
|
||||
void nRF24_mode_off();
|
||||
uint8_t nRF24_mode_get();
|
||||
|
||||
uint8_t nRF24_data_is_ready(void);
|
||||
|
||||
int8_t nRF24_packet_rx(uint8_t status, void *pBuf);
|
||||
void nRF24_packet_tx(void *pBuf, uint8_t bytes, uint8_t noack);
|
||||
uint8_t nRF24_rx_received_pipe();
|
||||
|
||||
void nRF24_clear_irq_flags(void);
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* true's NRF24L01 C library
|
||||
* STM32L1xx interface driver
|
||||
* basically: it's better than nothing
|
||||
*
|
||||
* $Id: true_nRF24L01_stm32l1xx.c 375 2015-07-06 02:52:40Z true $
|
||||
*/
|
||||
|
||||
|
||||
#include "true_nRF24l01_stm32l1xx.h"
|
||||
|
||||
|
||||
/* hardware init */
|
||||
void nRF24_spi_init(uint16_t speed) {
|
||||
SPI_InitTypeDef spi;
|
||||
|
||||
spi.SPI_Mode = SPI_Mode_Master;
|
||||
spi.SPI_BaudRatePrescaler = speed;
|
||||
spi.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
|
||||
spi.SPI_CPOL = SPI_CPOL_Low;
|
||||
spi.SPI_CPHA = SPI_CPHA_1Edge;
|
||||
spi.SPI_CRCPolynomial = 7;
|
||||
spi.SPI_DataSize = SPI_DataSize_8b;
|
||||
spi.SPI_FirstBit = SPI_FirstBit_MSB;
|
||||
spi.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set;
|
||||
|
||||
SPI_Init(_TRNRF_SPI_PORT, &spi);
|
||||
SPI_Cmd(_TRNRF_SPI_PORT, ENABLE);
|
||||
}
|
||||
|
||||
void nRF24_interrupt_init()
|
||||
{
|
||||
EXTI_InitTypeDef exti;
|
||||
NVIC_InitTypeDef nvic;
|
||||
|
||||
// make sure SYSCFG clock is running
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
|
||||
// set up the IRQ pin to actually attach to an interrupt
|
||||
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource11); // IRQ pin, also see lonelywolf_nRF24L01.h
|
||||
|
||||
exti.EXTI_Line = EXTI_Line11; // EXTI will be on line 11
|
||||
exti.EXTI_LineCmd = ENABLE; // EXTI enabled
|
||||
exti.EXTI_Mode = EXTI_Mode_Interrupt; // Generate IRQ
|
||||
exti.EXTI_Trigger = EXTI_Trigger_Falling; // IRQ on signal falling
|
||||
EXTI_Init(&exti);
|
||||
|
||||
// and then enable this interrupt at the lowest priority
|
||||
nvic.NVIC_IRQChannel = EXTI15_10_IRQn;
|
||||
nvic.NVIC_IRQChannelCmd = ENABLE;
|
||||
nvic.NVIC_IRQChannelPreemptionPriority = 0x0F;
|
||||
nvic.NVIC_IRQChannelSubPriority = 0x0F;
|
||||
NVIC_Init(&nvic);
|
||||
}
|
||||
|
||||
|
||||
/* driver init */
|
||||
void nRF24_driver_init()
|
||||
{
|
||||
GPIO_InitTypeDef gpio;
|
||||
|
||||
#if _TRNRF_SPI_PORT_USE == 1
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); // SPI pins
|
||||
#elif _TRNRF_SPI_PORT_USE == 2
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
|
||||
RCC_AHBPeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
|
||||
#endif
|
||||
|
||||
// set up other pin clocks
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE); // CE/IRQ pins
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE); // CS pin
|
||||
|
||||
// Configure SPI pins GPIO
|
||||
gpio.GPIO_Speed = GPIO_Speed_10MHz;
|
||||
gpio.GPIO_OType = GPIO_OType_PP;
|
||||
gpio.GPIO_Mode = GPIO_Mode_AF;
|
||||
gpio.GPIO_Pin = _TRNRF_SPI_SCK_PIN | _TRNRF_SPI_MISO_PIN | _TRNRF_SPI_MOSI_PIN;
|
||||
GPIO_Init(_TRNRF_SPI_GPIO_PORT, &gpio);
|
||||
|
||||
// configure SPI pin AF
|
||||
GPIO_PinAFConfig(_TRNRF_SPI_GPIO_PORT, _TRNRF_SPI_SCK_PINSRC, _TRNRF_SPI_GPIO_AF);
|
||||
GPIO_PinAFConfig(_TRNRF_SPI_GPIO_PORT, _TRNRF_SPI_MISO_PINSRC, _TRNRF_SPI_GPIO_AF);
|
||||
GPIO_PinAFConfig(_TRNRF_SPI_GPIO_PORT, _TRNRF_SPI_MOSI_PINSRC, _TRNRF_SPI_GPIO_AF);
|
||||
|
||||
// configure CS pin as output with push-pull
|
||||
gpio.GPIO_Mode = GPIO_Mode_OUT;
|
||||
gpio.GPIO_Pin = _TRNRF_SPI_CS_PIN;
|
||||
GPIO_Init(_TRNRF_SPI_CS_PORT, &gpio);
|
||||
|
||||
// configure CE pin as output with push-pull
|
||||
gpio.GPIO_Pin = _TRNRF_nRF24_CE_PIN;
|
||||
GPIO_Init(_TRNRF_nRF24_CE_PORT, &gpio);
|
||||
|
||||
// configure IRQ pin as input with weak pull-Up
|
||||
gpio.GPIO_Mode = GPIO_Mode_IN;
|
||||
gpio.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
gpio.GPIO_Pin = _TRNRF_nRF24_IRQ_PIN;
|
||||
GPIO_Init(_TRNRF_nRF24_IRQ_PORT, &gpio);
|
||||
|
||||
// set SPI and CE pins to startup values
|
||||
_TRNRF_CSN_H();
|
||||
_TRNRF_CE_L();
|
||||
|
||||
// start up SPI and IRQ interrupt
|
||||
nRF24_spi_init(_TRNRF_SPI_BAUD);
|
||||
nRF24_interrupt_init();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Communicates with the nRF24L01 (or anything else, really) over SPI.
|
||||
*
|
||||
* Since this command can be used for bulk transfer, it does NOT do anything
|
||||
* with the SPI CS pin. Please check CS before and after using this function.
|
||||
*
|
||||
* @param data byte to send on SPI bus
|
||||
*
|
||||
* @return data returned on SPI bus
|
||||
*/
|
||||
uint8_t nRF24_spi_rw(uint8_t data) {
|
||||
// Wait while DR register is not empty
|
||||
while (SPI_I2S_GetFlagStatus(_TRNRF_SPI_PORT, SPI_I2S_FLAG_TXE) == RESET);
|
||||
// Send byte to SPI
|
||||
SPI_I2S_SendData(_TRNRF_SPI_PORT, data);
|
||||
// Wait to receive byte
|
||||
while (SPI_I2S_GetFlagStatus(_TRNRF_SPI_PORT, SPI_I2S_FLAG_RXNE) == RESET);
|
||||
// Read byte from SPI bus
|
||||
return SPI_I2S_ReceiveData(_TRNRF_SPI_PORT);
|
||||
}
|
||||
|
||||
|
||||
/* irq handler */
|
||||
void EXTI15_10_IRQHandler(void) {
|
||||
uint8_t status = 0;
|
||||
|
||||
if (EXTI_GetITStatus(EXTI_Line11) != RESET) {
|
||||
status = nRF24_interrupt();
|
||||
|
||||
// do anything custom here if you like
|
||||
|
||||
EXTI_ClearITPendingBit(EXTI_Line11);
|
||||
}
|
||||
|
||||
// fixes compiler warning for unused status
|
||||
status = status | 0x00;
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* true's NRF24L01 C library
|
||||
* STM32L1xx interface driver header
|
||||
* basically: it's better than nothing
|
||||
*
|
||||
* $Id: true_nRF24L01_stm32l1xx.h 375 2015-07-06 02:52:40Z true $
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __TRUE_NRF24L01_STM32L1XX_H
|
||||
#define __TRUE_NRF24L01_STM32L1XX_H
|
||||
|
||||
|
||||
|
||||
// include stm libraries
|
||||
#include "stm32l1xx_conf.h"
|
||||
|
||||
// and the nrf libraries
|
||||
#include "true_nrf24l01.h"
|
||||
|
||||
|
||||
/********************/
|
||||
/**** SPI SELECT ****/
|
||||
// which SPI to use?
|
||||
#define _TRNRF_SPI_PORT_USE 1
|
||||
#define _TRNRF_SPI_BAUD SPI_BaudRatePrescaler_4
|
||||
|
||||
// nRF24L01 CS (Chip Select) pin (SPI CS)
|
||||
#define _TRNRF_SPI_CS_PORT GPIOD
|
||||
#define _TRNRF_SPI_CS_PIN GPIO_Pin_2 // PD2
|
||||
|
||||
// nRF24L01 CE (Chip Enable) pin (handles RX/TX mode)
|
||||
#define _TRNRF_nRF24_CE_PORT GPIOC
|
||||
#define _TRNRF_nRF24_CE_PIN GPIO_Pin_10 // PC10
|
||||
|
||||
// nRF24L01 IRQ pin
|
||||
#define _TRNRF_nRF24_IRQ_PORT GPIOC
|
||||
#define _TRNRF_nRF24_IRQ_PIN GPIO_Pin_11 // PC11
|
||||
|
||||
|
||||
/********************/
|
||||
/**** SPI CONFIG ****/
|
||||
#if _TRNRF_SPI_PORT_USE == 1
|
||||
#define _TRNRF_SPI_PORT SPI1
|
||||
|
||||
#define _TRNRF_SPI_GPIO_AF GPIO_AF_SPI1
|
||||
#define _TRNRF_SPI_GPIO_PORT GPIOB
|
||||
|
||||
#define _TRNRF_SPI_SCK_PIN GPIO_Pin_3
|
||||
#define _TRNRF_SPI_MISO_PIN GPIO_Pin_4
|
||||
#define _TRNRF_SPI_MOSI_PIN GPIO_Pin_5
|
||||
#define _TRNRF_SPI_SCK_PINSRC GPIO_PinSource3
|
||||
#define _TRNRF_SPI_MISO_PINSRC GPIO_PinSource4
|
||||
#define _TRNRF_SPI_MOSI_PINSRC GPIO_PinSource5
|
||||
#elif _TRNRF_SPI_PORT_USE == 2
|
||||
#define _TRNRF_SPI_PORT SPI2
|
||||
|
||||
#define _TRNRF_SPI_GPIO_AF GPIO_AF_SPI2
|
||||
#define _TRNRF_SPI_GPIO_PORT GPIOB
|
||||
|
||||
#define _TRNRF_SPI_SCK_PIN GPIO_Pin_13
|
||||
#define _TRNRF_SPI_MISO_PIN GPIO_Pin_14
|
||||
#define _TRNRF_SPI_MOSI_PIN GPIO_Pin_15
|
||||
#define _TRNRF_SPI_SCK_PINSRC GPIO_PinSource13
|
||||
#define _TRNRF_SPI_MISO_PINSRC GPIO_PinSource14
|
||||
#define _TRNRF_SPI_MOSI_PINSRC GPIO_PinSource15
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/********************/
|
||||
/**** PIN MACROS ****/
|
||||
// chip-enable (activates rx/tx modes)
|
||||
#define _TRNRF_CE_L() GPIO_ResetBits(_TRNRF_nRF24_CE_PORT, _TRNRF_nRF24_CE_PIN)
|
||||
#define _TRNRF_CE_H() GPIO_SetBits(_TRNRF_nRF24_CE_PORT, _TRNRF_nRF24_CE_PIN)
|
||||
|
||||
// SPI chipselect
|
||||
#define _TRNRF_CSN_L() GPIO_ResetBits(_TRNRF_SPI_CS_PORT, _TRNRF_SPI_CS_PIN)
|
||||
#define _TRNRF_CSN_H() GPIO_SetBits(_TRNRF_SPI_CS_PORT, _TRNRF_SPI_CS_PIN)
|
||||
|
||||
|
||||
|
||||
/********************/
|
||||
/**** PROTOTYPES ****/
|
||||
void nRF24_driver_init();
|
||||
|
||||
uint8_t nRF24_spi_rw(uint8_t data);
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* cgram.c: lcd cgram graphics constants
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: cgram.c 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
const uint8_t cgram_crown[6][8] = {
|
||||
{0x00, 0x00, 0x1C, 0x14, 0x1C, 0x0C, 0x0A, 0x09},
|
||||
{0x0E, 0x0A, 0x0E, 0x04, 0x04, 0x0A, 0x11, 0x00},
|
||||
{0x00, 0x00, 0x07, 0x05, 0x07, 0x06, 0x0A, 0x12},
|
||||
{0x08, 0x08, 0x09, 0x0E, 0x08, 0x0F, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x00},
|
||||
{0x02, 0x02, 0x12, 0x0E, 0x02, 0x1E, 0x00, 0x00}
|
||||
};
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* cgram.h: lcd cgram graphics constants
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: cgram.h 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_DISPLAY_CGRAM_H
|
||||
#define __PIRATE_DISPLAY_CGRAM_H
|
||||
|
||||
|
||||
|
||||
extern const uint8_t cgram_crown[6][8];
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,103 @@
|
|||
/**
|
||||
* infopirate.c: namebadge and other information animated 8x2 display
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: infopirate.c 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#include <pirate.h>
|
||||
|
||||
#include "../device/lcd.h"
|
||||
|
||||
#include "../menu/lcd_menu.h" // for lcd_line
|
||||
|
||||
#include "infopirate.h"
|
||||
#include "infopirate_prog.h"
|
||||
|
||||
#include "cgram/cgram.h"
|
||||
|
||||
|
||||
uint8_t prog_idx; // currently selected program
|
||||
uint8_t prog_loop; // current loop thru program
|
||||
|
||||
uint8_t (*infopirate_prog)(void);
|
||||
uint8_t (*infopirate_prog_list[])() = {
|
||||
&infopirate_prog_scroll_name_in_left,
|
||||
&infopirate_prog_nameonly,
|
||||
&infopirate_prog_scroll_name_out_left,
|
||||
&infopirate_prog_logo01,
|
||||
&infopirate_prog_logo02
|
||||
};
|
||||
const uint8_t prog_loop_run[] = { // amount of passes per program in static mode
|
||||
1,
|
||||
10,
|
||||
1,
|
||||
1,
|
||||
1
|
||||
};
|
||||
|
||||
|
||||
/* functions */
|
||||
void infopirate_init()
|
||||
{
|
||||
prog_wait = 0;
|
||||
prog_loop = 0;
|
||||
prog_idx = 0;
|
||||
infopirate_prog = NULL;
|
||||
}
|
||||
|
||||
static void infopirate_next_prog()
|
||||
{
|
||||
prog_wait = 0; // infopirate_prog.h
|
||||
prog_loop = 0;
|
||||
prog_idx++;
|
||||
|
||||
if (prog_idx >= sizeof_array(infopirate_prog_list)) prog_idx = 0;
|
||||
|
||||
infopirate_prog = infopirate_prog_list[prog_idx];
|
||||
}
|
||||
|
||||
void infopirate_update()
|
||||
{
|
||||
uint8_t state;
|
||||
|
||||
state = INFOPIRATE_PROG_NONE;
|
||||
|
||||
if (infopirate_prog != NULL) {
|
||||
state = infopirate_prog();
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case INFOPIRATE_PROG_NONE: {
|
||||
prog_idx = 0;
|
||||
prog_loop = 0;
|
||||
infopirate_prog = infopirate_prog_list[0];
|
||||
break;
|
||||
}
|
||||
case INFOPIRATE_PROG_DONE: {
|
||||
prog_loop++;
|
||||
if (prog_loop >= prog_loop_run[prog_idx]) {
|
||||
infopirate_next_prog();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void menu_infopirate_btn_prev()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void menu_infopirate_btn_next()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void menu_infopirate_btn_ok()
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* infopirate.h: namebadge and other information animated 8x2 display
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: infopirate.h 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_DISPLAY_INFOPIRATE_H
|
||||
#define __PIRATE_DISPLAY_INFOPIRATE_H
|
||||
|
||||
|
||||
|
||||
#define INFOPIRATE_PROG_NONE 0x00
|
||||
#define INFOPIRATE_PROG_PAUSED 0x01
|
||||
#define INFOPIRATE_PROG_RUNNING 0x02
|
||||
#define INFOPIRATE_PROG_DONE 0xFE
|
||||
|
||||
|
||||
/* prototypes */
|
||||
void infopirate_init();
|
||||
|
||||
void infopirate_update();
|
||||
|
||||
void menu_infopirate_btn_prev();
|
||||
void menu_infopirate_btn_next();
|
||||
void menu_infopirate_btn_ok();
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,158 @@
|
|||
/**
|
||||
* infopirate_prog.h: program functions for badge related bullshit
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: infopirate_prog.h 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#include "../menu/lcd_menu.h"
|
||||
#include "cgram/cgram.h" // for CGRAM graphics tables
|
||||
|
||||
|
||||
uint16_t prog_wait; // used by function to keep track of iteration time
|
||||
uint32_t prog_state[4]; // used by the function to keep track of state
|
||||
uint32_t prog_work[2]; // used for misc shit
|
||||
|
||||
|
||||
/* functions */
|
||||
uint8_t infopirate_prog_nameonly()
|
||||
{
|
||||
if (!prog_wait) {
|
||||
prog_wait = 100;
|
||||
lcd_set_height(LCD_CMD_DOUBLEHEIGHT);
|
||||
}
|
||||
|
||||
strncpy(lcd_line[0], settings.name, 8);
|
||||
|
||||
prog_wait--;
|
||||
return prog_wait ? INFOPIRATE_PROG_RUNNING : INFOPIRATE_PROG_DONE;
|
||||
}
|
||||
|
||||
uint8_t infopirate_prog_scroll_name_in_left()
|
||||
{
|
||||
if (!prog_wait) {
|
||||
prog_wait = 121;
|
||||
prog_state[0] = 8;
|
||||
lcd_set_height(LCD_CMD_DOUBLEHEIGHT);
|
||||
} else if (prog_wait % 15 == 0) {
|
||||
if (prog_state[0]) prog_state[0]--;
|
||||
|
||||
strncpy(lcd_line[0], " ", 8); // make the line all spaces
|
||||
if (prog_state[0] < 8) {
|
||||
lcd_line[0][prog_state[0]] = 0x00; // set our null
|
||||
strncat(lcd_line[0], settings.name, 8); // copy our name
|
||||
}
|
||||
}
|
||||
|
||||
prog_wait--;
|
||||
return prog_wait ? INFOPIRATE_PROG_RUNNING : INFOPIRATE_PROG_DONE;
|
||||
}
|
||||
|
||||
uint8_t infopirate_prog_scroll_name_out_left()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (!prog_wait) {
|
||||
prog_wait = 121;
|
||||
prog_state[0] = 0;
|
||||
lcd_set_height(LCD_CMD_DOUBLEHEIGHT);
|
||||
} else if (prog_wait % 15 == 0) {
|
||||
if (prog_state[0] < 7) prog_state[0]++;
|
||||
|
||||
strncpy(lcd_line[0], " ", 8); // make the line all spaces
|
||||
j = 0;
|
||||
for (i = prog_state[0]; i < 8; i++) {
|
||||
lcd_line[0][j++] = settings.name[i];
|
||||
}
|
||||
}
|
||||
|
||||
prog_wait--;
|
||||
return prog_wait ? INFOPIRATE_PROG_RUNNING : INFOPIRATE_PROG_DONE;
|
||||
}
|
||||
|
||||
uint8_t infopirate_prog_logo01()
|
||||
{
|
||||
int i;
|
||||
|
||||
static const char line1[8] = {0x00, 0x01, 0x02, 'T', 'h', 'r', 'e', 'e'};
|
||||
static const char line2[8] = {0x03, 0x04, 0x05, 'K', 'i', 'n', 'g', 's'};
|
||||
|
||||
if (!prog_wait) {
|
||||
// set our state timer
|
||||
prog_wait = 400;
|
||||
prog_state[0] = 0;
|
||||
|
||||
// enable CGRAM
|
||||
lcd_set_height(LCD_CMD_SINGLEHEIGHT & 0xfe); // enable cgram
|
||||
|
||||
// set the CGRAM data to load
|
||||
lcd_set_cgram_load(cgram_crown, sizeof_array(cgram_crown));
|
||||
|
||||
// set data
|
||||
for (i = 0; i < 8; i++) {
|
||||
lcd_line[0][i] = line1[i];
|
||||
lcd_line[1][i] = line2[i];
|
||||
}
|
||||
}
|
||||
|
||||
prog_wait--;
|
||||
return prog_wait ? INFOPIRATE_PROG_RUNNING : INFOPIRATE_PROG_DONE;
|
||||
}
|
||||
|
||||
uint8_t infopirate_prog_logo02()
|
||||
{
|
||||
// prog_state[0] is the current character on this line to print
|
||||
// prog_work[0] is the current character overall to print
|
||||
// prog_work[1] is the current position of the character
|
||||
if (!prog_wait) {
|
||||
// new setup
|
||||
prog_wait = 9;
|
||||
prog_state[0] = 0; // first character
|
||||
prog_work[0] = 0; // first character
|
||||
prog_work[1] = 8; // scrolling from right, set to last character
|
||||
|
||||
// clear strings for new setup
|
||||
strncpy(lcd_line[0], " ", 8);
|
||||
strncpy(lcd_line[1], " ", 8);
|
||||
} else if (prog_work[0] == 16) {
|
||||
// we're done. wait a while
|
||||
prog_wait = 210;
|
||||
prog_work[0]++;
|
||||
} else if (prog_wait == 1) {
|
||||
// loop timeout expired, reload timer and process
|
||||
prog_wait = 9;
|
||||
|
||||
static const char line1[] = "Whiskey ";
|
||||
static const char line2[] = " Pirates";
|
||||
|
||||
lcd_set_height(LCD_CMD_SINGLEHEIGHT);
|
||||
|
||||
// did our character reach the end?
|
||||
if (prog_work[1] <= prog_state[0]) {
|
||||
// then go to the next character and reset right position
|
||||
prog_work[0]++;
|
||||
prog_state[0] = prog_work[0] & 0x07;
|
||||
prog_work[1] = 8;
|
||||
}
|
||||
|
||||
// do we have characters left to update?
|
||||
if (prog_work[0] < 16) {
|
||||
// working variables
|
||||
char *src = prog_work[0] < 8 ? (char *)line1 : (char *)line2;
|
||||
char *target = prog_work[0] < 8 ? lcd_line[0] : lcd_line[1];
|
||||
|
||||
// set the character one less than prog_work[1] to our target
|
||||
target[prog_work[1] - 1] = src[prog_state[0]];
|
||||
// if this isn't the last one, set the current working character to a space
|
||||
if (prog_work[1] < 8) target[prog_work[1]] = 0x20;
|
||||
// and continue scrolling our character in to the left
|
||||
prog_work[1]--;
|
||||
}
|
||||
}
|
||||
|
||||
prog_wait--;
|
||||
return (prog_wait != 10) ? INFOPIRATE_PROG_RUNNING : INFOPIRATE_PROG_DONE;
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
/**
|
||||
* adc.h: manager for anything adc-related
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: adc.c 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
|
||||
#include <pirate.h>
|
||||
|
||||
#include "adc.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
const tGPIO adc_gpio[] = {
|
||||
{GPIOA, GPIO_Pin_5, 5}, // mic sig detect
|
||||
{GPIOB, GPIO_Pin_0, 0}, // mic peak detect
|
||||
{GPIOB, GPIO_Pin_0, 1}, // battery voltage
|
||||
};
|
||||
|
||||
uint8_t adc_chan;
|
||||
uint16_t adc_result[ADC_MAX_RESULT_COUNT];
|
||||
|
||||
|
||||
/* functions */
|
||||
void adc_init()
|
||||
{
|
||||
GPIO_InitTypeDef gpio;
|
||||
ADC_CommonInitTypeDef adc_com;
|
||||
ADC_InitTypeDef adc_init;
|
||||
NVIC_InitTypeDef nvic;
|
||||
|
||||
int i;
|
||||
|
||||
// make sure the HSI is turned on - STM32L1xx uses HSI only for ADC
|
||||
RCC_HSICmd(ENABLE);
|
||||
|
||||
// enable ADC clock
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
|
||||
|
||||
// set up pins as analog inputs
|
||||
// NOTE: clocks were likely enabled earlier. fix if they weren't.
|
||||
gpio.GPIO_Mode = GPIO_Mode_AN;
|
||||
gpio.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
gpio.GPIO_Pin = adc_gpio[i].pin;
|
||||
GPIO_Init(adc_gpio[i].port, &gpio);
|
||||
}
|
||||
|
||||
// configure ADC initial values
|
||||
ADC_CommonStructInit(&adc_com);
|
||||
ADC_StructInit(&adc_init);
|
||||
adc_init.ADC_ExternalTrigConv = 0;
|
||||
|
||||
// set up channels to read
|
||||
ADC_RegularChannelConfig(ADC1, ADC_CHAN_MIC_SIG, ADC_READ_MIC_SIG + 1, ADC_SampleTime_4Cycles);
|
||||
ADC_RegularChannelConfig(ADC1, ADC_CHAN_MIC_PEAK, ADC_READ_MIC_PEAK + 1, ADC_SampleTime_4Cycles);
|
||||
ADC_RegularChannelConfig(ADC1, ADC_CHAN_BATT_VOLTAGE, ADC_READ_BATT_VOLTAGE + 1, ADC_SampleTime_4Cycles);
|
||||
adc_init.ADC_ScanConvMode = ENABLE;
|
||||
adc_init.ADC_NbrOfConversion = 3;
|
||||
|
||||
// enable end of conversion on each channel read
|
||||
ADC_EOCOnEachRegularChannelCmd(ADC1, ENABLE);
|
||||
|
||||
// freeze ADC until data has been read
|
||||
ADC_DelaySelectionConfig(ADC1, ADC_DelayLength_Freeze);
|
||||
|
||||
// initialize the ADC
|
||||
ADC_CommonInit(&adc_com);
|
||||
ADC_Init(ADC1, &adc_init);
|
||||
|
||||
// it doesn't look like STM32L100 has auto-calibrate feature,
|
||||
// but if it did, we'd set it up here. baw.
|
||||
|
||||
// set up ADC power saving
|
||||
ADC_PowerDownCmd(ADC1, ADC_PowerDown_Idle_Delay, ENABLE);
|
||||
|
||||
// enable interrupt
|
||||
ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
|
||||
|
||||
// set interrupt priority
|
||||
nvic.NVIC_IRQChannel = ADC1_IRQn;
|
||||
nvic.NVIC_IRQChannelPreemptionPriority = 3;
|
||||
nvic.NVIC_IRQChannelSubPriority = 0;
|
||||
nvic.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&nvic);
|
||||
|
||||
// finally, turn on the ADC
|
||||
ADC_Cmd(ADC1, ENABLE);
|
||||
}
|
||||
|
||||
void adc_deinit()
|
||||
{
|
||||
// reset ADC
|
||||
ADC_DeInit(ADC1);
|
||||
|
||||
// and disable ADC clock
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, DISABLE);
|
||||
}
|
||||
|
||||
void adc_start()
|
||||
{
|
||||
int adc_timeout = 200;
|
||||
|
||||
adc_chan = 0;
|
||||
|
||||
// verify ADC is powered up
|
||||
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == RESET) {
|
||||
ADC_Cmd(ADC1, ENABLE);
|
||||
if (--adc_timeout == 0) {
|
||||
adc_result[2] |= 0xf000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// then start conversion if ADC is on
|
||||
if (ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == SET) {
|
||||
ADC_SoftwareStartConv(ADC1);
|
||||
}
|
||||
}
|
||||
|
||||
void ADC1_IRQHandler()
|
||||
{
|
||||
if (adc_chan < ADC_MAX_RESULT_COUNT) {
|
||||
adc_result[adc_chan] = ADC_GetConversionValue(ADC1);
|
||||
adc_chan++;
|
||||
}
|
||||
|
||||
ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* adc.h: prototypes for adc functions
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: adc.h 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_IF_ADC_H
|
||||
#define __PIRATE_IF_ADC_H
|
||||
|
||||
|
||||
|
||||
#define ADC_MAX_RESULT_COUNT 3 // channels in use
|
||||
|
||||
#define ADC_READ_MIC_SIG 0
|
||||
#define ADC_READ_MIC_PEAK 1
|
||||
#define ADC_READ_BATT_VOLTAGE 2
|
||||
|
||||
#define ADC_CHAN_MIC_SIG ADC_Channel_5
|
||||
#define ADC_CHAN_MIC_PEAK ADC_Channel_8
|
||||
#define ADC_CHAN_BATT_VOLTAGE ADC_Channel_9
|
||||
|
||||
|
||||
extern uint16_t adc_result[ADC_MAX_RESULT_COUNT];
|
||||
|
||||
|
||||
void adc_init();
|
||||
void adc_deinit();
|
||||
|
||||
void adc_channel(uint8_t rank);
|
||||
void adc_start();
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* pirate gpio interface
|
||||
* 2014 true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: gpio.c 327 2015-02-18 04:43:42Z true $
|
||||
**/
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* gpio.h: pirate gpio interface
|
||||
* 2014 true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: gpio.h 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_IF_GPIO_H
|
||||
#define __PIRATE_IF_GPIO_H
|
||||
|
||||
|
||||
|
||||
#define BIT_0 1
|
||||
#define BIT_1 (1 << 1)
|
||||
#define BIT_2 (1 << 2)
|
||||
#define BIT_3 (1 << 3)
|
||||
#define BIT_4 (1 << 4)
|
||||
#define BIT_5 (1 << 5)
|
||||
#define BIT_6 (1 << 6)
|
||||
#define BIT_7 (1 << 7)
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
|
||||
|
||||
typedef struct tGPIO {
|
||||
GPIO_TypeDef *port;
|
||||
uint16_t pin;
|
||||
uint8_t pinsource;
|
||||
} tGPIO;
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
* i2c.h: pirate i2c interface, command and data buffering, and data receive callbacks
|
||||
* 2014 true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: i2c.c 368 2015-06-16 06:49:48Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
|
||||
#include <pirate.h>
|
||||
|
||||
#include "i2c.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
#define I2C_GPIO_SCL 0
|
||||
#define I2C_GPIO_SDA 1
|
||||
|
||||
static const tGPIO i2c_pins[2][2] = {
|
||||
{ // i2c1
|
||||
{GPIOB, GPIO_Pin_8, 8}, // scl
|
||||
{GPIOB, GPIO_Pin_9, 9} // sda
|
||||
},
|
||||
{ // i2c2
|
||||
{GPIOB, GPIO_Pin_10, 10}, // scl
|
||||
{GPIOB, GPIO_Pin_11, 11} // sda
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* functions */
|
||||
void i2c_init(I2C_TypeDef *i2cdev, uint32_t speed)
|
||||
{
|
||||
GPIO_InitTypeDef gpio;
|
||||
I2C_InitTypeDef i2c;
|
||||
|
||||
int i2c_idx;
|
||||
|
||||
if (i2cdev == I2C1) {
|
||||
i2c_idx = 0;
|
||||
} else {
|
||||
i2c_idx = 1;
|
||||
}
|
||||
|
||||
// enable peripheral clocks
|
||||
// GPIOB is already enabled by LED driver
|
||||
if (i2cdev == I2C1) {
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
|
||||
} else if (i2cdev == I2C2) {
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
|
||||
// and reset it (silicon bug?)
|
||||
RCC_AHBPeriphResetCmd(RCC_APB1Periph_I2C2, ENABLE);
|
||||
RCC_AHBPeriphResetCmd(RCC_APB1Periph_I2C2, DISABLE);
|
||||
}
|
||||
|
||||
// set up peripheral
|
||||
I2C_StructInit(&i2c);
|
||||
i2c.I2C_ClockSpeed = speed;
|
||||
I2C_Init(i2cdev, &i2c);
|
||||
|
||||
// set up pins
|
||||
gpio.GPIO_Mode = GPIO_Mode_AF;
|
||||
gpio.GPIO_OType = GPIO_OType_OD;
|
||||
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
gpio.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
|
||||
gpio.GPIO_Pin = i2c_pins[i2c_idx][I2C_GPIO_SCL].pin | i2c_pins[i2c_idx][I2C_GPIO_SDA].pin;
|
||||
GPIO_Init(i2c_pins[i2c_idx][I2C_GPIO_SCL].port, &gpio);
|
||||
|
||||
// set pin alternate function
|
||||
GPIO_PinAFConfig(i2c_pins[i2c_idx][I2C_GPIO_SCL].port,
|
||||
i2c_pins[i2c_idx][I2C_GPIO_SCL].pinsource, GPIO_AF_I2C1);
|
||||
GPIO_PinAFConfig(i2c_pins[i2c_idx][I2C_GPIO_SDA].port,
|
||||
i2c_pins[i2c_idx][I2C_GPIO_SDA].pinsource, GPIO_AF_I2C1);
|
||||
|
||||
// enable the i2c interrupts
|
||||
|
||||
// enable peripheral
|
||||
I2C_Cmd(i2cdev, ENABLE);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* i2c.h: pirate i2c interface, command and data buffering, and data receive callbacks
|
||||
* 2014 true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: i2c.h 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_I2C_H
|
||||
#define __PIRATE_I2C_H
|
||||
|
||||
|
||||
|
||||
// we're using this guy's library because it seems to work
|
||||
#include "peter_i2c/peter_i2c.h"
|
||||
|
||||
|
||||
#define I2C_BUF_SIZE 16 // power of 2
|
||||
|
||||
#define I2C_READ I2C_Direction_Receiver
|
||||
#define I2C_WRITE I2C_Direction_Transmitter
|
||||
|
||||
|
||||
/* prototypes */
|
||||
void i2c_init(I2C_TypeDef *i2c, uint32_t speed);
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* led_pwm.c: led pwm configuration functions
|
||||
* 2014 true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: led_pwm.c 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#include <pirate.h>
|
||||
|
||||
#include "led_pwm.h"
|
||||
|
||||
|
||||
/* functions */
|
||||
void led_pwm_init(TIM_TypeDef *timer, uint16_t polarity, uint8_t channel_mask)
|
||||
{
|
||||
TIM_TimeBaseInitTypeDef tim_tb;
|
||||
TIM_OCInitTypeDef tim_oc;
|
||||
|
||||
// set up with 250 levels of brightness
|
||||
tim_tb.TIM_Prescaler = 5 - 1; // 6.4MHz
|
||||
tim_tb.TIM_Period = 256 - 1; // 25KHz PWM, 5 updates/LED
|
||||
tim_tb.TIM_ClockDivision = 0;
|
||||
tim_tb.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_TimeBaseInit(timer, &tim_tb);
|
||||
|
||||
// configure outputs as pwm
|
||||
tim_oc.TIM_OCMode = TIM_OCMode_PWM1;
|
||||
tim_oc.TIM_OutputState = TIM_OutputState_Enable;
|
||||
tim_oc.TIM_Pulse = 0;
|
||||
tim_oc.TIM_OCPolarity = polarity;
|
||||
|
||||
// configure pin for PWM output mode, enable preload
|
||||
if (channel_mask & 0x01) {
|
||||
TIM_OC1Init(timer, &tim_oc);
|
||||
TIM_OC1PreloadConfig(timer, TIM_OCPreload_Enable);
|
||||
}
|
||||
if (channel_mask & 0x02) {
|
||||
TIM_OC2Init(timer, &tim_oc);
|
||||
TIM_OC2PreloadConfig(timer, TIM_OCPreload_Enable);
|
||||
}
|
||||
if (channel_mask & 0x04) {
|
||||
TIM_OC3Init(timer, &tim_oc);
|
||||
TIM_OC3PreloadConfig(timer, TIM_OCPreload_Enable);
|
||||
}
|
||||
if (channel_mask & 0x08) {
|
||||
TIM_OC4Init(timer, &tim_oc);
|
||||
TIM_OC4PreloadConfig(timer, TIM_OCPreload_Enable);
|
||||
}
|
||||
|
||||
// finally, enable the timer
|
||||
TIM_ARRPreloadConfig(timer, ENABLE);
|
||||
TIM_Cmd(timer, ENABLE);
|
||||
}
|
||||
|
||||
void led_pwm_init_all()
|
||||
{
|
||||
// enable peripheral clock and configure timers with PWM settings
|
||||
|
||||
// main led matrix
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
||||
led_pwm_init(TIM2, TIM_OCPolarity_High,
|
||||
LED_PWM_CH1 | LED_PWM_CH2 | LED_PWM_CH3 | LED_PWM_CH4);
|
||||
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
|
||||
led_pwm_init(TIM3, TIM_OCPolarity_High,
|
||||
LED_PWM_CH1 | LED_PWM_CH2 | LED_PWM_CH3 | LED_PWM_CH4);
|
||||
|
||||
// bone led matrix
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM11, ENABLE);
|
||||
led_pwm_init(TIM11, TIM_OCPolarity_High, LED_PWM_CH1);
|
||||
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE);
|
||||
led_pwm_init(TIM9, TIM_OCPolarity_High, LED_PWM_CH1 | LED_PWM_CH2);
|
||||
}
|
||||
|
||||
void led_pwm_set_oc(TIM_TypeDef *timer, uint32_t *oc)
|
||||
{
|
||||
timer->CCR1 = *oc++;
|
||||
|
||||
if (timer == TIM9) {
|
||||
timer->CCR2 = *oc++;
|
||||
} else if (timer == TIM2 || timer == TIM3 || timer == TIM4) {
|
||||
timer->CCR2 = *oc++;
|
||||
timer->CCR3 = *oc++;
|
||||
timer->CCR4 = *oc;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* led_pwm.h: led pwm configuration prototypes
|
||||
* 2014 true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: led_pwm.h 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_LED_PWM_H
|
||||
#define __PIRATE_LED_PWM_H
|
||||
|
||||
|
||||
|
||||
#define LED_PWM_CH1 0x01
|
||||
#define LED_PWM_CH2 0x02
|
||||
#define LED_PWM_CH3 0x04
|
||||
#define LED_PWM_CH4 0x08
|
||||
|
||||
|
||||
/* prototypes */
|
||||
void led_pwm_init_all();
|
||||
void led_pwm_set_oc(TIM_TypeDef *timer, uint32_t *oc);
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,351 @@
|
|||
#include "peter_i2c.h"
|
||||
|
||||
//-------------------------------------------
|
||||
// Definition of local constants
|
||||
//-------------------------------------------
|
||||
#define I2C_TIMEOUT (0x1000)
|
||||
|
||||
//-------------------------------------------
|
||||
// Declaration of local functions
|
||||
//-------------------------------------------
|
||||
static int I2C_check_dev(uint8_t addr);
|
||||
static int I2C_start(I2C_TypeDef* I2Cx, uint8_t addr, uint8_t rdwr);
|
||||
static int I2C_restart(I2C_TypeDef* I2Cx, uint8_t addr, uint8_t rdwr);
|
||||
static int I2C_stop(I2C_TypeDef* I2Cx);
|
||||
static int I2C_write(I2C_TypeDef* I2Cx, uint8_t data);
|
||||
static int I2C_read(I2C_TypeDef* I2Cx, uint8_t ack);
|
||||
// static int I2C_timeout(char *msg);
|
||||
static int I2C_timeout(uint8_t flag);
|
||||
|
||||
/*
|
||||
NVIC_InitStructure.NVIC_IRQChannel = PeterI2C_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
*/
|
||||
|
||||
//===============================================================================
|
||||
// I2C_ReadTransfer - initiate a read transfer on the I2C bus
|
||||
//
|
||||
// Initiates a read transfer on the I2C bus.
|
||||
// If a register address is specified (<addressLength> != 0) a write without a stop
|
||||
// condition will be initiated to the device to write the address, before the
|
||||
// read is initiated.
|
||||
// If no address if required (sequential read) <addressLength> is set to 0.
|
||||
//-------------------------------------------------------------------------------
|
||||
// u08 dev_addr I2C device address
|
||||
// u08 *buffer pointer to the buffer to store the read data.
|
||||
// The buffer must be at least 'cnt' bytes long
|
||||
// int cnt number of bytes to read
|
||||
// u32 ptr register address, if required by the I2C-device
|
||||
// u08 ptrlen length of the register address to be written.
|
||||
// Valid values are 0..4
|
||||
//-------------------------------------------------------------------------------
|
||||
int I2C_ReadTransfer(uint8_t dev_addr, uint8_t *buffer, int cnt, uint32_t ptr, uint8_t ptrlen)
|
||||
{
|
||||
int i;
|
||||
int rc = SUCCESS;
|
||||
//-----------------------------------------------------------------------------
|
||||
// parameter check
|
||||
//-----------------------------------------------------------------------------
|
||||
if ((buffer == 0) || (ptrlen > 4) || ((cnt | ptrlen) == 0))
|
||||
{
|
||||
return I2C_check_dev(dev_addr); // may be used to check if device is responding
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// write the register address pointer to the device
|
||||
//-----------------------------------------------------------------------------
|
||||
if (ptrlen > 0)
|
||||
{
|
||||
rc = I2C_start(PeterI2C, dev_addr, I2C_Direction_Transmitter);
|
||||
if (rc == SUCCESS)
|
||||
{
|
||||
for (i=1; i<=ptrlen; i++)
|
||||
{
|
||||
rc |= I2C_write(PeterI2C,((ptr >>(8*(ptrlen-i))) & 0xff));
|
||||
}
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// read data from device
|
||||
//-----------------------------------------------------------------------------
|
||||
if ((cnt > 0) && (rc == SUCCESS))
|
||||
{
|
||||
if (ptrlen > 0)
|
||||
{
|
||||
rc |= I2C_restart(PeterI2C, dev_addr, I2C_Direction_Receiver);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc |= I2C_start(PeterI2C, dev_addr, I2C_Direction_Receiver);
|
||||
}
|
||||
if (rc == SUCCESS)
|
||||
{
|
||||
while (--cnt>0) // while more than one byte to read
|
||||
{
|
||||
*(buffer++) = I2C_read(PeterI2C, 1); // read next databyte from I2C device
|
||||
}
|
||||
*(buffer) = I2C_read(PeterI2C, 0); // read last databyte from I2C device
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
I2C_stop(PeterI2C); // stop the transmission
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
//===============================================================================
|
||||
// I2C_WriteTransfer r- initiate a write transfer on the I2C bus
|
||||
//
|
||||
// Initiates a write transfer on the I2C bus.
|
||||
// If a register address is supplied it is inserted between the I2C device address
|
||||
// and the data.
|
||||
//-------------------------------------------------------------------------------
|
||||
// u08 dev_addr I2C device address
|
||||
// u08 *buffer pointer to the buffer to store the read data.
|
||||
// The buffer must be at least 'cnt' bytes long
|
||||
// int cnt number of bytes to read
|
||||
// u32 ptr register address, if required by the I2C-device
|
||||
// u08 ptrlen length of the register address to be written.
|
||||
// Valid values are 0..4
|
||||
//-------------------------------------------------------------------------------
|
||||
int I2C_WriteTransfer(uint8_t dev_addr, uint8_t *buffer, int cnt, uint32_t ptr, uint8_t ptrlen)
|
||||
{
|
||||
int i;
|
||||
int rc = SUCCESS;
|
||||
//-----------------------------------------------------------------------------
|
||||
// parameter check
|
||||
//-----------------------------------------------------------------------------
|
||||
if ((buffer == 0) || (ptrlen > 4) || ((cnt | ptrlen) == 0))
|
||||
{
|
||||
return I2C_check_dev(dev_addr); // may be used to check if device is responding
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
rc = I2C_start(PeterI2C, dev_addr, I2C_Direction_Transmitter);
|
||||
if (rc == SUCCESS)
|
||||
{
|
||||
//---------------------------------------------------------------------------
|
||||
// write the register address pointer to the device
|
||||
//---------------------------------------------------------------------------
|
||||
if (ptrlen > 0)
|
||||
{
|
||||
for (i=1; i<=ptrlen; i++)
|
||||
{
|
||||
rc |= I2C_write(PeterI2C,((ptr >>(8*(ptrlen-i))) & 0xff));
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
// write data to the device
|
||||
//---------------------------------------------------------------------------
|
||||
for (i=0; i<cnt; i++)
|
||||
{
|
||||
rc |= I2C_write(PeterI2C,*(buffer++));
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
I2C_stop(PeterI2C); // stop the transmission
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
//===============================================================================
|
||||
// Check if a device is responding with acknowledge on the given I2C-Bus address
|
||||
//-------------------------------------------------------------------------------
|
||||
static int I2C_check_dev(uint8_t addr)
|
||||
{
|
||||
int timeout;
|
||||
//-----------------------------------------------------------------------------
|
||||
timeout = I2C_TIMEOUT;
|
||||
while(I2C_GetFlagStatus(PeterI2C, I2C_FLAG_BUSY))
|
||||
{
|
||||
if((timeout--)==0) // wait until I2C-Bus is not busy anymore
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
I2C_GenerateSTART(PeterI2C, ENABLE);
|
||||
timeout = I2C_TIMEOUT;
|
||||
while(!I2C_CheckEvent(PeterI2C, I2C_EVENT_MASTER_MODE_SELECT))
|
||||
{
|
||||
if((timeout--)==0) // wait while sending I2C-Bus START condition
|
||||
{
|
||||
I2C_GenerateSTOP(PeterI2C, ENABLE);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
I2C_Send7bitAddress(PeterI2C, addr, I2C_Direction_Transmitter);
|
||||
timeout = I2C_TIMEOUT;
|
||||
while(!I2C_CheckEvent(PeterI2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
|
||||
{
|
||||
if((timeout--)==0) // wait while sending slave address for write
|
||||
{
|
||||
I2C_GenerateSTOP(PeterI2C, ENABLE);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
I2C_GenerateSTOP(PeterI2C, ENABLE);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// This function issues a start condition and
|
||||
// transmits the slave address + R/W bit
|
||||
//
|
||||
// Parameters:
|
||||
// I2Cx --> the I2C peripheral e.g. I2C1
|
||||
// addr --> the 7 bit slave address
|
||||
// rdwr --> the tranmission direction can be:
|
||||
// I2C_Direction_Tranmitter for Master transmitter mode
|
||||
// I2C_Direction_Receiver for Master receiver
|
||||
//------------------------------------------------------------------
|
||||
static int I2C_start(I2C_TypeDef* I2Cx, uint8_t addr, uint8_t rdwr)
|
||||
{
|
||||
uint32_t timeout = (100 * I2C_TIMEOUT);
|
||||
// wait until I2C1 is not busy anymore
|
||||
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY))
|
||||
{
|
||||
if((timeout--)==0) return I2C_timeout(I2C_TFLAG_BUS_BUSY);//I2C_timeout("I2C_start(): bus busy");
|
||||
}
|
||||
// Send I2C1 RESTART condition
|
||||
return I2C_restart(I2Cx, addr, rdwr);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// This function issues a restart condition and
|
||||
// transmits the slave address + R/W bit
|
||||
//
|
||||
// Parameters:
|
||||
// I2Cx --> the I2C peripheral e.g. I2C1
|
||||
// addr --> the 7 bit slave address
|
||||
// rdwr --> the tranmission direction can be:
|
||||
// I2C_Direction_Tranmitter for Master transmitter mode
|
||||
// I2C_Direction_Receiver for Master receiver
|
||||
//------------------------------------------------------------------
|
||||
static int I2C_restart(I2C_TypeDef* I2Cx, uint8_t addr, uint8_t rdwr)
|
||||
{
|
||||
uint32_t timeout = I2C_TIMEOUT;
|
||||
// Send I2C1 START condition
|
||||
I2C_GenerateSTART(I2Cx, ENABLE);
|
||||
// wait for I2C1 EV5 --> Slave has acknowledged start condition
|
||||
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
|
||||
{
|
||||
if((timeout--)==0) return I2C_timeout(I2C_TFLAG_START_FAILED);//I2C_timeout("I2C_start(): start failed");
|
||||
}
|
||||
// Send slave Address for read or write
|
||||
I2C_Send7bitAddress(I2Cx, addr << 1, rdwr);
|
||||
//------------------------------------------------------------------------
|
||||
// wait for I2C1 EV6, check if Slave has acknowledged Master transmitter
|
||||
// or Master receiver mode, depending on the transmission direction
|
||||
//------------------------------------------------------------------------
|
||||
timeout = I2C_TIMEOUT;
|
||||
if (rdwr==I2C_Direction_Transmitter)
|
||||
{
|
||||
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
|
||||
{
|
||||
if((timeout--)==0) return I2C_timeout(I2C_TFLAG_NO_ACK);//I2C_timeout("I2C_start(): no acknowledge");
|
||||
}
|
||||
}
|
||||
else if(rdwr==I2C_Direction_Receiver)
|
||||
{
|
||||
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
|
||||
{
|
||||
if((timeout--)==0) return I2C_timeout(I2C_TFLAG_NO_ACK);//I2C_timeout("I2C_start(): no acknowledge");
|
||||
}
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// This function transmits one byte to the slave device
|
||||
// Parameters:
|
||||
// I2Cx --> the I2C peripheral e.g. I2C1
|
||||
// data --> the data byte to be transmitted
|
||||
//------------------------------------------------------------------
|
||||
static int I2C_write(I2C_TypeDef* I2Cx, uint8_t data)
|
||||
{
|
||||
uint32_t timeout = I2C_TIMEOUT;
|
||||
I2C_SendData(I2Cx, data);
|
||||
// wait for I2C1 EV8_2 --> byte has been transmitted
|
||||
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
|
||||
{
|
||||
if((timeout--)==0) return I2C_timeout(I2C_TFLAG_WRITE_FAILED);//I2C_timeout("I2C_write(): write byte failed");
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// This function reads one byte from the slave device
|
||||
// and acknowledges the byte (requests another byte)
|
||||
//------------------------------------------------------------------
|
||||
static int I2C_read(I2C_TypeDef* I2Cx, uint8_t ack)
|
||||
{
|
||||
uint32_t timeout = I2C_TIMEOUT;
|
||||
|
||||
// enable acknowledge of recieved data
|
||||
if (ack) {
|
||||
I2C_AcknowledgeConfig(I2Cx, ENABLE);
|
||||
} else {
|
||||
I2C_AcknowledgeConfig(I2Cx, DISABLE);
|
||||
}
|
||||
|
||||
// wait until one byte has been received
|
||||
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED))
|
||||
{
|
||||
if((timeout--)==0) return I2C_timeout(I2C_TFLAG_READ_FAILED);//I2C_timeout("I2C_read_ack(): read byte failed");
|
||||
}
|
||||
// read data from I2C data register and return data byte
|
||||
return I2C_ReceiveData(I2Cx);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// This funtion issues a stop condition and therefore
|
||||
// releases the bus
|
||||
//------------------------------------------------------------------
|
||||
static int I2C_stop(I2C_TypeDef* I2Cx)
|
||||
{
|
||||
// Send I2C1 STOP Condition
|
||||
I2C_GenerateSTOP(I2Cx, ENABLE);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
static int I2C_timeout(char *msg)
|
||||
{
|
||||
// printf("TIMEOUT: %s\n",msg);
|
||||
return ERROR;
|
||||
}
|
||||
*/
|
||||
static int I2C_timeout(uint8_t flag)
|
||||
{
|
||||
if (flag < 32) {
|
||||
// set some debug-related shit here, like maybe light an LED, etc.
|
||||
// TODO: do this
|
||||
}
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
void I2C1_EV_IRQHandler(void)
|
||||
{
|
||||
u32 event;
|
||||
event = I2C_GetLastEvent(I2C2);
|
||||
printf("I2C1_EV_IRQHandler(): Event=0x%08X\n",event);
|
||||
//---------------------------------------------------
|
||||
// todo, if I2C1 ISR mode shall be used
|
||||
//---------------------------------------------------
|
||||
}
|
||||
|
||||
void I2C2_EV_IRQHandler(void)
|
||||
{
|
||||
u32 event;
|
||||
event = I2C_GetLastEvent(I2C2);
|
||||
printf("I2C2_EV_IRQHandler(): Event=0x%08X\n",event);
|
||||
//---------------------------------------------------
|
||||
// todo, if I2C2 ISR mode shall be used
|
||||
//---------------------------------------------------
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,72 @@
|
|||
#ifndef _I2C_H
|
||||
#define _I2C_H
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "stm32l1xx_conf.h"
|
||||
|
||||
|
||||
//#define I2C1_OPEN
|
||||
#define I2C2_OPEN
|
||||
|
||||
#define I2C_SCL_SPEED (200000) // SCL in Hz
|
||||
#define I2C_OWN_ADDR (0x00) // use 0x00 for master
|
||||
|
||||
/**
|
||||
* @brief Definition for I2C1
|
||||
*/
|
||||
#if defined I2C1_OPEN
|
||||
#define PeterI2C I2C1
|
||||
#define PeterI2C_CLK RCC_APB1Periph_I2C1
|
||||
|
||||
#define PeterI2C_SCL_PIN GPIO_Pin_6
|
||||
#define PeterI2C_SCL_GPIO_PORT GPIOB
|
||||
#define PeterI2C_SCL_GPIO_CLK RCC_AHB1Periph_GPIOB
|
||||
#define PeterI2C_SCL_SOURCE GPIO_PinSource6
|
||||
#define PeterI2C_SCL_AF GPIO_AF_I2C1
|
||||
|
||||
#define PeterI2C_SDA_PIN GPIO_Pin_9
|
||||
#define PeterI2C_SDA_GPIO_PORT GPIOB
|
||||
#define PeterI2C_SDA_GPIO_CLK RCC_AHB1Periph_GPIOB
|
||||
#define PeterI2C_SDA_SOURCE GPIO_PinSource9
|
||||
#define PeterI2C_SDA_AF GPIO_AF_I2C1
|
||||
|
||||
#define PeterI2C_IRQn I2C1_EV_IRQn
|
||||
#define I2Cx_IRQHANDLER I2C1_EV_IRQHandler
|
||||
|
||||
#elif defined I2C2_OPEN
|
||||
#define PeterI2C I2C2
|
||||
#define PeterI2C_CLK RCC_APB1Periph_I2C2
|
||||
|
||||
#define PeterI2C_SCL_PIN GPIO_Pin_10
|
||||
#define PeterI2C_SCL_GPIO_PORT GPIOB
|
||||
#define PeterI2C_SCL_GPIO_CLK RCC_AHB1Periph_GPIOB
|
||||
#define PeterI2C_SCL_SOURCE GPIO_PinSource10
|
||||
#define PeterI2C_SCL_AF GPIO_AF_I2C2
|
||||
|
||||
#define PeterI2C_SDA_PIN GPIO_Pin_11
|
||||
#define PeterI2C_SDA_GPIO_PORT GPIOB
|
||||
#define PeterI2C_SDA_GPIO_CLK RCC_AHB1Periph_GPIOB
|
||||
#define PeterI2C_SDA_SOURCE GPIO_PinSource11
|
||||
#define PeterI2C_SDA_AF GPIO_AF_I2C2
|
||||
|
||||
#define PeterI2C_IRQn I2C2_EV_IRQn
|
||||
#define I2Cx_IRQHANDLER I2C2_EV_IRQHandler
|
||||
|
||||
#else
|
||||
#error "Please select the I2C-Device to be used (in i2c.h)"
|
||||
#endif
|
||||
|
||||
|
||||
#define I2C_TFLAG_BUS_BUSY 0x01
|
||||
#define I2C_TFLAG_START_FAILED 0x02
|
||||
#define I2C_TFLAG_NO_ACK 0x04
|
||||
#define I2C_TFLAG_WRITE_FAILED 0x08
|
||||
#define I2C_TFLAG_READ_FAILED 0x10
|
||||
|
||||
int I2C_ReadTransfer(uint8_t dev_addr, uint8_t *buffer, int cnt, uint32_t ptr, uint8_t ptrlen);
|
||||
int I2C_WriteTransfer(uint8_t dev_addr, uint8_t *buffer, int cnt, uint32_t ptr, uint8_t ptrlen);
|
||||
|
||||
#endif /*_I2C_H*/
|
|
@ -0,0 +1,236 @@
|
|||
/**
|
||||
* led_bone.c: skull crossbones led matrix handling functions
|
||||
* 2014 true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: led_bone.c 373 2015-06-25 06:21:27Z true $
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* Resources:
|
||||
* - Uses TIM11 OC1 and TIM9 OC1 and OC2 for PWM output; for frequency, see led_pwm.c
|
||||
*
|
||||
* TODO:
|
||||
* - use PWM for bone LEDs
|
||||
* - integrate with main matrix patterns somehow
|
||||
**/
|
||||
|
||||
#include <pirate.h>
|
||||
|
||||
#include "../interface/gpio.h"
|
||||
#include "../interface/led_pwm.h"
|
||||
#include "../device/lightsensor.h"
|
||||
|
||||
#include "led_matrix.h"
|
||||
#include "led_bone.h"
|
||||
|
||||
|
||||
// devices
|
||||
static TIM_TypeDef *led_bone_row_pwm[3] = {TIM11, TIM9, TIM9};
|
||||
static const tGPIO led_bone_row_gpio[3] = {
|
||||
{GPIOA, GPIO_Pin_7, 7},
|
||||
{GPIOB, GPIO_Pin_13, 13},
|
||||
{GPIOB, GPIO_Pin_14, 14}
|
||||
};
|
||||
static const tGPIO led_bone_col_gpio[3] = {
|
||||
{GPIOB, GPIO_Pin_12, 12},
|
||||
{GPIOB, GPIO_Pin_15, 15},
|
||||
{GPIOA, GPIO_Pin_8, 8}
|
||||
};
|
||||
|
||||
const uint8_t led_bone_order[8] = {
|
||||
BONE_LED_TR_UPPER,
|
||||
BONE_LED_TR_LOWER,
|
||||
BONE_LED_BR_UPPER,
|
||||
BONE_LED_BR_LOWER,
|
||||
BONE_LED_BL_LOWER,
|
||||
BONE_LED_BL_UPPER,
|
||||
BONE_LED_TL_LOWER,
|
||||
BONE_LED_TL_UPPER
|
||||
};
|
||||
|
||||
// pwm level
|
||||
static uint8_t led_bone_mode;
|
||||
static uint8_t led_level[9];
|
||||
|
||||
// led programs
|
||||
#include "led_bone_prog.h"
|
||||
static void (*led_program)();
|
||||
static void (*led_program_list[])() = {
|
||||
led_prog_all_on,
|
||||
led_prog_loops,
|
||||
led_prog_updown
|
||||
};
|
||||
const char led_bone_prog_name[LED_BONE_PROG_COUNT][16] = {
|
||||
{"AllOn"},
|
||||
{"Loops"},
|
||||
{"UpDown"},
|
||||
};
|
||||
|
||||
// currently lit led
|
||||
static uint8_t led_index = 0;
|
||||
|
||||
|
||||
/* functions */
|
||||
void led_bone_io_init()
|
||||
{
|
||||
uint8_t i;
|
||||
GPIO_InitTypeDef gpio;
|
||||
|
||||
// configure LOW as standard outputs
|
||||
gpio.GPIO_Mode = GPIO_Mode_OUT;
|
||||
gpio.GPIO_OType = GPIO_OType_PP;
|
||||
gpio.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
|
||||
// init and set low
|
||||
for (i = 0; i < 3; i++) {
|
||||
gpio.GPIO_Pin = led_bone_col_gpio[i].pin;
|
||||
GPIO_Init(led_bone_col_gpio[i].port, &gpio);
|
||||
GPIO_ResetBits(led_bone_col_gpio[i].port, led_bone_col_gpio[i].pin);
|
||||
}
|
||||
|
||||
// configure HIGH pins as AF
|
||||
gpio.GPIO_Mode = GPIO_Mode_AF;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
gpio.GPIO_Pin = led_bone_row_gpio[i].pin;
|
||||
GPIO_Init(led_bone_row_gpio[i].port, &gpio);
|
||||
}
|
||||
|
||||
// configure AF on these pins
|
||||
GPIO_PinAFConfig(led_bone_row_gpio[0].port, led_bone_row_gpio[0].pinsource, GPIO_AF_TIM11);
|
||||
GPIO_PinAFConfig(led_bone_row_gpio[1].port, led_bone_row_gpio[1].pinsource, GPIO_AF_TIM9);
|
||||
GPIO_PinAFConfig(led_bone_row_gpio[2].port, led_bone_row_gpio[2].pinsource, GPIO_AF_TIM9);
|
||||
}
|
||||
|
||||
void led_bone_io_disable()
|
||||
{
|
||||
GPIO_InitTypeDef gpio;
|
||||
int i;
|
||||
|
||||
gpio.GPIO_Mode = GPIO_Mode_OUT;
|
||||
gpio.GPIO_OType = GPIO_OType_OD;
|
||||
gpio.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
gpio.GPIO_Pin = led_bone_row_gpio[i].pin;
|
||||
GPIO_Init(led_bone_row_gpio[i].port, &gpio);
|
||||
}
|
||||
}
|
||||
|
||||
void inline led_bone_next()
|
||||
{
|
||||
uint8_t update_col;
|
||||
uint8_t update_row;
|
||||
uint16_t update_scaler;
|
||||
|
||||
uint32_t update_level[3] = {
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
// set active column
|
||||
update_col = led_index % 3;
|
||||
|
||||
// set updated row
|
||||
if (led_index < 3) {
|
||||
update_row = 0;
|
||||
} else if (led_index < 6) {
|
||||
update_row = 1;
|
||||
} else {
|
||||
update_row = 2;
|
||||
}
|
||||
|
||||
// set new levels
|
||||
// update_level[update_row] = *(led_level + led_index);
|
||||
update_scaler = (settings.led_autoadjust & 0x80) ? lightsensor_get_scalerval(LIGHTSENS_SCALED_BONES) : 256;
|
||||
update_level[update_row] = (led_level[led_index] * update_scaler) >> 8;
|
||||
|
||||
// disable PWM
|
||||
TIM_Cmd(led_bone_row_pwm[0], DISABLE);
|
||||
TIM_Cmd(led_bone_row_pwm[1], DISABLE);
|
||||
|
||||
// clear all columns (set high)
|
||||
GPIO_SetBits(led_bone_col_gpio[0].port, led_bone_col_gpio[0].pin);
|
||||
GPIO_SetBits(led_bone_col_gpio[1].port, led_bone_col_gpio[1].pin);
|
||||
GPIO_SetBits(led_bone_col_gpio[2].port, led_bone_col_gpio[2].pin);
|
||||
|
||||
// set new row pwm value
|
||||
led_pwm_set_oc(led_bone_row_pwm[0], &update_level[0]); // TIM11 has pin0
|
||||
led_pwm_set_oc(led_bone_row_pwm[1], &update_level[1]); // TIM9 has pin1, pin2
|
||||
|
||||
// reset pwm counter (fixes matrix glitches)
|
||||
TIM_SetCounter(led_bone_row_pwm[0], 0xff);
|
||||
TIM_SetCounter(led_bone_row_pwm[1], 0xff);
|
||||
|
||||
// generate update event to apply pwm values
|
||||
TIM_GenerateEvent(led_bone_row_pwm[0], TIM_EventSource_Update);
|
||||
TIM_GenerateEvent(led_bone_row_pwm[1], TIM_EventSource_Update);
|
||||
|
||||
// and now set the active column (set low)
|
||||
GPIO_ResetBits(led_bone_col_gpio[update_col].port, led_bone_col_gpio[update_col].pin);
|
||||
|
||||
// re-enable PWM
|
||||
TIM_Cmd(led_bone_row_pwm[0], ENABLE);
|
||||
TIM_Cmd(led_bone_row_pwm[1], ENABLE);
|
||||
|
||||
// next led
|
||||
led_index++;
|
||||
if (led_index >= 9) {
|
||||
led_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void led_bone_set_mode(uint8_t mode)
|
||||
{
|
||||
led_bone_mode = mode;
|
||||
}
|
||||
|
||||
void led_bone_set_program(uint8_t program_idx, uint8_t init,
|
||||
uint16_t wait, uint16_t level, uint32_t offset, uint32_t settings)
|
||||
{
|
||||
// we need to be in program mode
|
||||
led_bone_set_mode(LED_MATRIX_MODE_PROGRAM);
|
||||
// update the program pointer
|
||||
led_program = led_program_list[program_idx];
|
||||
|
||||
// set initial program variables
|
||||
led_prog_set_wait = wait;
|
||||
led_prog_set_level = level;
|
||||
led_prog_set_offset = offset;
|
||||
led_prog_set_option = settings;
|
||||
|
||||
// is this a new set? if so, initialize program parameters
|
||||
if (init) {
|
||||
uint8_t i;
|
||||
|
||||
led_prog_wait = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
led_prog_state[i] = 0;
|
||||
led_prog_work[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void led_bone_mode_update()
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
switch (led_bone_mode) {
|
||||
case LED_MATRIX_MODE_PROGRAM: {
|
||||
// if we have a valid program loaded, run it
|
||||
if (led_program != NULL) {
|
||||
led_program();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case LED_MATRIX_MODE_OFF: {
|
||||
led_program = NULL;
|
||||
for (i = 0; i < 9; i++) {
|
||||
led_level[i] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* led_bone.h: skull crossbones led matrix handling prototypes
|
||||
* 2014 true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: led_bone.h 364 2015-06-12 04:44:55Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_LED_BONE_H
|
||||
#define __PIRATE_LED_BONE_H
|
||||
|
||||
|
||||
|
||||
/* struct */
|
||||
typedef struct LEDBonePattern {
|
||||
uint16_t wait;
|
||||
uint8_t led[9];
|
||||
} LEDBonePattern;
|
||||
|
||||
|
||||
/* constants */
|
||||
#define LED_BONE_PROG_COUNT 3
|
||||
#define LED_BONE_PTRN_COUNT 0
|
||||
|
||||
/* led positions */
|
||||
#define BONE_LED_BR_LOWER 0
|
||||
#define BONE_LED_TR_LOWER 1
|
||||
#define BONE_LED_BR_UPPER 3
|
||||
#define BONE_LED_TL_UPPER 4
|
||||
#define BONE_LED_TL_LOWER 5
|
||||
#define BONE_LED_TR_UPPER 6
|
||||
#define BONE_LED_BL_UPPER 7
|
||||
#define BONE_LED_BL_LOWER 8
|
||||
|
||||
|
||||
/* variables */
|
||||
extern const char led_bone_prog_name[LED_BONE_PROG_COUNT][16];
|
||||
|
||||
|
||||
/* prototypes */
|
||||
void led_bone_io_init();
|
||||
void led_bone_io_disable();
|
||||
void led_bone_next();
|
||||
|
||||
void led_bone_mode_update();
|
||||
void led_bone_set_mode(uint8_t mode); // used for turning off
|
||||
void led_bone_set_program(uint8_t program_idx, uint8_t init,
|
||||
uint16_t wait, uint16_t level, uint32_t offset, uint32_t settings);
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* led_bone.c: skull crossbones led matrix fixed patterns
|
||||
* 2014 true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: led_bone_pattern.h 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
// LEDs are in this arrangement:
|
||||
// W-BR W-TR xxxx
|
||||
// P-BR P-TL W-TL
|
||||
// P-TR P-BL W-BL
|
||||
|
||||
// all on 100%
|
||||
static const LEDBonePattern led_pattern_01[] = {
|
||||
{1000, {0xff, 0xff, 0x00,
|
||||
0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff}},
|
||||
};
|
||||
|
||||
// all on 50%
|
||||
static const LEDBonePattern led_pattern_02[] = {
|
||||
{1000, {0x33, 0x33, 0x00,
|
||||
0x33, 0x33, 0x33,
|
||||
0x33, 0x33, 0x33}},
|
||||
};
|
||||
|
||||
// all on, white matching apparent purple 100% brightness
|
||||
static const LEDBonePattern led_pattern_03[] = {
|
||||
{1000, {0x10, 0x10, 0x00,
|
||||
0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10}},
|
||||
};
|
||||
|
||||
// pattern count - make sure this is updated with the amount
|
||||
// of entries in the patterns above!
|
||||
static uint8_t led_pattern_size[] = {
|
||||
1,
|
||||
1,
|
||||
1
|
||||
};
|
|
@ -0,0 +1,143 @@
|
|||
/**
|
||||
* led_bone.c: skull crossbones led matrix fixed patterns
|
||||
* 2014 true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: led_bone_prog.h 364 2015-06-12 04:44:55Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
static uint16_t led_prog_wait; // used by function to keep track of iteration time
|
||||
static uint32_t led_prog_state[4]; // used by the function to keep track of lit LEDs, state
|
||||
static uint32_t led_prog_work[4]; // used for misc shit
|
||||
|
||||
static uint16_t led_prog_set_wait; // used by setter function to set iteration time in ms
|
||||
static uint16_t led_prog_set_level; // used by setter function to set desired level
|
||||
static uint32_t led_prog_set_offset; // used by setter function to set desired offset
|
||||
static uint32_t led_prog_set_option; // used by setter to set options
|
||||
|
||||
|
||||
/* programs */
|
||||
static void led_prog_all_on()
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
if (!led_prog_wait) {
|
||||
led_prog_wait = 50;
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
led_level[i] = led_prog_set_level & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
led_prog_wait--;
|
||||
}
|
||||
|
||||
/********
|
||||
* around the bones in a loop program
|
||||
* speed: set as desired
|
||||
* options: bit 2 = direction (0 = clockwise, 1 = counter-clockwise),
|
||||
* bit 4 = decay trails faster, bit 5 = decay trails even faster,
|
||||
* bit 6 = trails enable
|
||||
*********/
|
||||
static void led_prog_loops()
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
if (!led_prog_wait) {
|
||||
// load new timer wait value
|
||||
led_prog_wait = led_prog_set_wait * 5;
|
||||
|
||||
// first run?
|
||||
if (!led_prog_state[3]) {
|
||||
// store starting offset
|
||||
led_prog_state[0] = led_prog_set_offset & 0x07;
|
||||
|
||||
// reset levels
|
||||
for (i = 0; i < 9; i++) {
|
||||
led_level[i] = 0;
|
||||
}
|
||||
|
||||
led_prog_state[3] = 1;
|
||||
}
|
||||
|
||||
// set decay rate (LED PWM active values are right shifted by this value)
|
||||
led_prog_work[0] = 1;
|
||||
if (led_prog_set_option & BIT_4) led_prog_work[0]++;
|
||||
if (led_prog_set_option & BIT_5) led_prog_work[0] += 2;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (i == led_prog_state[0]) {
|
||||
// LED is next in line so turn it on
|
||||
led_level[led_bone_order[i]] = led_prog_set_level & 0xff;
|
||||
} else {
|
||||
// LED is not on so decay or turn off
|
||||
led_level[led_bone_order[i]] = (led_prog_set_option & BIT_6) ?
|
||||
led_level[led_bone_order[i]] >> led_prog_work[0] : 0;
|
||||
}
|
||||
}
|
||||
|
||||
// update state with next LED
|
||||
led_prog_state[0] += (led_prog_set_option & BIT_2) ? 7 : 1;
|
||||
led_prog_state[0] &= 0x07;
|
||||
}
|
||||
|
||||
led_prog_wait--;
|
||||
}
|
||||
|
||||
/********
|
||||
* sweeping up and down symetically
|
||||
* speed: set as desired
|
||||
* options: bit 4 = decay trails faster, bit 5 = decay trails even faster,
|
||||
* bit 6 = trails enable
|
||||
*********/
|
||||
void led_prog_updown()
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
if (!led_prog_wait) {
|
||||
// load new timer wait value
|
||||
led_prog_wait = led_prog_set_wait * 5;
|
||||
|
||||
// first run?
|
||||
if (!led_prog_state[3]) {
|
||||
// store starting offset
|
||||
led_prog_state[0] = led_prog_set_offset & 0x07;
|
||||
|
||||
// reset levels
|
||||
for (i = 0; i < 9; i++) {
|
||||
led_level[i] = 0;
|
||||
}
|
||||
|
||||
led_prog_state[3] = 1;
|
||||
}
|
||||
|
||||
// set decay rate (LED PWM active values are right shifted by this value)
|
||||
led_prog_work[0] = 1;
|
||||
if (led_prog_set_option & BIT_4) led_prog_work[0] = 2;
|
||||
if (led_prog_set_option & BIT_5) led_prog_work[0] += 2;
|
||||
|
||||
led_prog_work[1] = led_prog_state[0] >= 4 ? 7 - led_prog_state[0] : led_prog_state[0];
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (i == led_prog_work[1]) {
|
||||
// LED is next in line so turn it on
|
||||
led_level[led_bone_order[i]] = led_prog_set_level & 0xff;
|
||||
} else {
|
||||
// LED is not on so decay or turn off
|
||||
led_level[led_bone_order[i]] = (led_prog_set_option & BIT_6) ?
|
||||
led_level[led_bone_order[i]] >> led_prog_work[0] : 0;
|
||||
}
|
||||
|
||||
led_level[led_bone_order[7 - i]] = led_level[led_bone_order[i]];
|
||||
}
|
||||
|
||||
// update state with next LED
|
||||
led_prog_state[0] += (led_prog_set_option & BIT_2) ? 7 : 1;
|
||||
led_prog_state[0] &= 0x07;
|
||||
|
||||
}
|
||||
|
||||
led_prog_wait--;
|
||||
}
|
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
* led_eyes_prog.h: programs for the RGBLED eyes
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: led_eyes_prog.h 375 2015-07-06 02:52:40Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
uint16_t led_prog_wait; // used by function to keep track of iteration time
|
||||
uint32_t led_prog_state[4]; // used by the function to keep track of lit LEDs, state
|
||||
uint32_t led_prog_work[4]; // used for misc shit
|
||||
|
||||
uint16_t led_prog_set_wait; // used by setter function to set iteration time in ms
|
||||
uint16_t led_prog_set_level; // used by setter function to set desired level
|
||||
uint32_t led_prog_set_offset; // used by setter function to set desired offset
|
||||
uint32_t led_prog_set_option; // used by setter to set options
|
||||
|
||||
|
||||
/* programs */
|
||||
/********
|
||||
* candle flicker
|
||||
* option sets the color mix; each 8 bits set the mix level in RGBx
|
||||
* (so 0xff0000?? would be red, etc)
|
||||
* xx option bits determine if independent (1 = yes, 0 = no)
|
||||
*********/
|
||||
static void led_prog_candle_flicker()
|
||||
{
|
||||
static const uint8_t lookup[] = {20, 52, 84, 116, 148, 184, 220, 255};
|
||||
uint32_t rand = 0;
|
||||
uint8_t new_val[3];
|
||||
|
||||
int i;
|
||||
|
||||
// ideally we want to update flicker at about 454.54hz (as close to 440hz as we can get) = 11
|
||||
// I don't know where I read this so let's just update LEDs less often because it looks nicer
|
||||
|
||||
if (!led_prog_wait) {
|
||||
led_prog_wait = 45;
|
||||
|
||||
// set which LED to update if in alternating mode
|
||||
led_prog_state[0] = led_prog_state[0] ? 0 : 1;
|
||||
|
||||
rand = pirate_prng() & 0x1f;
|
||||
rand = (rand > 7) ? lookup[7] : lookup[rand];
|
||||
|
||||
// create scaled value
|
||||
new_val[0] = ((led_prog_set_option >> 24));
|
||||
new_val[1] = ((led_prog_set_option >> 16) & 0xff);
|
||||
new_val[2] = ((led_prog_set_option >> 8) & 0xff);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
new_val[i] = (rand * new_val[i]) >> 8;
|
||||
}
|
||||
|
||||
// update LED values
|
||||
if (led_prog_set_option & 1) {
|
||||
led_level[led_prog_state[0]][0] = new_val[0];
|
||||
led_level[led_prog_state[0]][1] = new_val[1];
|
||||
led_level[led_prog_state[0]][2] = new_val[2];
|
||||
} else {
|
||||
led_level[0][0] = led_level[1][0] = new_val[0];
|
||||
led_level[0][1] = led_level[1][1] = new_val[1];
|
||||
led_level[0][2] = led_level[1][2] = new_val[2];
|
||||
}
|
||||
}
|
||||
|
||||
led_prog_wait--;
|
||||
}
|
||||
|
||||
static void led_prog_candle_flicker_favcolor()
|
||||
{
|
||||
led_prog_set_option = settings.fav_color[0] << 24 | settings.fav_color[1] << 16 |
|
||||
settings.fav_color[2] << 8 | (led_prog_set_option & 0x01);
|
||||
|
||||
led_prog_candle_flicker();
|
||||
}
|
||||
|
||||
/********
|
||||
* static led or random led flasher
|
||||
* option sets the color mix; each 8 bits set the mix level in RGBx
|
||||
* (so 0xff0000?? would be red, etc)
|
||||
* low bit of option sets LEDs in independent mode (1 = yes, 0 = no)
|
||||
* offset sets the flash color mix
|
||||
* low 8 bits of offset set the threshold of the flasher (0x00=always, 0xff=never)
|
||||
* having eyes on while set to always activate will simply alternate the LEDs
|
||||
*********/
|
||||
static void led_prog_randflasher()
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!led_prog_wait) {
|
||||
led_prog_wait = led_prog_set_wait * 5;
|
||||
|
||||
// set which LED to operate
|
||||
led_prog_state[0] = led_prog_state[0] ? 0 : 1;
|
||||
|
||||
// set background levels on all LEDs
|
||||
for (i = 0; i < 2; i++) {
|
||||
led_level[i][0] = ((led_prog_set_option >> 24));
|
||||
led_level[i][1] = ((led_prog_set_option >> 16) & 0xff);
|
||||
led_level[i][2] = ((led_prog_set_option >> 8) & 0xff);
|
||||
}
|
||||
|
||||
// set flash
|
||||
if (pirate_prng() > (led_prog_set_offset & 0xff)) {
|
||||
if (!(led_prog_set_option & BIT_0) || (led_prog_state[0] == 0)) {
|
||||
led_level[0][0] = ((led_prog_set_offset >> 24));
|
||||
led_level[0][1] = ((led_prog_set_offset >> 16) & 0xff);
|
||||
led_level[0][2] = ((led_prog_set_offset >> 8) & 0xff);
|
||||
}
|
||||
if (!(led_prog_set_option & BIT_0) || (led_prog_state[0] == 1)) {
|
||||
led_level[1][0] = ((led_prog_set_offset >> 24));
|
||||
led_level[1][1] = ((led_prog_set_offset >> 16) & 0xff);
|
||||
led_level[1][2] = ((led_prog_set_offset >> 8) & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
led_prog_wait--;
|
||||
}
|
||||
|
||||
/********
|
||||
* mic spl meter
|
||||
* level: sets the threshold scaler. 0xff = 100 is max, 0x80 = 50 is max, and so on
|
||||
* offset: sets the cold (0%) color, see above for format
|
||||
* option: sets the hot (100%) color, see above for format
|
||||
* last 7 bits of option sets how fast the ramping up is
|
||||
* last 7 bits of offset sets how fast the ramping down is
|
||||
*********/
|
||||
static void led_prog_mic_spl()
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!led_prog_wait) {
|
||||
led_prog_wait = led_prog_set_wait * 5;
|
||||
|
||||
// first run?
|
||||
if (led_prog_set_option & 0x80) {
|
||||
led_prog_work[0] = 0;
|
||||
led_prog_set_option |= 0x80;
|
||||
}
|
||||
|
||||
// speed is set?
|
||||
if (!(led_prog_set_option & 0x7f)) {
|
||||
led_prog_set_option |= 0x0f;
|
||||
}
|
||||
if (!(led_prog_set_offset & 0x7f)) {
|
||||
led_prog_set_offset |= 0x01;
|
||||
}
|
||||
|
||||
// set our value
|
||||
if (mic_peak > led_prog_work[0]) {
|
||||
led_prog_work[0] += led_prog_set_option & 0xff;
|
||||
if (led_prog_work[0] > mic_peak) led_prog_work[0] = mic_peak;
|
||||
} else {
|
||||
led_prog_work[0] -= led_prog_set_offset & 0xff;
|
||||
if (led_prog_work[0] < mic_peak) led_prog_work[0] = mic_peak;
|
||||
}
|
||||
|
||||
// make it a percentage
|
||||
led_prog_work[1] = pirate_scale(led_prog_work[0], settings.mic_cal[0], settings.mic_cal[1], 0, 255);
|
||||
|
||||
// scale value
|
||||
led_prog_state[0] = pirate_scale(led_prog_work[1], (led_prog_set_level >> 8), (led_prog_set_level & 0xff), 0, 248);
|
||||
|
||||
// scale hot/cold levels on LEDs
|
||||
for (i = 0; i < 3; i++) {
|
||||
led_level[0][i] = led_level[1][i] = pirate_scale(led_prog_state[0], 0, 248,
|
||||
((led_prog_set_offset >> ((3 - i) << 3)) & 0xff),
|
||||
((led_prog_set_option >> ((3 - i) << 3)) & 0xff));
|
||||
}
|
||||
}
|
||||
|
||||
led_prog_wait--;
|
||||
}
|
||||
|
||||
/********
|
||||
* color fader, rgb
|
||||
* starts out blank right now
|
||||
* level does nothing right now
|
||||
* option sets the order and mix, for each half byte (0x01=red, 0x02=blue, 0x04=grn, 0x08=rampdown)
|
||||
* (order is LS to MS) -
|
||||
* 0x8 = stop pattern (go to beginning)
|
||||
* 0x9-0xF = 0x1-0x7 except other colors must finish dimming
|
||||
* offset sets the lag in the right eye, but this doesn't work right now, so just inverts
|
||||
*
|
||||
*********/
|
||||
static void led_prog_fader()
|
||||
{
|
||||
uint32_t bitshift;
|
||||
uint32_t bitfield;
|
||||
uint8_t nextstep;
|
||||
int i;
|
||||
|
||||
if (!led_prog_wait) {
|
||||
led_prog_wait = led_prog_set_wait * 5;
|
||||
|
||||
// first run?
|
||||
if (!led_prog_state[3]) {
|
||||
led_prog_work[0] = 0;
|
||||
led_prog_work[1] = 0;
|
||||
led_prog_work[2] = 0;
|
||||
led_prog_state[0] = 0;
|
||||
led_prog_state[1] = led_prog_set_offset;
|
||||
led_prog_state[3] = 1;
|
||||
}
|
||||
|
||||
// figure out what colors to manipulate for the left eye
|
||||
bitshift = (led_prog_state[0] << 2);
|
||||
bitfield = (led_prog_set_option >> bitshift) & 0xF;
|
||||
|
||||
// is this a reset instruction?
|
||||
if (bitfield == 0x8) {
|
||||
// start over
|
||||
led_prog_state[0] = 0;
|
||||
bitfield = led_prog_set_option & 0xF;
|
||||
}
|
||||
|
||||
// is this a require-clearing instruction?
|
||||
if (bitfield & 0x8) {
|
||||
//copy inverse of low nybble to high nybble
|
||||
bitfield |= (~(bitfield & 0xf)) << 4;
|
||||
// clear high bits in each nybble if set
|
||||
bitfield &= 0x77;
|
||||
}
|
||||
|
||||
nextstep = 0;
|
||||
|
||||
// and manipulate (fade) them
|
||||
if (bitfield) {
|
||||
if (bitfield >> 4) { // fade-down bit set
|
||||
for (i = 0; i <= 2; i++) {
|
||||
if ((bitfield >> 4) & (1 << i)) { // config bit unset (set here)
|
||||
if (led_prog_work[i]) {
|
||||
led_prog_work[i]--; // means fade down for unused channels
|
||||
} else {
|
||||
nextstep |= (1 << (i + 4)); // and signal when we are done with this channel
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i <= 2; i++) {
|
||||
if (bitfield & (1 << i)) { // low bit set, normal fade-up addition
|
||||
if (led_prog_work[i] < 255) {
|
||||
led_prog_work[i]++;
|
||||
} else {
|
||||
nextstep |= (1 << i); // all the way up? signal we're done
|
||||
}
|
||||
} else if (!(bitfield & 0x8) && led_prog_work[i]) {
|
||||
led_prog_work[i]--; // neither high nor low set? fade down
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// figure out delay for right eye
|
||||
if (led_prog_state[1]) {
|
||||
led_prog_state[1]--;
|
||||
} else {
|
||||
// ok, delay is done, we can start manipulating the right eye
|
||||
}
|
||||
|
||||
// special task for forcing all outputs to 0
|
||||
if (!bitfield) {
|
||||
// if unset, then we need to dim down to nothing
|
||||
for (i = 0; i <= 2; i++) {
|
||||
if (led_prog_work[i] & 0xff) {
|
||||
led_prog_work[i]--;
|
||||
} else {
|
||||
nextstep++;
|
||||
}
|
||||
}
|
||||
|
||||
if (nextstep == 3) {
|
||||
led_prog_state[0]++;
|
||||
led_prog_state[0] %= 8;
|
||||
}
|
||||
} else if (nextstep == bitfield) {
|
||||
// all of our LEDs are set to level, we can proceed to the next step
|
||||
led_prog_state[0]++;
|
||||
led_prog_state[0] %= 8;
|
||||
}
|
||||
|
||||
// actually set LEDs
|
||||
for (i = 0; i <= 2; i++) {
|
||||
led_level[0][i] = led_prog_work[i] & 0xff;
|
||||
//led_level[1][i] = (led_prog_work[i] >> 8) & 0xff;
|
||||
led_level[1][i] = led_prog_set_offset ? ~led_prog_work[i] : led_prog_work[i];
|
||||
}
|
||||
}
|
||||
|
||||
led_prog_wait--;
|
||||
}
|
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* led_matrix.c: main skull led matrix handling functions
|
||||
* 3414 true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: led_matrix.c 373 2015-06-25 06:21:27Z true $
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* Resources:
|
||||
* - Uses TIM2 and TIM3 as PWM output; for frequency, see led_pwm.c
|
||||
**/
|
||||
|
||||
#include <pirate.h>
|
||||
|
||||
#include "../interface/gpio.h"
|
||||
#include "../interface/led_pwm.h"
|
||||
#include "../device/lightsensor.h"
|
||||
|
||||
#include "led_matrix.h"
|
||||
|
||||
|
||||
// pwm devices
|
||||
TIM_TypeDef *led_pwm[2] = {TIM2, TIM3};
|
||||
|
||||
// pwm pins
|
||||
// order is 0=white, 1=purple. row=high, col=low
|
||||
GPIO_TypeDef *led_row_port[2] = {GPIOA, GPIOC};
|
||||
uint16_t led_row_pin_mask[2] = {0x000f, 0x03c0};
|
||||
const uint8_t led_row_pin_low[2] = {0, 6};
|
||||
|
||||
GPIO_TypeDef *led_col_port[2] = {GPIOC, GPIOC};
|
||||
uint16_t led_col_pin_mask[2] = {0xf000, 0x003c};
|
||||
const uint8_t led_col_pin_low[2] = {12, 2};
|
||||
|
||||
// led mode
|
||||
uint8_t led_matrix_mode;
|
||||
|
||||
// led brightness
|
||||
uint8_t led_level[2][16];
|
||||
|
||||
// led programs
|
||||
#include "led_matrix_prog.h"
|
||||
static void (*led_program)();
|
||||
static void (*led_program_list[])() = {
|
||||
led_prog_debug,
|
||||
led_prog_loops,
|
||||
led_prog_loops_mic,
|
||||
led_prog_loops_rotate,
|
||||
led_prog_rand_on_rand_off,
|
||||
led_prog_mic_spl_meter
|
||||
};
|
||||
const char led_matrix_prog_name[LED_MATRIX_PROG_COUNT][16] = {
|
||||
{"Debug"},
|
||||
{"Loops"},
|
||||
{"Loops+Mic"},
|
||||
{"Loops+Rotate"},
|
||||
{"Random"},
|
||||
{"SPLMeter"},
|
||||
};
|
||||
|
||||
// currently lit LED
|
||||
static uint8_t led_index;
|
||||
|
||||
|
||||
/* functions */
|
||||
void led_matrix_io_init()
|
||||
{
|
||||
int i;
|
||||
GPIO_InitTypeDef gpio;
|
||||
|
||||
// configure LOW as standard outputs
|
||||
gpio.GPIO_Mode = GPIO_Mode_OUT;
|
||||
gpio.GPIO_OType = GPIO_OType_PP;
|
||||
gpio.GPIO_Speed = GPIO_Speed_10MHz;
|
||||
|
||||
gpio.GPIO_Pin = led_col_pin_mask[0];
|
||||
GPIO_Init(led_col_port[0], &gpio);
|
||||
|
||||
gpio.GPIO_Pin = led_col_pin_mask[1];
|
||||
GPIO_Init(led_col_port[1], &gpio);
|
||||
|
||||
// and set low
|
||||
GPIO_ResetBits(led_col_port[0], led_col_pin_mask[0]);
|
||||
GPIO_ResetBits(led_col_port[1], led_col_pin_mask[1]);
|
||||
|
||||
// configure HIGH pins as AF
|
||||
gpio.GPIO_Mode = GPIO_Mode_AF;
|
||||
|
||||
gpio.GPIO_Pin = led_row_pin_mask[0];
|
||||
GPIO_Init(led_row_port[0], &gpio);
|
||||
|
||||
gpio.GPIO_Pin = led_row_pin_mask[1];
|
||||
GPIO_Init(led_row_port[1], &gpio);
|
||||
|
||||
// set AF on HIGH pins
|
||||
for (i = 0; i < 4; i++) {
|
||||
GPIO_PinAFConfig(led_row_port[0], led_row_pin_low[0] + i, GPIO_AF_TIM2);
|
||||
GPIO_PinAFConfig(led_row_port[1], led_row_pin_low[1] + i, GPIO_AF_TIM3);
|
||||
}
|
||||
|
||||
// MAKE SURE to enable PWM for these to work!
|
||||
}
|
||||
|
||||
void led_matrix_io_disable()
|
||||
{
|
||||
GPIO_InitTypeDef gpio;
|
||||
int i;
|
||||
|
||||
gpio.GPIO_Mode = GPIO_Mode_OUT;
|
||||
gpio.GPIO_OType = GPIO_OType_OD;
|
||||
gpio.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
gpio.GPIO_Pin = led_row_pin_low[0] + i;
|
||||
GPIO_Init(led_row_port[0], &gpio);
|
||||
gpio.GPIO_Pin = led_row_pin_low[1] + i;
|
||||
GPIO_Init(led_row_port[1], &gpio);
|
||||
}
|
||||
}
|
||||
|
||||
void inline led_matrix_next()
|
||||
{
|
||||
uint32_t update_col;
|
||||
uint32_t update_row;
|
||||
uint16_t update_scaler;
|
||||
uint32_t update_level[2][4] = {
|
||||
//{0xff, 0xff, 0xff, 0xff},
|
||||
//{0xff, 0xff, 0xff, 0xff}
|
||||
{0x100, 0x100, 0x100, 0x100},
|
||||
{0x100, 0x100, 0x100, 0x100}
|
||||
};
|
||||
|
||||
// set next index
|
||||
led_index++;
|
||||
led_index &= 0x0f;
|
||||
|
||||
// set active column
|
||||
update_col = led_index % 4;
|
||||
update_row = led_index >> 2;
|
||||
|
||||
// set new levels
|
||||
update_scaler = (settings.led_autoadjust & 0x80) ? lightsensor_get_scalerval(LIGHTSENS_SCALED_SKULL_WHT) : 256;
|
||||
update_level[0][update_row] = 0x100 - ((led_level[0][led_index] * update_scaler) >> 8);
|
||||
update_scaler = (settings.led_autoadjust & 0x80) ? lightsensor_get_scalerval(LIGHTSENS_SCALED_SKULL_PUR) : 256;
|
||||
update_level[1][update_row] = 0x100 - ((led_level[1][led_index] * update_scaler) >> 8);
|
||||
|
||||
// updating the matrix is glitchy as best and I know I am doing something wrong here.
|
||||
// but this is the best I could come up with while sleep-deprived forceful debugging.
|
||||
// disable PWM
|
||||
TIM_Cmd(led_pwm[0], DISABLE);
|
||||
TIM_Cmd(led_pwm[1], DISABLE);
|
||||
|
||||
// set new PWM value for the active row
|
||||
led_pwm_set_oc(led_pwm[0], update_level[0]);
|
||||
led_pwm_set_oc(led_pwm[1], update_level[1]);
|
||||
|
||||
// reset pwm counter (fixes matrix glitches)
|
||||
TIM_SetCounter(led_pwm[0], 0xff);
|
||||
TIM_SetCounter(led_pwm[1], 0xff);
|
||||
|
||||
// generate update event to apply pwm values
|
||||
TIM_GenerateEvent(led_pwm[0], TIM_EventSource_Update);
|
||||
TIM_GenerateEvent(led_pwm[1], TIM_EventSource_Update);
|
||||
|
||||
// clear all columns
|
||||
// we do this after setting PWM to fix glitchy other LEDs lighting
|
||||
GPIO_ResetBits(led_col_port[0], led_col_pin_mask[0]);
|
||||
GPIO_ResetBits(led_col_port[1], led_col_pin_mask[1]);
|
||||
|
||||
// and now set the active column
|
||||
GPIO_SetBits(led_col_port[0], (1 << (led_col_pin_low[0] + update_col)));
|
||||
GPIO_SetBits(led_col_port[1], (1 << (led_col_pin_low[1] + update_col)));
|
||||
|
||||
// re-enable PWM
|
||||
TIM_Cmd(led_pwm[0], ENABLE);
|
||||
TIM_Cmd(led_pwm[1], ENABLE);
|
||||
}
|
||||
|
||||
void led_matrix_set_mode(uint8_t mode)
|
||||
{
|
||||
led_matrix_mode = mode;
|
||||
}
|
||||
|
||||
void led_matrix_set_program(uint8_t program_idx, uint8_t init,
|
||||
uint16_t wait, uint16_t level, uint32_t offset, uint32_t settings)
|
||||
{
|
||||
// we need to be in program mode
|
||||
led_matrix_set_mode(LED_MATRIX_MODE_PROGRAM);
|
||||
// update the program pointer
|
||||
led_program = led_program_list[program_idx];
|
||||
|
||||
// set initial program variables
|
||||
led_prog_set_wait = wait;
|
||||
led_prog_set_level = level;
|
||||
led_prog_set_offset = offset;
|
||||
led_prog_set_option = settings;
|
||||
|
||||
// is this a new set? if so, initialize program parameters
|
||||
if (init) {
|
||||
int i;
|
||||
|
||||
led_prog_wait = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
led_prog_state[i] = 0;
|
||||
led_prog_work[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t led_matrix_get_mode()
|
||||
{
|
||||
return led_matrix_mode;
|
||||
}
|
||||
|
||||
void led_matrix_mode_update()
|
||||
{
|
||||
int i;
|
||||
|
||||
switch (led_matrix_mode) {
|
||||
case LED_MATRIX_MODE_PROGRAM: {
|
||||
// if we have a valid program loaded, run it
|
||||
if (led_program != NULL) {
|
||||
led_program();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LED_MATRIX_MODE_OFF: {
|
||||
led_program = NULL;
|
||||
for (i = 0; i < 16; i++) {
|
||||
led_level[LED_MATRIX_WHITE][i] = 0;
|
||||
led_level[LED_MATRIX_PURPLE][i] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* led_matrix.h: main skull led matrix handling prototypes
|
||||
* 2014 true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: led_matrix.h 364 2015-06-12 04:44:55Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_LED_MATRIX_H
|
||||
#define __PIRATE_LED_MATRIX_H
|
||||
|
||||
|
||||
|
||||
/* struct */
|
||||
typedef struct LEDFixedPattern {
|
||||
uint16_t wait;
|
||||
uint32_t led[8];
|
||||
} LEDFixedPattern;
|
||||
|
||||
|
||||
|
||||
/* constants */
|
||||
#define LED_MATRIX_PROG_COUNT 6
|
||||
|
||||
/* interface */
|
||||
#define LED_MATRIX_WHITE 0
|
||||
#define LED_MATRIX_PURPLE 1
|
||||
|
||||
/* programs */
|
||||
#define LED_MATRIX_MODE_OFF 0
|
||||
#define LED_MATRIX_MODE_PROGRAM 2
|
||||
|
||||
|
||||
/* variables */
|
||||
extern const char led_matrix_prog_name[LED_MATRIX_PROG_COUNT][16];
|
||||
|
||||
|
||||
/* prototypes */
|
||||
void led_matrix_io_init();
|
||||
void led_matrix_io_disable();
|
||||
void led_matrix_next();
|
||||
|
||||
void led_matrix_mode_update();
|
||||
void led_matrix_set_mode(uint8_t mode); // used for turning off
|
||||
void led_matrix_set_program(uint8_t program_idx, uint8_t init,
|
||||
uint16_t wait, uint16_t level, uint32_t offset, uint32_t settings);
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* led_matrix_pattern.h: fixed patterns for the RGBLED eyes
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: led_matrix_pattern.h 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
// all LEDs on 100%
|
||||
static const LEDFixedPattern led_pattern_01[] = {
|
||||
{1000, {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}},
|
||||
};
|
||||
|
||||
// all LEDs on 50%
|
||||
static const LEDFixedPattern led_pattern_02[] = {
|
||||
{1000, {0x7d7d7d7d, 0x7d7d7d7d, 0x7d7d7d7d, 0x7d7d7d7d,
|
||||
0x7d7d7d7d, 0x7d7d7d7d, 0x7d7d7d7d, 0x7d7d7d7d}},
|
||||
};
|
||||
|
||||
// alternate, fast fade
|
||||
static const LEDFixedPattern led_pattern_03[] = {
|
||||
{600, {0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00,
|
||||
0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff}},
|
||||
{80, {0x80808080, 0x80808080, 0x80808080, 0x80808080,
|
||||
0x80808080, 0x80808080, 0x80808080, 0x80808080}},
|
||||
{600, {0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff,
|
||||
0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00}},
|
||||
{80, {0x80808080, 0x80808080, 0x80808080, 0x80808080,
|
||||
0x80808080, 0x80808080, 0x80808080, 0x80808080}}
|
||||
};
|
||||
|
||||
// fast white/alternate flash
|
||||
static const LEDFixedPattern led_pattern_04[] = {
|
||||
{80, {0x34343434, 0x34343434, 0x34343434, 0x34343434,
|
||||
0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0}},
|
||||
{80, {0x04040404, 0x04040404, 0x04040404, 0x04040404,
|
||||
0xfdfdfdfd, 0xfdfdfdfd, 0xfdfdfdfd, 0xfdfdfdfd}},
|
||||
{80, {0x78787878, 0x78787878, 0x78787878, 0x78787878,
|
||||
0x86868686, 0x86868686, 0x86868686, 0x86868686}},
|
||||
{80, {0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0,
|
||||
0x34343434, 0x34343434, 0x34343434, 0x34343434}},
|
||||
{80, {0xfdfdfdfd, 0xfdfdfdfd, 0xfdfdfdfd, 0xfdfdfdfd,
|
||||
0x04040404, 0x04040404, 0x04040404, 0x04040404}},
|
||||
{80, {0x86868686, 0x86868686, 0x86868686, 0x86868686,
|
||||
0x78787878, 0x78787878, 0x78787878, 0x78787878}}
|
||||
};
|
||||
|
||||
// pattern count - make sure this is updated with the amount
|
||||
// of entries in the patterns above!
|
||||
static const uint8_t led_pattern_size[] = {
|
||||
1,
|
||||
1,
|
||||
4,
|
||||
6
|
||||
};
|
|
@ -0,0 +1,300 @@
|
|||
/**
|
||||
* led_matrix_prog.h: programs for the main LED matrix
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: led_matrix_prog.h 364 2015-06-12 04:44:55Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
// program variables
|
||||
static uint16_t led_prog_wait; // used by function to keep track of iteration time
|
||||
static uint32_t led_prog_state[4]; // used by the function to keep track of lit LEDs, state
|
||||
static uint32_t led_prog_work[4]; // used for misc shit
|
||||
|
||||
static uint16_t led_prog_set_wait; // used by setter function to set iteration time in ms
|
||||
static uint16_t led_prog_set_level; // used by setter function to set desired level
|
||||
static uint32_t led_prog_set_offset;// used by setter function to set desired offset
|
||||
static uint32_t led_prog_set_option;// used by setter to set options
|
||||
|
||||
|
||||
/* programs */
|
||||
/********
|
||||
* debug light output
|
||||
* uses white LEDs as debug output.
|
||||
* set the offset to the LED mask for LEDs you want lit.
|
||||
* set the wait time to the time to stay lit (15000 is a good value).
|
||||
*********/
|
||||
static void led_prog_debug()
|
||||
{
|
||||
int i;
|
||||
|
||||
if (led_prog_set_wait) {
|
||||
led_prog_wait = led_prog_set_wait;
|
||||
led_prog_set_wait = 0;
|
||||
led_prog_state[0] = led_prog_set_offset;
|
||||
}
|
||||
|
||||
if (led_prog_wait) {
|
||||
led_prog_wait--;
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (led_prog_state[0] & (1 << i)) {
|
||||
led_level[0][i] = led_prog_wait ? (led_prog_set_level & 0xff) : 0;
|
||||
} else {
|
||||
led_level[0][i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/********
|
||||
* around the skull in a loop program
|
||||
* speed: set as desired
|
||||
* options: bit 0 = white enable, bit 1 = purple enable,
|
||||
* bit 2 = white direction (0 = clockwise, 1 = counter-clockwise),
|
||||
* bit 3 = purple direction (0 = clockwise, 1 = counter-clockwise),
|
||||
* bit 4 = decay trails faster, bit 5 = decay trails even faster,
|
||||
* bit 6 = trails enable on white, bit 7 = trails enable on purple
|
||||
*********/
|
||||
static void led_prog_loops()
|
||||
{
|
||||
int i;
|
||||
|
||||
// timeout is done?
|
||||
if (!led_prog_wait) {
|
||||
// load new timer wait value
|
||||
led_prog_wait = led_prog_set_wait * 5;
|
||||
|
||||
// set decay rate (LED PWM active values are right shifted by this value)
|
||||
led_prog_work[0] = 1;
|
||||
if (led_prog_set_option & BIT_4) led_prog_work[0]++;
|
||||
if (led_prog_set_option & BIT_5) led_prog_work[0] += 2;
|
||||
|
||||
// set initial LED offsets
|
||||
if (!led_prog_work[3]) {
|
||||
led_prog_state[0] = led_prog_set_offset & 0x0f;
|
||||
led_prog_state[1] = (led_prog_set_offset >> 4) & 0x0f;
|
||||
led_prog_work[3] = 1;
|
||||
}
|
||||
|
||||
// set LED PWM levels
|
||||
for (i = 0; i < 16; i++) {
|
||||
if ((i == led_prog_state[0]) && (led_prog_set_option & BIT_0)) {
|
||||
// LED is active and enabled; set to desired level.
|
||||
led_level[0][i] = led_prog_set_level & 0xff;
|
||||
} else {
|
||||
// led is not active - decay if trails on, otherwise turn off
|
||||
led_level[0][i] = (led_prog_set_option & BIT_6) ?
|
||||
led_level[0][i] >> led_prog_work[0] : 0;
|
||||
}
|
||||
|
||||
if ((i == led_prog_state[1]) && (led_prog_set_option & BIT_1)) {
|
||||
// LED is active and enabled; set to desired level.
|
||||
led_level[1][i] = led_prog_set_level >> 8;
|
||||
} else {
|
||||
// led is not active - decay if trails on, otherwise turn off
|
||||
led_level[1][i] = (led_prog_set_option & BIT_7) ?
|
||||
led_level[1][i] >> led_prog_work[0] : 0;
|
||||
}
|
||||
}
|
||||
|
||||
// update program state with the next LED
|
||||
for (i = 0; i < 2; i++) {
|
||||
led_prog_state[i] += (led_prog_set_option & (1 << (i + 2))) ? 15 : 1;
|
||||
led_prog_state[i] &= 0x0f;
|
||||
}
|
||||
}
|
||||
|
||||
// bide our time...
|
||||
led_prog_wait--;
|
||||
}
|
||||
|
||||
/********
|
||||
* around the skull in a loop program modulated by microphone
|
||||
* speed: set as desired
|
||||
* options: see above program
|
||||
*********/
|
||||
static void led_prog_loops_mic()
|
||||
{
|
||||
static uint32_t delay = 0;
|
||||
uint16_t low, high;
|
||||
|
||||
low = (led_prog_set_offset >> 8) & 0xff;
|
||||
high = (led_prog_set_offset >> 16) & 0xff;
|
||||
|
||||
led_prog_state[3] = pirate_scale(mic_peak, settings.mic_cal[0], settings.mic_cal[1], 255, 0);
|
||||
led_prog_state[3] = pirate_scale(led_prog_state[3], low, high, 1, 120);
|
||||
|
||||
// variable decay
|
||||
if (!delay) {
|
||||
delay = (led_prog_set_offset >> 24);
|
||||
if (!delay) delay = 1;
|
||||
if (led_prog_set_wait < led_prog_state[3]) {
|
||||
led_prog_set_wait++;
|
||||
}
|
||||
}
|
||||
|
||||
// always have fast attack
|
||||
if (led_prog_set_wait > led_prog_state[3]) {
|
||||
led_prog_set_wait = led_prog_state[3];
|
||||
}
|
||||
|
||||
delay--;
|
||||
|
||||
led_prog_loops();
|
||||
}
|
||||
|
||||
/********
|
||||
* around the skull in a loop program that rotates
|
||||
* most useful for oppositing direction loops so that the
|
||||
* point of contact changes
|
||||
* speed: set as desired
|
||||
* options: see above program, with the following:
|
||||
* high 12 option bits: time between rotating in ms
|
||||
* bits[19:16]: specify direction (1-15 = move pos cw)
|
||||
*********/
|
||||
static void led_prog_loops_rotate()
|
||||
{
|
||||
static uint32_t wait = 0;
|
||||
uint32_t t;
|
||||
|
||||
if (!wait) {
|
||||
wait = (led_prog_set_option >> 20) * 5;
|
||||
if (!wait) wait = 1;
|
||||
|
||||
t = (led_prog_set_option >> 16 & 0x0f);
|
||||
|
||||
if (t >= 1 && t <= 15) {
|
||||
led_prog_state[0] += t;
|
||||
led_prog_state[0] &= 0x0f;
|
||||
|
||||
led_prog_state[1] += t;
|
||||
led_prog_state[1] &= 0x0f;
|
||||
}
|
||||
}
|
||||
|
||||
wait--;
|
||||
led_prog_loops();
|
||||
}
|
||||
|
||||
|
||||
/********
|
||||
* random on, random off
|
||||
* speed: set as desired
|
||||
* options: bit 7 = fade off instead of turning off, bit 6 = fade faster
|
||||
* bit 5 = fade even faster, bit 4 = fade faster still
|
||||
* bit 1 = enable purple, bit 0 = enable white
|
||||
*********/
|
||||
static void led_prog_rand_on_rand_off()
|
||||
{
|
||||
int i;
|
||||
uint8_t fade;
|
||||
|
||||
if (!led_prog_wait) {
|
||||
// load new timer wait value
|
||||
led_prog_wait = led_prog_set_wait * 5;
|
||||
|
||||
// is this a new run?
|
||||
if (!led_prog_state[3]) {
|
||||
led_prog_state[3] = 1;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
led_level[LED_MATRIX_WHITE][i] = 0;
|
||||
led_level[LED_MATRIX_PURPLE][i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
led_prog_state[0] = led_prog_state[0] ? 0 : 1;
|
||||
|
||||
fade = 0;
|
||||
if (led_prog_set_option & 0x80) fade = 2;
|
||||
if (led_prog_set_option & 0x40) fade += 6;
|
||||
if (led_prog_set_option & 0x20) fade += 12;
|
||||
if (led_prog_set_option & 0x10) fade += 24;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (fade) {
|
||||
if (led_level[LED_MATRIX_WHITE][i] > fade) {
|
||||
led_level[LED_MATRIX_WHITE][i] -= fade;
|
||||
} else {
|
||||
led_level[LED_MATRIX_WHITE][i] = 0;
|
||||
}
|
||||
|
||||
if (led_level[LED_MATRIX_PURPLE][i] > fade) {
|
||||
led_level[LED_MATRIX_PURPLE][i] -= fade;
|
||||
} else {
|
||||
led_level[LED_MATRIX_PURPLE][i] = 0;
|
||||
}
|
||||
} else {
|
||||
led_level[LED_MATRIX_WHITE][i] = 0;
|
||||
led_level[LED_MATRIX_PURPLE][i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (led_prog_set_option & (1 << led_prog_state[0])) {
|
||||
led_level[led_prog_state[0]][pirate_prng() % 16] = led_prog_set_level >> (led_prog_state[0] << 3);
|
||||
}
|
||||
}
|
||||
|
||||
led_prog_wait--;
|
||||
}
|
||||
|
||||
/********
|
||||
* impulse spl meter
|
||||
* speed: ignored
|
||||
* options: bits7-0 = sensitivity
|
||||
*********/
|
||||
static void led_prog_mic_spl_meter()
|
||||
{
|
||||
int i;
|
||||
uint8_t set[2];
|
||||
|
||||
if (!led_prog_wait) {
|
||||
led_prog_wait = led_prog_set_wait * 5;
|
||||
|
||||
if (led_prog_work[0] > mic_peak) {
|
||||
led_prog_work[0] -= 4;
|
||||
} else {
|
||||
led_prog_work[0] = mic_peak;
|
||||
}
|
||||
|
||||
// scale peak value to calculated value and invert it
|
||||
led_prog_state[3] = pirate_scale(led_prog_work[0], settings.mic_cal[0], settings.mic_cal[1], 0, 255);
|
||||
|
||||
// and invert it
|
||||
led_prog_state[3] ^= 0xff;
|
||||
|
||||
// set defaults high level if not set
|
||||
if (!(led_prog_set_option >> 24)) led_prog_set_option |= (0xff << 24);
|
||||
|
||||
// stretch value with constrained bounds to original bounds
|
||||
led_prog_state[3] = pirate_scale(led_prog_state[3],
|
||||
(led_prog_set_option >> 16) & 0xff, (led_prog_set_option >> 24), 0, 255);
|
||||
|
||||
// finally determine which LEDs to light
|
||||
led_prog_state[3] = pirate_scale(led_prog_state[3], 0, 255, 0, 8);
|
||||
|
||||
// then set them
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (led_prog_state[3] < i) {
|
||||
set[0] = led_prog_set_level & 0xff;
|
||||
set[1] = led_prog_set_level >> 8;
|
||||
} else if (led_prog_state[3] == i) {
|
||||
set[0] = (led_prog_set_level & 0xff) >> 1;
|
||||
set[1] = led_prog_set_level >> 9;
|
||||
} else {
|
||||
set[0] = 0;
|
||||
set[1] = 0;
|
||||
}
|
||||
|
||||
led_level[LED_MATRIX_WHITE][i] = set[0];
|
||||
led_level[LED_MATRIX_WHITE][15 - i] = set[0];
|
||||
|
||||
led_level[LED_MATRIX_PURPLE][i] = set[1];
|
||||
led_level[LED_MATRIX_PURPLE][15 - i] = set[1];
|
||||
}
|
||||
}
|
||||
|
||||
led_prog_wait--;
|
||||
}
|
|
@ -0,0 +1,659 @@
|
|||
/**
|
||||
* Whiskey Pirates DC22 Badge "PIRATE CPU" Firmware
|
||||
* MCU firmware for STM32L100RBT6
|
||||
* Originally written 2014 by true, updates in 2015 for DC23 by true
|
||||
* Created: 2014.05.16
|
||||
* ts:4
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* ISR Usage ~13% average, 26% max (as of rev186)
|
||||
* Yeah, some of this shit is hackish. What do you expect from a hacker.
|
||||
* I'm sorry for some of the shit in here, 90% was written while sleep-deprived
|
||||
* plus I don't know wtf I am doing -- true
|
||||
*
|
||||
**/
|
||||
|
||||
|
||||
/* pirates */
|
||||
#include "pirate.h" // cmsis include is located here
|
||||
|
||||
#include "interface/gpio.h"
|
||||
#include "interface/led_pwm.h"
|
||||
#include "interface/adc.h"
|
||||
#include "interface/i2c.h"
|
||||
|
||||
#include "device/lcd.h"
|
||||
#include "device/beep.h"
|
||||
#include "device/attiny.h"
|
||||
#include "device/lightsensor.h"
|
||||
#include "device/radio/nrf.h"
|
||||
|
||||
#include "led/led_matrix.h"
|
||||
#include "led/led_bone.h"
|
||||
|
||||
#include "menu/lcd_menu.h"
|
||||
#include "menu/menu_settings.h" // settings_restore() lives here
|
||||
#include "menu/menu_program.h" // LED program related shit lives here
|
||||
|
||||
#include "display/infopirate.h"
|
||||
|
||||
|
||||
/* usb cdc serial port support */
|
||||
#include "usb/core/usb_lib.h"
|
||||
#include "usb/glue.h"
|
||||
|
||||
|
||||
// hard buttons
|
||||
static const tGPIO btn[4] = {
|
||||
{GPIOC, GPIO_Pin_0, 0},
|
||||
{GPIOA, GPIO_Pin_15, 15},
|
||||
{GPIOC, GPIO_Pin_1, 1},
|
||||
{GPIOB, GPIO_Pin_2, 2},
|
||||
};
|
||||
|
||||
#define BTN_DEBOUNCE_CYCLES 30
|
||||
|
||||
static const uint8_t btn_hilevel = 0b00001000; // button is active high when its bit is set, otherwise active low
|
||||
uint16_t btn_press[4];
|
||||
uint16_t btn_hold[4];
|
||||
|
||||
// main handler timer timekeeping
|
||||
uint32_t tim6_count;
|
||||
uint32_t tim6_usage; // profiling
|
||||
|
||||
|
||||
/* functions */
|
||||
/********
|
||||
* initialize main handler interrupt
|
||||
********/
|
||||
void pirate_tim6_init()
|
||||
{
|
||||
TIM_TimeBaseInitTypeDef tim_tb;
|
||||
NVIC_InitTypeDef nvic;
|
||||
|
||||
// enable peripheral clock
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
|
||||
|
||||
// set up to fire 0.2ms main handler loop (2.5KHz, ~12800 clocks per cycle)
|
||||
// LED light rate for main LED matrix looprate/16 (for 16 LEDs per matrix), which is 156Hz...
|
||||
TIM_TimeBaseStructInit(&tim_tb);
|
||||
tim_tb.TIM_Period = (SystemCoreClock / 2500) - 1;
|
||||
TIM_TimeBaseInit(TIM6, &tim_tb);
|
||||
|
||||
// enable interrupt
|
||||
TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
|
||||
|
||||
// set as highest priority - this is our UI handler too
|
||||
nvic.NVIC_IRQChannel = TIM6_IRQn;
|
||||
nvic.NVIC_IRQChannelPreemptionPriority = 2;
|
||||
nvic.NVIC_IRQChannelSubPriority = 1;
|
||||
nvic.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&nvic);
|
||||
|
||||
// finally, enable the timer
|
||||
TIM_Cmd(TIM6, ENABLE);
|
||||
|
||||
// make sure our profiling variable doesn't get optimized away
|
||||
__asm__ __volatile__("" :: "m" (tim6_usage));
|
||||
}
|
||||
|
||||
|
||||
/********
|
||||
* initialize gpio for buttons
|
||||
* this assumes the GPIOs are clocked already
|
||||
********/
|
||||
static inline void btn_init()
|
||||
{
|
||||
GPIO_InitTypeDef gpio;
|
||||
int i;
|
||||
|
||||
gpio.GPIO_Mode = GPIO_Mode_IN;
|
||||
gpio.GPIO_Speed = GPIO_Speed_400KHz;
|
||||
|
||||
for (i = 3; i >= 0; i--) {
|
||||
if (btn_hilevel & (1 << i)) {
|
||||
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
} else {
|
||||
gpio.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
}
|
||||
|
||||
gpio.GPIO_Pin = btn[i].pin;
|
||||
GPIO_Init(btn[i].port, &gpio);
|
||||
}
|
||||
|
||||
// set initial button types to operate the main menu
|
||||
// TODO: maybe this won't do this and it'll instead run the program by default
|
||||
menu_btntype_menus();
|
||||
}
|
||||
|
||||
|
||||
/********
|
||||
* default button push handlers
|
||||
* TODO: implement what is necessary to make these more useful
|
||||
********/
|
||||
static inline void btn_evt_push(uint16_t btn)
|
||||
{
|
||||
if (lcd_btn_fn[btn]) {
|
||||
lcd_btn_fn[btn]();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void btn_evt_hold(uint16_t btn, uint16_t count)
|
||||
{
|
||||
if (btn == BTN_UP || btn == BTN_DOWN) {
|
||||
if (!(count == 0 || count == 2)) {
|
||||
btn_evt_push(btn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void btn_evt_release(uint16_t btn)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/********
|
||||
* update the state of pressed buttons
|
||||
********/
|
||||
static inline void btn_update()
|
||||
{
|
||||
int i;
|
||||
int pressed;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
pressed = 0;
|
||||
|
||||
// button high or low?
|
||||
if (btn_hilevel & (1 << i)) {
|
||||
if (btn[i].pin & GPIO_ReadInputData(btn[i].port)) pressed = 1;
|
||||
} else {
|
||||
if (!(btn[i].pin & GPIO_ReadInputData(btn[i].port))) pressed = 1;
|
||||
}
|
||||
|
||||
if (pressed) {
|
||||
btn_press[i]++;
|
||||
if (btn_press[i] == BTN_DEBOUNCE_CYCLES) {
|
||||
// button is pushed
|
||||
btn_evt_push(i);
|
||||
} else if (btn_press[i] == 1500) {
|
||||
// btn is held
|
||||
btn_evt_hold(i, btn_hold[i]);
|
||||
|
||||
// btn is held for 0.3s (or re-fired 0.1s)
|
||||
btn_hold[i]++;
|
||||
// we only uniquely count 30 seconds of hold...
|
||||
if (btn_hold[i] > 30000) {
|
||||
btn_hold[i] = 30000;
|
||||
}
|
||||
// reset to re-fire in 0.1s increments
|
||||
btn_press[i] = 1000;
|
||||
}
|
||||
|
||||
// done handling buttons - we only do one pressed at a time right now
|
||||
break;
|
||||
} else {
|
||||
// if pushed, fire release event
|
||||
if (btn_press[i] > BTN_DEBOUNCE_CYCLES) {
|
||||
btn_evt_release(i);
|
||||
}
|
||||
// reset pushed state
|
||||
btn_press[i] = 0;
|
||||
btn_hold[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* startup */
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
// update clock info
|
||||
SystemCoreClockUpdate();
|
||||
|
||||
// enable gpio clocks
|
||||
// enable peripheral clocks
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
|
||||
|
||||
// set up LED matrix GPIO and clocks
|
||||
led_matrix_io_init();
|
||||
// set up bone LED GPIO and clocks
|
||||
led_bone_io_init();
|
||||
|
||||
// set up LED PWM peripherals
|
||||
led_pwm_init_all();
|
||||
|
||||
// set up buttons
|
||||
btn_init();
|
||||
|
||||
// read settings from EEPROM
|
||||
// NOTE: MENU button will load default settings (but keep name)
|
||||
// NOTE: MENU+OK will also erase name, restoring all defaults
|
||||
// TODO: separate programs from this, have another combo for erasing programs
|
||||
i = (GPIO_ReadInputDataBit(btn[BTN_MENU].port, btn[BTN_MENU].pin)) ? 0x00 : 0x01;
|
||||
if (i) i |= (GPIO_ReadInputDataBit(btn[BTN_OK].port, btn[BTN_OK].pin)) ? 0x00 : 0x02;
|
||||
|
||||
settings_restore(i);
|
||||
|
||||
// set up program run variables
|
||||
prog_init();
|
||||
|
||||
// set up ADC
|
||||
adc_init();
|
||||
|
||||
// set up I2C master peripheral (pegleg and LCD comms)
|
||||
i2c_init(I2C2, 400000);
|
||||
|
||||
// wait some more time for pegleg to boot. it can take a while
|
||||
pirate_delay(10);
|
||||
|
||||
// set up LCD
|
||||
lcd_init();
|
||||
lcd_cmd(LCD_CMD_CLEAR_SCREEN);
|
||||
|
||||
// set up LCD menus
|
||||
lcd_menu_init();
|
||||
|
||||
// set up LCD backlight
|
||||
lcd_led_init();
|
||||
|
||||
// set up USB
|
||||
USB_ClockEna();
|
||||
USB_Interrupts_Config();
|
||||
USB_Init_System();
|
||||
|
||||
pirate_delay(10); // need to wait a bit, if we start up too fast host won't find device
|
||||
USB_Init();
|
||||
|
||||
// set up magical beeper
|
||||
beep_init();
|
||||
|
||||
// and play startup tone
|
||||
beep(26, 40);
|
||||
beep(31, 40);
|
||||
beep(30, 40);
|
||||
beep(29, 40);
|
||||
beep(28, 40);
|
||||
|
||||
// need to wait some more for NRF to be ready to configure
|
||||
// this is per datasheet; it is probably actually working by now
|
||||
pirate_delay(50);
|
||||
// set up the radio
|
||||
nrf_init();
|
||||
|
||||
// set up pegleg light sensor gain
|
||||
if (settings.light_setgain) {
|
||||
// we have a fixed gain set
|
||||
light_gain = settings.light_setgain;
|
||||
attiny_write_light_sensitivity(0, light_gain);
|
||||
} else {
|
||||
// we don't have a fixed gain, so load a default gain value
|
||||
light_gain = LIGHTSENS_THRESH_TOP_NORM;
|
||||
attiny_write_light_sensitivity(0, LIGHTSENS_THRESH_TOP_NORM);
|
||||
}
|
||||
|
||||
// set up main handler interrupt
|
||||
pirate_tim6_init();
|
||||
|
||||
// after system is booted, we can enable the prefetch buffer
|
||||
// for some reason, at 32MHz, power glitches could cause some
|
||||
// freak out when booting if we turned this on any earlier
|
||||
FLASH->ACR |= FLASH_ACR_PRFTEN;
|
||||
|
||||
while (1) {
|
||||
// update clock info
|
||||
SystemCoreClockUpdate();
|
||||
|
||||
// update various low-priority things
|
||||
if (tim6_count % 500 == 0) {
|
||||
static volatile uint32_t update = 0;
|
||||
|
||||
update++;
|
||||
if (update == 20) update = 0;
|
||||
|
||||
switch (update) {
|
||||
case 1: { // light sensor
|
||||
// TODO: investigate the bug that causes this to read ~70-80 when it
|
||||
// should be reading >100
|
||||
if ((settings.led_autoadjust & 0x80) || settings.lcd_autobrite) {
|
||||
if (!settings.light_setgain) {
|
||||
light_level = attiny_read_light_level(0);
|
||||
}
|
||||
} else {
|
||||
light_level = settings.led_autogain_lev_max - 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
// auto-update light sensor gain
|
||||
if (!settings.light_setgain) {
|
||||
if (lightsensor_gainvalue_update()) {
|
||||
// updated, so send updated value
|
||||
attiny_write_light_sensitivity(0, light_gain);
|
||||
}
|
||||
} else {
|
||||
light_gain = settings.light_setgain;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
case 13: { // temp sensor
|
||||
pirate_thermometer_log(attiny_read_temp());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// max update 50 times/second
|
||||
if (tim6_count % 50 == 8) {
|
||||
// update eyes
|
||||
led_eyes_tx();
|
||||
|
||||
// update LCD contrast
|
||||
lcd_apply_contrast();
|
||||
|
||||
// update LCD CGRAM
|
||||
if (lcd_cgram_len) {
|
||||
// set LCD height
|
||||
// make sure in your code that you set this to CGRAM mode!
|
||||
lcd_cmd(lcd_get_height());
|
||||
|
||||
// only update CGRAM if we are in CGRAM mode
|
||||
if ((lcd_get_height() & 0x01) == 0) {
|
||||
// make sure to force updating the mode again
|
||||
lcd_cmd(lcd_get_height());
|
||||
// and update CGRAM contents
|
||||
for (i = 0; i < lcd_cgram_len; i++) {
|
||||
lcd_print(0x40 + (i << 3), lcd_cgram[i], 8);
|
||||
}
|
||||
lcd_cgram_len = 0;
|
||||
}
|
||||
} else {
|
||||
// set LCD height
|
||||
// this is here like this to fix compiler optimization bug?
|
||||
// TODO: find out wtf I meant by this
|
||||
lcd_cmd(lcd_get_height());
|
||||
}
|
||||
|
||||
// update LCD characters
|
||||
lcd_linebuf_send();
|
||||
|
||||
// set the LCD cursor position and type
|
||||
lcd_cmd(lcd_get_cursor_type());
|
||||
lcd_cmd(lcd_get_cursor_pos());
|
||||
}
|
||||
|
||||
// update battery voltage info 10 times/second
|
||||
if (tim6_count % 250 == 248) {
|
||||
pirate_batt_log(adc_result[ADC_READ_BATT_VOLTAGE]);
|
||||
}
|
||||
|
||||
// then go to sleep
|
||||
__WFI();
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* ISR */
|
||||
// main handler interrupt
|
||||
void TIM6_IRQHandler()
|
||||
{
|
||||
int i, j, k, n;
|
||||
static uint16_t nametx;
|
||||
|
||||
// update counter
|
||||
tim6_count++;
|
||||
if (tim6_count >= 2500) {
|
||||
tim6_count = 0;
|
||||
}
|
||||
|
||||
// manage buttons
|
||||
btn_update();
|
||||
|
||||
// update ADC values, currently 2.5KHz
|
||||
if ((tim6_count & 0x01) == 0x01) {
|
||||
adc_start();
|
||||
}
|
||||
|
||||
// update LED mic peak
|
||||
// mic peak decaying
|
||||
if ((tim6_count & 0x03) == 0x03) {
|
||||
if (mic_peak > adc_result[ADC_READ_MIC_PEAK]) {
|
||||
mic_peak--;
|
||||
} else {
|
||||
mic_peak = adc_result[ADC_READ_MIC_PEAK];
|
||||
}
|
||||
}
|
||||
|
||||
// update autoadjust value for LEDs, polls 25 times/second (40ms)
|
||||
if (tim6_count % 200 == 0) {
|
||||
uint8_t brightness;
|
||||
|
||||
// always need to run this as the LCD might use it
|
||||
lightsensor_scaler_update();
|
||||
|
||||
// backlight LCD is a little different
|
||||
brightness = settings.lcd_autobrite ?
|
||||
lightsensor_get_scalerval(LIGHTSENS_SCALED_BACKLIGHT) : settings.lcd_brightness;
|
||||
|
||||
lcd_led_set_level(brightness, 1);
|
||||
}
|
||||
|
||||
// update LCD backlight
|
||||
lcd_led_update();
|
||||
|
||||
// update main matrix LEDs
|
||||
led_matrix_mode_update();
|
||||
led_matrix_next();
|
||||
|
||||
// update bone matrix LEDs
|
||||
led_bone_mode_update();
|
||||
led_bone_next();
|
||||
|
||||
// update eyes RGBLEDs
|
||||
led_eyes_mode_update();
|
||||
|
||||
// update beeper
|
||||
beep_update();
|
||||
|
||||
// update LCD data 100Hz
|
||||
// yes, we only update it at 50Hz. but timings use 100Hz timings.
|
||||
if (tim6_count % 50 == 0) {
|
||||
if (menuc == (MenuItem *)&menu_runitem) {
|
||||
// run mode display
|
||||
infopirate_update();
|
||||
} else {
|
||||
// info display
|
||||
lcd_menu_update();
|
||||
}
|
||||
}
|
||||
|
||||
// runmode program
|
||||
if (tim6_count == 0) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (!(
|
||||
(menu_mode == MENU_MODE_RUNNING_PROGRAM)
|
||||
|| (menu_mode == MENU_MODE_PROGRAM_EDITOR)
|
||||
|| settings.autorun & 0x02)) {
|
||||
|
||||
// we aren't running the program or editing, so stop everything
|
||||
prog_id[i] = 255;
|
||||
switch (i) {
|
||||
case PROG_TYPE_SKULL: {
|
||||
led_matrix_set_mode(LED_MATRIX_MODE_OFF);
|
||||
break;
|
||||
}
|
||||
case PROG_TYPE_BONES: {
|
||||
led_bone_set_mode(LED_MATRIX_MODE_OFF);
|
||||
break;
|
||||
}
|
||||
case PROG_TYPE_EYES: {
|
||||
// only stop eyes if not in favcolor editor
|
||||
if (!(menuc->root == &menu_pref_ritem[1])) {
|
||||
led_eyes_set_mode(LED_EYES_MODE_OFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// we're running the program or editing a program. update the display
|
||||
if (prog_dwell[i] > 0) {
|
||||
prog_dwell[i]--;
|
||||
}
|
||||
if (prog_dwell[i] == 0) {
|
||||
if (menu_mode == MENU_MODE_PROGRAM_EDITOR) {
|
||||
// if we are editing, set up what we are trying to edit for preview
|
||||
n = menu_prog_get_type();
|
||||
j = menu_prog_get_idx();
|
||||
k = (prog_id[n] == 255 || (settings.led_prog[n][j].type & 0x02)) ? 1 : 0;
|
||||
|
||||
prog_id[i] = 0;
|
||||
prog_dwell[i] = k ? (settings.led_prog[n][j].dwell << 1) : k;
|
||||
|
||||
switch (n) {
|
||||
case PROG_TYPE_SKULL: {
|
||||
led_matrix_set_program(
|
||||
settings.led_prog[0][j].progidx,
|
||||
k,
|
||||
settings.led_prog[0][j].wait,
|
||||
settings.led_prog[0][j].level,
|
||||
settings.led_prog[0][j].offset,
|
||||
settings.led_prog[0][j].option
|
||||
);
|
||||
break;
|
||||
}
|
||||
case PROG_TYPE_BONES: {
|
||||
led_bone_set_program(
|
||||
settings.led_prog[1][j].progidx,
|
||||
k,
|
||||
settings.led_prog[1][j].wait,
|
||||
settings.led_prog[1][j].level,
|
||||
settings.led_prog[1][j].offset,
|
||||
settings.led_prog[1][j].option
|
||||
);
|
||||
break;
|
||||
}
|
||||
case PROG_TYPE_EYES: {
|
||||
led_eyes_set_program(
|
||||
settings.led_prog[2][j].progidx,
|
||||
k,
|
||||
settings.led_prog[2][j].wait,
|
||||
settings.led_prog[2][j].level,
|
||||
settings.led_prog[2][j].offset,
|
||||
settings.led_prog[2][j].option
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// we must be trying to run the program. show it all.
|
||||
j = PIRATE_PROG_SAVED_MAX + 1;
|
||||
k = prog_id[i];
|
||||
while (j) {
|
||||
j--;
|
||||
prog_id[i]++;
|
||||
if (prog_id[i] >= PIRATE_PROG_SAVED_MAX) prog_id[i] = 0;
|
||||
|
||||
if (settings.led_prog[i][prog_id[i]].type & 0x80) {
|
||||
// we have an enabled program
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j) {
|
||||
// load new program if it doesn't match the old program
|
||||
// or if a program was never run (such as at reboot)
|
||||
if (prog_get_mode(i) == 1) {
|
||||
k = (k == 255 || (settings.led_prog[i][prog_id[i]].type & 0x02)) ? 1 : 0;
|
||||
// program change check: (settings.led_prog[i][prog_id[i]].progidx != k)
|
||||
|
||||
prog_dwell[i] = (settings.led_prog[i][prog_id[i]].dwell << 1);
|
||||
|
||||
switch (i) {
|
||||
case PROG_TYPE_SKULL: {
|
||||
led_matrix_set_program(
|
||||
settings.led_prog[0][prog_id[0]].progidx,
|
||||
k,
|
||||
settings.led_prog[0][prog_id[0]].wait,
|
||||
settings.led_prog[0][prog_id[0]].level,
|
||||
settings.led_prog[0][prog_id[0]].offset,
|
||||
settings.led_prog[0][prog_id[0]].option
|
||||
);
|
||||
break;
|
||||
}
|
||||
case PROG_TYPE_BONES: {
|
||||
led_bone_set_program(
|
||||
settings.led_prog[1][prog_id[1]].progidx,
|
||||
k,
|
||||
settings.led_prog[1][prog_id[1]].wait,
|
||||
settings.led_prog[1][prog_id[1]].level,
|
||||
settings.led_prog[1][prog_id[1]].offset,
|
||||
settings.led_prog[1][prog_id[1]].option
|
||||
);
|
||||
break;
|
||||
}
|
||||
case PROG_TYPE_EYES: {
|
||||
led_eyes_set_program(
|
||||
settings.led_prog[2][prog_id[2]].progidx,
|
||||
k,
|
||||
settings.led_prog[2][prog_id[2]].wait,
|
||||
settings.led_prog[2][prog_id[2]].level,
|
||||
settings.led_prog[2][prog_id[2]].offset,
|
||||
settings.led_prog[2][prog_id[2]].option
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// send nametx packet
|
||||
if (dc23_nametx && tim6_count % 500 == 4) {
|
||||
if (nametx == 2) {
|
||||
// send first packet
|
||||
nrf_tx_buf[0] = NRF_CMD_DC22_23GREET;
|
||||
nrf_tx_buf[1] = 22;
|
||||
nrf_tx_buf[2] = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
nrf_tx_buf[3 + i] = settings.name[i];
|
||||
}
|
||||
nrf_tx_buf[7] = nrf_checksum(nrf_tx_buf, 7, 0);
|
||||
nRF24_packet_tx(nrf_tx_buf, NRF_PAYLOAD_LEN, 1);
|
||||
} else if (nametx == 1) {
|
||||
// send second packet
|
||||
nrf_tx_buf[0] = NRF_CMD_DC22_23GREET;
|
||||
nrf_tx_buf[1] = 22;
|
||||
nrf_tx_buf[2] = 1;
|
||||
for (i = 0; i < 4; i++) {
|
||||
nrf_tx_buf[3 + i] = settings.name[4 + i];
|
||||
}
|
||||
nrf_tx_buf[7] = nrf_checksum(nrf_tx_buf, 7, 0);
|
||||
nRF24_packet_tx(nrf_tx_buf, NRF_PAYLOAD_LEN, 1);
|
||||
}
|
||||
|
||||
if (nametx) {
|
||||
nametx--;
|
||||
} else {
|
||||
nametx = dc23_nametx * 600;
|
||||
}
|
||||
}
|
||||
|
||||
// profiling: get current counter value
|
||||
tim6_usage = tim6_usage;
|
||||
tim6_usage = TIM6->CNT;
|
||||
|
||||
// clear interrupt bit
|
||||
TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
|
||||
}
|
|
@ -0,0 +1,735 @@
|
|||
/**
|
||||
* lcd_menu.c: lcd menuing functions, in particular editing functions
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: lcd_menu.c 368 2015-06-16 06:49:48Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#include <pirate.h>
|
||||
|
||||
#include "../interface/i2c.h" // for writing tempcal to attiny
|
||||
#include "../device/lcd.h" // lcd constants, modes and buffer routines
|
||||
|
||||
#include "../device/attiny.h" // for temperature offset editing
|
||||
#include "../device/lightsensor.h" // for light gain editing
|
||||
#include "../device/beep.h" // for letting you know you did something
|
||||
|
||||
#include "../display/infopirate.h"
|
||||
#include "lcd_menu.h"
|
||||
|
||||
#include "menu_radio.h" // all the various submenu helper functions and root menu declarations
|
||||
#include "menu_settings.h" // editing handlers are in this file though
|
||||
#include "menu_program.h" // the actual submenus are in their respective files
|
||||
#include "menu_sensors.h" // this is what happens when sleep deprived
|
||||
#include "menu_testing.h"
|
||||
#include "menu_credits.h"
|
||||
|
||||
|
||||
/* lcd */
|
||||
MenuItem *menuc;
|
||||
uint8_t menu_mode;
|
||||
|
||||
static uint16_t line_idx[2] = {0xffff, 0xffff};
|
||||
static uint16_t line_time[2] = {0, 0};
|
||||
|
||||
static uint8_t lcd_fn_time = 0;
|
||||
static char lcd_fn_output[64];
|
||||
|
||||
void (*lcd_btn_fn[4])();
|
||||
|
||||
|
||||
/* menus */
|
||||
uint16_t menu_editing;
|
||||
uint32_t menu_oldval;
|
||||
uint32_t menu_newval;
|
||||
|
||||
const MenuItem menu_runitem; // used for run mode
|
||||
|
||||
|
||||
/* functions */
|
||||
void lcd_menu_init()
|
||||
{
|
||||
// initial menu
|
||||
if (settings.autorun & 0x01) {
|
||||
menuc = (MenuItem *)&menu_runitem;
|
||||
menu_root_run(0);
|
||||
} else {
|
||||
menuc = (MenuItem *)&menu_ritem[0];
|
||||
menu_btntype_menus();
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_menu_set(const MenuItem *set)
|
||||
{
|
||||
menuc = (MenuItem *)set;
|
||||
}
|
||||
|
||||
void lcd_menu_linescroll_reset(uint8_t idx)
|
||||
{
|
||||
line_time[idx] = 0;
|
||||
line_idx[idx] = 0xffff;
|
||||
}
|
||||
|
||||
static uint8_t lcd_menu_linescroll(uint8_t idx, char *dst, char *src, uint8_t maxlen,
|
||||
uint8_t spaces, uint16_t time_wait, uint16_t time_run)
|
||||
{
|
||||
int i;
|
||||
int len;
|
||||
|
||||
char *cpy;
|
||||
uint16_t copied = 0;
|
||||
|
||||
len = strlen(src);
|
||||
|
||||
// is this line too long?
|
||||
if (len > maxlen) {
|
||||
// begin scrolling.
|
||||
// if timeout occurred, update the index
|
||||
if (line_time[idx] == 0) {
|
||||
// set the pause time based on the max length plus padding spaces
|
||||
// if we are over this limit, we are in "start over" phase and need to use that delay
|
||||
if (line_idx[idx] > len + spaces) {
|
||||
// this is where we start or start over
|
||||
line_time[idx] = time_wait;
|
||||
line_idx[idx] = 0;
|
||||
} else {
|
||||
// we are in normal continuing phase, use the continuing delay and increment index
|
||||
line_time[idx] = time_run;
|
||||
line_idx[idx]++;
|
||||
}
|
||||
}
|
||||
line_time[idx]--;
|
||||
|
||||
// figure out how much to copy
|
||||
cpy = src + line_idx[idx];
|
||||
len = ((len - maxlen) > line_idx[idx]) ?
|
||||
maxlen :
|
||||
len - line_idx[idx];
|
||||
|
||||
// copy up to and including the trailing edge of the text
|
||||
if (len > 0) {
|
||||
for (i = 0; i < len && copied < maxlen; i++) {
|
||||
*dst++ = *cpy++;
|
||||
copied++;
|
||||
}
|
||||
}
|
||||
|
||||
// if we have more left than the length provided, we are done
|
||||
if (len >= maxlen) {
|
||||
return maxlen;
|
||||
}
|
||||
|
||||
// otherwise, we need to add some spaces
|
||||
i = spaces;
|
||||
if (len < 0) {
|
||||
i += len;
|
||||
}
|
||||
|
||||
// copy the spaces into the stream
|
||||
if (i) {
|
||||
for (; i > 0 && (copied < maxlen); i--) {
|
||||
*dst++ = 0x20;
|
||||
copied++;
|
||||
}
|
||||
}
|
||||
|
||||
// and, if we have room, copy starting from the beginning of the source
|
||||
while (copied < maxlen) {
|
||||
*dst++ = *src++;
|
||||
copied++;
|
||||
}
|
||||
|
||||
return maxlen;
|
||||
} else {
|
||||
// nope, just copy directly
|
||||
strncpy(dst, src, maxlen);
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_menu_update()
|
||||
{
|
||||
int line_len;
|
||||
int i;
|
||||
|
||||
// header line static text
|
||||
if (menuc->root == 0) {
|
||||
lcd_menu_linescroll(0, lcd_line[0], LCD_ROOT_TEXT, LCD_MAX_LINE_LENGTH,
|
||||
LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN);
|
||||
} else if ((int)menuc->root > 255) {
|
||||
lcd_menu_linescroll(0, lcd_line[0], menuc->root->this->disp, LCD_MAX_LINE_LENGTH,
|
||||
menuc->root->this->scroll_spaces, menuc->root->this->scroll_time_wait,
|
||||
menuc->root->this->scroll_time_run);
|
||||
} else {
|
||||
// maybe we can do other special shit here later
|
||||
// if set to 255, then external tasks need to update this line
|
||||
}
|
||||
|
||||
// TODO: show header line dynamic text? or flag?
|
||||
|
||||
// do we update the function-based string?
|
||||
if (!lcd_fn_time) {
|
||||
// reset the timeout value
|
||||
lcd_fn_time = menuc->this->dispfn_delay;
|
||||
|
||||
// if there was no timeout value, we need to fake one
|
||||
if (lcd_fn_time == 0) {
|
||||
lcd_fn_time++;
|
||||
}
|
||||
|
||||
// if there is a function attached, call it
|
||||
if (menuc->this->dispfn != NULL) {
|
||||
strncpy(lcd_fn_output, menuc->this->dispfn(menuc->this->disp_id), 63);
|
||||
lcd_fn_output[63] = 0;
|
||||
} else {
|
||||
// no function? no data.
|
||||
lcd_fn_output[0] = 0;
|
||||
}
|
||||
}
|
||||
lcd_fn_time--;
|
||||
|
||||
// second line static text
|
||||
line_len = lcd_menu_linescroll(1, lcd_line[1], menuc->this->disp, LCD_MAX_LINE_LENGTH,
|
||||
menuc->this->scroll_spaces, menuc->this->scroll_time_wait, menuc->this->scroll_time_run);
|
||||
// second line dynamic text
|
||||
if (line_len < LCD_MAX_LINE_LENGTH) {
|
||||
lcd_menu_linescroll(1, lcd_line[1] + line_len, lcd_fn_output, LCD_MAX_LINE_LENGTH - line_len,
|
||||
menuc->this->scroll_spaces, menuc->this->scroll_time_wait, menuc->this->scroll_time_run);
|
||||
}
|
||||
|
||||
// fix any nulls
|
||||
for (i = 0; i < 9; i++) {
|
||||
if (!lcd_line[0][i]) lcd_line[0][i] = 0x20;
|
||||
if (!lcd_line[1][i]) lcd_line[1][i] = 0x20;
|
||||
}
|
||||
}
|
||||
|
||||
/* menu nav functions */
|
||||
void menu_btn_next()
|
||||
{
|
||||
if (menuc->next != 0) {
|
||||
lcd_menu_set(menuc->next);
|
||||
lcd_menu_linescroll_reset(1);
|
||||
lcd_fn_output[0] = 0;
|
||||
|
||||
if (settings.beeper) {
|
||||
beep(settings.beep_type[0], 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void menu_btn_prev()
|
||||
{
|
||||
if (menuc->prev != 0) {
|
||||
lcd_menu_set(menuc->prev);
|
||||
lcd_menu_linescroll_reset(1);
|
||||
lcd_fn_output[0] = 0;
|
||||
|
||||
if (settings.beeper) {
|
||||
beep(settings.beep_type[0], 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void menu_btn_menu()
|
||||
{
|
||||
if (menuc->root) {
|
||||
// call the root menu's entry function
|
||||
if (menuc->root->this->entryfn != NULL) {
|
||||
menuc->root->this->entryfn(menuc->root->this->entry_id);
|
||||
}
|
||||
|
||||
// and set to that menu
|
||||
lcd_menu_set(menuc->root);
|
||||
lcd_menu_linescroll_reset(0);
|
||||
lcd_menu_linescroll_reset(1);
|
||||
lcd_fn_output[0] = 0;
|
||||
|
||||
if (settings.beeper) {
|
||||
beep(settings.beep_type[0] - 1, 10);
|
||||
}
|
||||
}
|
||||
|
||||
menu_btntype_menus();
|
||||
}
|
||||
|
||||
void menu_btn_ok()
|
||||
{
|
||||
// call this menu's entry function
|
||||
if (menuc->this->entryfn != NULL) {
|
||||
menuc->this->entryfn(menuc->this->entry_id);
|
||||
if (settings.beeper) {
|
||||
beep(settings.beep_type[0] + 1, 10);
|
||||
}
|
||||
}
|
||||
|
||||
// and set to the new menu if available
|
||||
if (menuc->enter) {
|
||||
lcd_menu_set(menuc->enter);
|
||||
lcd_menu_linescroll_reset(0);
|
||||
lcd_menu_linescroll_reset(1);
|
||||
lcd_fn_output[0] = 0;
|
||||
if (settings.beeper) {
|
||||
beep(settings.beep_type[0], 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* menu edit functions */
|
||||
void menu_edit_next()
|
||||
{
|
||||
int work;
|
||||
int do_beep = 0;
|
||||
|
||||
switch (menu_editing) {
|
||||
case SETTING_NAME: {
|
||||
break;
|
||||
}
|
||||
|
||||
case SETTING_CONTRAST: {
|
||||
if (menu_newval < 63) {
|
||||
menu_newval++;
|
||||
lcd_set_contrast(menu_newval);
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SETTING_FAVCOLOR_RED:
|
||||
case SETTING_FAVCOLOR_GREEN:
|
||||
case SETTING_FAVCOLOR_BLUE: {
|
||||
if (menu_newval < 0xff) {
|
||||
menu_newval++;
|
||||
settings.fav_color[menu_editing - SETTING_FAVCOLOR_RED] = menu_newval;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SETTING_BEEP_TYPE_BUTTON:
|
||||
case SETTING_BEEP_TYPE_PAGING:
|
||||
case SETTING_BEEP_TYPE_ALARM: {
|
||||
if (menu_newval < 30) {
|
||||
menu_newval++;
|
||||
settings.beep_type[menu_editing - SETTING_BEEP_TYPE_BUTTON] = menu_newval;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SENSOR_LIGHT_SETTINGSGAIN: {
|
||||
if (menu_newval == 0) {
|
||||
menu_newval = LIGHTSENS_GAIN_MIN;
|
||||
do_beep = settings.beeper;
|
||||
} else if (menu_newval < LIGHTSENS_GAIN_MAX) {
|
||||
menu_newval++;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
|
||||
settings.light_setgain = menu_newval;
|
||||
break;
|
||||
}
|
||||
|
||||
case SETTING_BRITE_LCD_VALUE: {
|
||||
if (menu_newval < 200) {
|
||||
menu_newval++;
|
||||
settings.lcd_brightness = menu_newval;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SETTING_BRITE_AUTOGAIN_LO: {
|
||||
if (menu_newval < 160) {
|
||||
menu_newval++;
|
||||
settings.led_autogain_lev_min = menu_newval;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SETTING_BRITE_AUTOGAIN_HI: {
|
||||
if (menu_newval < 160) {
|
||||
menu_newval++;
|
||||
settings.led_autogain_lev_max = menu_newval;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SETTING_BRITE_THRESH0:
|
||||
case SETTING_BRITE_THRESH1:
|
||||
case SETTING_BRITE_THRESH2:
|
||||
case SETTING_BRITE_THRESH3:
|
||||
case SETTING_BRITE_THRESH4: {
|
||||
work = menu_editing - SETTING_BRITE_THRESH0;
|
||||
|
||||
if (menu_editing == SETTING_BRITE_THRESH4) {
|
||||
work = LIGHTSENS_GAIN_MAX;
|
||||
} else {
|
||||
work = settings.led_autothresh[work + 1] - 1;
|
||||
}
|
||||
|
||||
if (menu_newval < work) {
|
||||
menu_newval++;
|
||||
settings.led_autothresh[menu_editing - SETTING_BRITE_THRESH0] = menu_newval;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SENSOR_TEMP_CALVALUE: {
|
||||
if (temperature_cal < 60) {
|
||||
temperature_cal++;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_beep) {
|
||||
beep(settings.beep_type[0], 10);
|
||||
}
|
||||
}
|
||||
|
||||
void menu_edit_prev()
|
||||
{
|
||||
int work;
|
||||
int do_beep = 0;
|
||||
|
||||
switch (menu_editing) {
|
||||
case SETTING_NAME: {
|
||||
break;
|
||||
}
|
||||
|
||||
case SETTING_CONTRAST: {
|
||||
if (settings.contrast) {
|
||||
menu_newval--;
|
||||
lcd_set_contrast(menu_newval);
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SETTING_FAVCOLOR_RED:
|
||||
case SETTING_FAVCOLOR_GREEN:
|
||||
case SETTING_FAVCOLOR_BLUE: {
|
||||
if (menu_newval) {
|
||||
menu_newval--;
|
||||
settings.fav_color[menu_editing - SETTING_FAVCOLOR_RED] = menu_newval;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SETTING_BEEP_TYPE_BUTTON:
|
||||
case SETTING_BEEP_TYPE_PAGING:
|
||||
case SETTING_BEEP_TYPE_ALARM: {
|
||||
if (menu_newval > 1) {
|
||||
menu_newval--;
|
||||
settings.beep_type[menu_editing - SETTING_BEEP_TYPE_BUTTON] = menu_newval;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SENSOR_LIGHT_SETTINGSGAIN: {
|
||||
if (menu_newval > LIGHTSENS_GAIN_MIN) {
|
||||
menu_newval--;
|
||||
do_beep = settings.beeper;
|
||||
} else if (menu_newval == LIGHTSENS_GAIN_MIN) {
|
||||
menu_newval = 0;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
|
||||
settings.light_setgain = menu_newval;
|
||||
break;
|
||||
}
|
||||
|
||||
case SETTING_BRITE_LCD_VALUE: {
|
||||
if (menu_newval) {
|
||||
menu_newval--;
|
||||
settings.lcd_brightness = menu_newval;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SETTING_BRITE_AUTOGAIN_LO: {
|
||||
if (menu_newval > 0) {
|
||||
menu_newval--;
|
||||
settings.led_autogain_lev_min = menu_newval;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SETTING_BRITE_AUTOGAIN_HI: {
|
||||
if (menu_newval > 0) {
|
||||
menu_newval--;
|
||||
settings.led_autogain_lev_max = menu_newval;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SETTING_BRITE_THRESH0:
|
||||
case SETTING_BRITE_THRESH1:
|
||||
case SETTING_BRITE_THRESH2:
|
||||
case SETTING_BRITE_THRESH3:
|
||||
case SETTING_BRITE_THRESH4: {
|
||||
work = menu_editing - SETTING_BRITE_THRESH0;
|
||||
|
||||
if (!work) {
|
||||
work = LIGHTSENS_GAIN_MIN;
|
||||
} else {
|
||||
work = settings.led_autothresh[work - 1] + 1;
|
||||
}
|
||||
|
||||
if (menu_newval > work) {
|
||||
menu_newval--;
|
||||
settings.led_autothresh[menu_editing - SETTING_BRITE_THRESH0] = menu_newval;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SENSOR_TEMP_CALVALUE: {
|
||||
if (temperature_cal > -20) {
|
||||
temperature_cal--;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_beep) {
|
||||
beep(settings.beep_type[0], 10);
|
||||
}
|
||||
}
|
||||
|
||||
void menu_edit_menu()
|
||||
{
|
||||
// values in this switch need to REVERT previous settings
|
||||
switch (menu_editing) {
|
||||
case SETTING_NAME: {
|
||||
break;
|
||||
}
|
||||
|
||||
case SETTING_CONTRAST: {
|
||||
lcd_set_contrast(menu_oldval);
|
||||
break;
|
||||
}
|
||||
|
||||
case SETTING_FAVCOLOR_RED:
|
||||
case SETTING_FAVCOLOR_GREEN:
|
||||
case SETTING_FAVCOLOR_BLUE: {
|
||||
settings.fav_color[menu_editing - SETTING_FAVCOLOR_RED] = menu_oldval;
|
||||
break;
|
||||
}
|
||||
|
||||
case SETTING_BEEP_TYPE_BUTTON:
|
||||
case SETTING_BEEP_TYPE_PAGING:
|
||||
case SETTING_BEEP_TYPE_ALARM: {
|
||||
settings.beep_type[menu_editing - SETTING_BEEP_TYPE_BUTTON] = menu_oldval;
|
||||
break;
|
||||
}
|
||||
|
||||
case SENSOR_LIGHT_SETTINGSGAIN: {
|
||||
settings.light_setgain = menu_oldval;
|
||||
break;
|
||||
}
|
||||
|
||||
case SETTING_BRITE_LCD_VALUE: {
|
||||
settings.lcd_brightness = menu_oldval;
|
||||
break;
|
||||
}
|
||||
case SETTING_BRITE_AUTOGAIN_LO: {
|
||||
settings.led_autogain_lev_min = menu_oldval;
|
||||
break;
|
||||
}
|
||||
case SETTING_BRITE_AUTOGAIN_HI: {
|
||||
settings.led_autogain_lev_max = menu_oldval;
|
||||
break;
|
||||
}
|
||||
case SETTING_BRITE_THRESH0:
|
||||
case SETTING_BRITE_THRESH1:
|
||||
case SETTING_BRITE_THRESH2:
|
||||
case SETTING_BRITE_THRESH3:
|
||||
case SETTING_BRITE_THRESH4: {
|
||||
settings.led_autothresh[menu_editing - SETTING_BRITE_THRESH0] = menu_oldval;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case SENSOR_TEMP_CALVALUE: {
|
||||
temperature_cal = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// stop editing and return to menu control
|
||||
menu_editing = 0;
|
||||
menu_btntype_menus();
|
||||
|
||||
if (settings.beeper) {
|
||||
beep(settings.beep_type[0], 10);
|
||||
}
|
||||
}
|
||||
|
||||
void menu_edit_ok()
|
||||
{
|
||||
// values in this switch need to COMMIT edited settings
|
||||
switch (menu_editing) {
|
||||
case SENSOR_TEMP_CALVALUE: {
|
||||
I2C_WriteTransfer(ATTINY_I2C_ADDR, (uint8_t *)&temperature_cal, 1, ATTINY_CMD_TEMP_CAL, 1);
|
||||
temperature_cal = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {break;}
|
||||
}
|
||||
|
||||
// stop editing and return to menu control
|
||||
menu_editing = 0;
|
||||
menu_btntype_menus();
|
||||
|
||||
if (settings.beeper) {
|
||||
beep(settings.beep_type[0] + 1, 10);
|
||||
}
|
||||
}
|
||||
|
||||
void menu_edit_start(uint16_t id)
|
||||
{
|
||||
menu_editing = id;
|
||||
|
||||
// set edited value
|
||||
switch (id) {
|
||||
case SETTING_CONTRAST: {
|
||||
menu_oldval = menu_newval = settings.contrast;
|
||||
break;
|
||||
}
|
||||
|
||||
case SETTING_FAVCOLOR_RED:
|
||||
case SETTING_FAVCOLOR_GREEN:
|
||||
case SETTING_FAVCOLOR_BLUE: {
|
||||
menu_newval = menu_oldval = settings.fav_color[menu_editing - SETTING_FAVCOLOR_RED];
|
||||
break;
|
||||
}
|
||||
|
||||
case SETTING_BEEP_TYPE_BUTTON:
|
||||
case SETTING_BEEP_TYPE_PAGING:
|
||||
case SETTING_BEEP_TYPE_ALARM: {
|
||||
menu_newval = menu_oldval = settings.beep_type[menu_editing - SETTING_BEEP_TYPE_BUTTON];
|
||||
break;
|
||||
}
|
||||
|
||||
case SENSOR_LIGHT_SETTINGSGAIN: {
|
||||
menu_newval = menu_oldval = settings.light_setgain;
|
||||
break;
|
||||
}
|
||||
|
||||
case SETTING_BRITE_LCD_VALUE: {
|
||||
menu_newval = menu_oldval = settings.lcd_brightness;
|
||||
break;
|
||||
}
|
||||
case SETTING_BRITE_AUTOGAIN_LO: {
|
||||
menu_newval = menu_oldval = settings.led_autogain_lev_min;
|
||||
break;
|
||||
}
|
||||
case SETTING_BRITE_AUTOGAIN_HI: {
|
||||
menu_newval = menu_oldval = settings.led_autogain_lev_max;
|
||||
break;
|
||||
}
|
||||
case SETTING_BRITE_THRESH0:
|
||||
case SETTING_BRITE_THRESH1:
|
||||
case SETTING_BRITE_THRESH2:
|
||||
case SETTING_BRITE_THRESH3:
|
||||
case SETTING_BRITE_THRESH4: {
|
||||
menu_newval = menu_oldval = settings.led_autothresh[menu_editing - SETTING_BRITE_THRESH0];
|
||||
break;
|
||||
}
|
||||
|
||||
case SENSOR_TEMP_CALVALUE: {
|
||||
temperature_cal = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// set buttons to editing control
|
||||
menu_btntype_editing();
|
||||
}
|
||||
|
||||
/* menu fn pointer set functions */
|
||||
void menu_btntype_menus()
|
||||
{
|
||||
menu_mode = MENU_MODE_NAVIGATING_MENUS;
|
||||
|
||||
lcd_btn_fn[BTN_UP] = menu_btn_prev;
|
||||
lcd_btn_fn[BTN_MENU] = menu_btn_menu;
|
||||
lcd_btn_fn[BTN_OK] = menu_btn_ok;
|
||||
lcd_btn_fn[BTN_DOWN] = menu_btn_next;
|
||||
|
||||
lcd_set_cursor(LCD_LINE_1, LCD_CMD_NO_CURSOR_FLASH);
|
||||
lcd_set_height(LCD_CMD_SINGLEHEIGHT);
|
||||
}
|
||||
|
||||
void menu_btntype_run()
|
||||
{
|
||||
menu_mode = MENU_MODE_RUNNING_PROGRAM;
|
||||
|
||||
lcd_btn_fn[BTN_UP] = menu_infopirate_btn_prev;
|
||||
lcd_btn_fn[BTN_MENU] = menu_btn_menu;
|
||||
lcd_btn_fn[BTN_OK] = menu_infopirate_btn_ok;
|
||||
lcd_btn_fn[BTN_DOWN] = menu_infopirate_btn_next;
|
||||
|
||||
lcd_set_cursor(LCD_LINE_1, LCD_CMD_NO_CURSOR_FLASH);
|
||||
lcd_set_height(LCD_CMD_DOUBLEHEIGHT);
|
||||
}
|
||||
|
||||
void menu_btntype_editing()
|
||||
{
|
||||
menu_mode = MENU_MODE_EDITING;
|
||||
|
||||
lcd_btn_fn[BTN_UP] = menu_edit_prev;
|
||||
lcd_btn_fn[BTN_MENU] = menu_edit_menu;
|
||||
lcd_btn_fn[BTN_OK] = menu_edit_ok;
|
||||
lcd_btn_fn[BTN_DOWN] = menu_edit_next;
|
||||
|
||||
lcd_set_cursor(LCD_LINE_2 + 7, LCD_CMD_CURSOR_FLASH);
|
||||
}
|
||||
|
||||
// run mode
|
||||
void menu_root_run(uint16_t id)
|
||||
{
|
||||
prog_init();
|
||||
infopirate_init();
|
||||
menu_btntype_run();
|
||||
}
|
||||
|
||||
|
||||
/* menu construction */
|
||||
// root menu
|
||||
const MenuData menu_rdata[9] = {
|
||||
{"Run!", NULL, 0, 0, 0, 0, 0, menu_root_run, 0},
|
||||
{"Radio", NULL, 0, 0, 0, 0, 0, NULL, 0},
|
||||
{"Settings", NULL, 0, 0, 0, 0, 0, NULL, 0},
|
||||
{"Programs", NULL, 0, 0, 0, 0, 0, NULL, 0},
|
||||
{"Save", NULL, 0, 0, 0, 0, 0, menu_settings_save, 0},
|
||||
{"Sensors", NULL, 0, 0, 0, 0, 0, NULL, 0},
|
||||
{"Testing", NULL, 0, 0, 0, 0, 0, NULL, 0},
|
||||
{"Credits", NULL, 0, 0, 0, 0, 0, NULL, 0},
|
||||
{"Shutdown", NULL, 0, 0, 0, 0, 0, pirate_shutdown, 0}
|
||||
};
|
||||
const MenuItem menu_ritem[9] = {
|
||||
{0, 0, &menu_ritem[1], &menu_runitem, &menu_rdata[0]},
|
||||
{0, &menu_ritem[0], &menu_ritem[2], &menu_comm_ritem[0], &menu_rdata[1]},
|
||||
{0, &menu_ritem[1], &menu_ritem[3], &menu_pref_ritem[0], &menu_rdata[2]},
|
||||
{0, &menu_ritem[2], &menu_ritem[4], &menu_prog_ritem[0], &menu_rdata[3]},
|
||||
{0, &menu_ritem[3], &menu_ritem[5], 0, &menu_rdata[4]},
|
||||
{0, &menu_ritem[4], &menu_ritem[6], &menu_sens_ritem[0], &menu_rdata[5]},
|
||||
{0, &menu_ritem[5], &menu_ritem[7], &menu_test_ritem[0], &menu_rdata[6]},
|
||||
{0, &menu_ritem[6], &menu_ritem[8], &menu_cred_ritem[0], &menu_rdata[7]},
|
||||
{0, &menu_ritem[7], 0, 0, &menu_rdata[8]},
|
||||
};
|
||||
|
||||
// run entry
|
||||
const MenuData menu_rundata = {"", NULL, 0, 4, 0, 0, 0, NULL, 0};
|
||||
const MenuItem menu_runitem = {&menu_ritem[0], 0, 0, 0, &menu_rundata};
|
|
@ -0,0 +1,106 @@
|
|||
/**
|
||||
* lcd_menu.c: lcd menuing prototypes
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: lcd_menu.h 374 2015-06-29 02:06:22Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_LCD_MENU_H
|
||||
#define __PIRATE_LCD_MENU_H
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define LCD_ROOT_TEXT "WP DC22 and DC23 Badge v0.3d by true"
|
||||
|
||||
#define LCD_DEF_SPACING 4
|
||||
#define LCD_DEF_SCROLL_WAIT 144
|
||||
#define LCD_DEF_SCROLL_RUN 16
|
||||
|
||||
#define LCD_MENU_ROOT_COMMS 1
|
||||
#define LCD_MENU_ROOT_SETTINGS 2
|
||||
#define LCD_MENU_ROOT_PROGRAMS 3
|
||||
#define LCD_MENU_ROOT_SENSORS 5
|
||||
#define LCD_MENU_ROOT_TESTING 6
|
||||
#define LCD_MENU_ROOT_CREDITS 7
|
||||
|
||||
#define BTN_UP 0
|
||||
#define BTN_MENU 1
|
||||
#define BTN_OK 2
|
||||
#define BTN_DOWN 3
|
||||
|
||||
#define MENU_MODE_NAVIGATING_MENUS 0
|
||||
#define MENU_MODE_EDITING 1
|
||||
#define MENU_MODE_RUNNING_PROGRAM 2
|
||||
#define MENU_MODE_PROGRAM_EDITOR 3
|
||||
|
||||
|
||||
/* struct */
|
||||
typedef struct MenuData {
|
||||
char *disp; // string to display
|
||||
char * (*dispfn)(uint16_t id); // function which returns string to display
|
||||
uint16_t disp_id; // index to pass to dispfn
|
||||
uint8_t dispfn_delay; // how many 5000hz ticks to wait before re-calling dispfn
|
||||
uint8_t scroll_spaces; // how many spaces between scroll; 0 disables scroll
|
||||
uint8_t scroll_time_wait; // how long to wait before (re)scrolling
|
||||
uint8_t scroll_time_run; // how long to wait between characters
|
||||
void (*entryfn)(uint16_t eid); // function to call when entering menu
|
||||
uint16_t entry_id; // index to pass to entryfn
|
||||
} MenuData;
|
||||
|
||||
typedef struct MenuItem MenuItem;
|
||||
struct MenuItem {
|
||||
const MenuItem *root;
|
||||
const MenuItem *prev;
|
||||
const MenuItem *next;
|
||||
const MenuItem *enter;
|
||||
const MenuData *this;
|
||||
};
|
||||
|
||||
|
||||
/* lcd variables */
|
||||
extern MenuItem *menuc;
|
||||
extern const MenuItem menu_ritem[9];
|
||||
|
||||
extern void (*lcd_btn_fn[4])();
|
||||
|
||||
|
||||
/* menu variables */
|
||||
extern uint8_t menu_mode;
|
||||
|
||||
extern uint16_t menu_editing;
|
||||
extern uint32_t menu_oldval;
|
||||
extern uint32_t menu_newval;
|
||||
|
||||
|
||||
/* menu constants */
|
||||
extern const MenuItem menu_runitem;
|
||||
|
||||
|
||||
/* prototypes */
|
||||
void lcd_menu_init();
|
||||
void lcd_menu_set(const MenuItem *set);
|
||||
void lcd_menu_update();
|
||||
|
||||
void lcd_menu_linescroll_reset(uint8_t idx);
|
||||
|
||||
void menu_edit_start(uint16_t id);
|
||||
void menu_root_run(uint16_t id);
|
||||
|
||||
void menu_btn_next();
|
||||
void menu_btn_prev();
|
||||
void menu_btn_menu();
|
||||
void menu_btn_ok();
|
||||
|
||||
void menu_btntype_menus();
|
||||
void menu_btntype_run();
|
||||
void menu_btntype_editing();
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* menu_credits.c: we are legit
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: menu_credits.c 350 2015-05-28 02:23:03Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#include <pirate.h>
|
||||
|
||||
#include "lcd_menu.h"
|
||||
#include "menu_credits.h"
|
||||
|
||||
|
||||
/* menu construction */
|
||||
const MenuData menu_cred_rdata[] = {
|
||||
{"idea by rCON and true (at the last minute)", NULL, 0, 0, 3, LCD_DEF_SCROLL_WAIT - 40, LCD_DEF_SCROLL_RUN - 4, NULL, 0},
|
||||
{"T3K shipmates Bad Kobold and the lord canon", NULL, 0, 0, 3, LCD_DEF_SCROLL_WAIT - 40, LCD_DEF_SCROLL_RUN - 4, NULL, 0},
|
||||
{"a fire? don't blame us if you didn't know", NULL, 0, 0, 3, LCD_DEF_SCROLL_WAIT - 40, LCD_DEF_SCROLL_RUN - 4, NULL, 0},
|
||||
{"financed by captain rCON's billions", NULL, 0, 0, 3, LCD_DEF_SCROLL_WAIT - 40, LCD_DEF_SCROLL_RUN - 4, NULL, 0},
|
||||
{"code and design rushed by true", NULL, 0, 0, 3, LCD_DEF_SCROLL_WAIT - 40, LCD_DEF_SCROLL_RUN - 4, NULL, 0},
|
||||
{"the lord canon's divorce", NULL, 0, 0, 3, LCD_DEF_SCROLL_WAIT - 40, LCD_DEF_SCROLL_RUN - 4, NULL, 0},
|
||||
{"keep it between the bones, guys", NULL, 0, 0, 3, LCD_DEF_SCROLL_WAIT - 40, LCD_DEF_SCROLL_RUN - 4, NULL, 0},
|
||||
{"is your badge shit? did it break? blame BK", NULL, 0, 0, 3, LCD_DEF_SCROLL_WAIT - 40, LCD_DEF_SCROLL_RUN - 4, NULL, 0},
|
||||
{"always need moar cake from avah", NULL, 0, 0, 3, LCD_DEF_SCROLL_WAIT - 40, LCD_DEF_SCROLL_RUN - 4, NULL, 0},
|
||||
{"do what you want 'cause a pirate is free", NULL, 0, 0, 3, LCD_DEF_SCROLL_WAIT - 40, LCD_DEF_SCROLL_RUN - 4, NULL, 0},
|
||||
{"you are A PIRATE", NULL, 0, 0, 3, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN + 2, NULL, 0}
|
||||
};
|
||||
const MenuItem menu_cred_ritem[] = {
|
||||
{&menu_ritem[LCD_MENU_ROOT_CREDITS], 0, &menu_cred_ritem[1], 0, &menu_cred_rdata[0]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_CREDITS], &menu_cred_ritem[0], &menu_cred_ritem[2], 0, &menu_cred_rdata[1]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_CREDITS], &menu_cred_ritem[1], &menu_cred_ritem[3], 0, &menu_cred_rdata[2]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_CREDITS], &menu_cred_ritem[2], &menu_cred_ritem[4], 0, &menu_cred_rdata[3]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_CREDITS], &menu_cred_ritem[3], &menu_cred_ritem[5], 0, &menu_cred_rdata[4]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_CREDITS], &menu_cred_ritem[4], &menu_cred_ritem[6], 0, &menu_cred_rdata[5]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_CREDITS], &menu_cred_ritem[5], &menu_cred_ritem[7], 0, &menu_cred_rdata[6]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_CREDITS], &menu_cred_ritem[6], &menu_cred_ritem[7], 0, &menu_cred_rdata[7]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_CREDITS], &menu_cred_ritem[7], &menu_cred_ritem[8], 0, &menu_cred_rdata[8]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_CREDITS], &menu_cred_ritem[8], &menu_cred_ritem[10], 0, &menu_cred_rdata[9]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_CREDITS], &menu_cred_ritem[9], 0, 0, &menu_cred_rdata[10]}
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* menu_credits.h: we are a pirates
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: menu_credits.h 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_MENU_CREDITS_H
|
||||
#define __PIRATE_MENU_CREDITS_H
|
||||
|
||||
|
||||
|
||||
/* credits menus */
|
||||
extern const MenuItem menu_cred_ritem[];
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,786 @@
|
|||
/**
|
||||
* menu_program.c: led and lcd program selection and configuration
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: menu_program.c 368 2015-06-16 06:49:48Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#include <pirate.h>
|
||||
|
||||
#include "../device/lcd.h"
|
||||
|
||||
#include "../device/attiny.h" // eyes
|
||||
#include "../device/beep.h"
|
||||
|
||||
#include "../led/led_matrix.h"
|
||||
#include "../led/led_bone.h"
|
||||
|
||||
#include "lcd_menu.h"
|
||||
#include "menu_program.h"
|
||||
|
||||
|
||||
// programs
|
||||
static char prog_str[20]; // program names max 16 characters (currently coded to 15 characters)
|
||||
|
||||
static uint8_t prog_type; // which menu has been selected (skull, bones, eyes)
|
||||
static uint8_t prog_idx; // which program is being edited within the menu
|
||||
|
||||
static uint16_t prog_hex_val; // the value being edited
|
||||
|
||||
extern uint16_t menu_editing; // lcd_menu.h
|
||||
extern uint32_t menu_oldval;
|
||||
extern uint32_t menu_newval;
|
||||
|
||||
// program running
|
||||
uint8_t prog_id[3];
|
||||
uint16_t prog_dwell[3];
|
||||
|
||||
// program names
|
||||
const char led_matrix_prog_name[LED_MATRIX_PROG_COUNT][16];
|
||||
const char led_bone_prog_name[LED_BONE_PROG_COUNT][16];
|
||||
const char led_eyes_prog_name[LED_EYES_PROG_COUNT][16];
|
||||
|
||||
const char (*prog_name[3])[16] = {
|
||||
led_matrix_prog_name,
|
||||
led_bone_prog_name,
|
||||
led_eyes_prog_name
|
||||
};
|
||||
const uint8_t prog_count[3] = {
|
||||
LED_MATRIX_PROG_COUNT,
|
||||
LED_BONE_PROG_COUNT,
|
||||
LED_EYES_PROG_COUNT
|
||||
};
|
||||
|
||||
|
||||
// programs menu forward declaration
|
||||
const MenuItem menu_prog_leditem[];
|
||||
const MenuItem menu_prog_ledaitem;
|
||||
|
||||
|
||||
/* external program functions */
|
||||
/********
|
||||
* initialize variables for program running
|
||||
********/
|
||||
void prog_init()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
prog_id[i] = 255;
|
||||
prog_dwell[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t prog_get_mode(uint8_t id)
|
||||
{
|
||||
return (settings.led_prog_mode >> (id << 1)) & 0x03;
|
||||
}
|
||||
|
||||
uint8_t menu_prog_get_type()
|
||||
{
|
||||
return prog_type;
|
||||
}
|
||||
|
||||
uint8_t menu_prog_get_idx()
|
||||
{
|
||||
return prog_idx;
|
||||
}
|
||||
|
||||
/* program functions */
|
||||
char * menu_prog_disp(uint16_t id)
|
||||
{
|
||||
switch (id) {
|
||||
case PROG_GLOBAL_MODE: {
|
||||
switch ((settings.led_prog_mode >> (prog_type << 1)) & 0x03) {
|
||||
case 0b00: return " Off";
|
||||
case 0b01: return "Nrml";
|
||||
case 0b10: return "Rand";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
case PROG_GLOBAL_CHANGEIDX: {
|
||||
prog_str[0] = '#';
|
||||
prog_str[1] = 0;
|
||||
strncat(prog_str, pirate_sitoa(prog_idx + 1, 10, 2), 4);
|
||||
if (prog_str[1] == 0x00 || prog_str[1] == 0x20) prog_str[1] = 0x30;
|
||||
return prog_str;
|
||||
}
|
||||
|
||||
case PROG_EDIT_ENABLE: {
|
||||
if (settings.led_prog[prog_type][prog_idx].type & 0x80) {
|
||||
return "Y";
|
||||
} else {
|
||||
return "N";
|
||||
}
|
||||
}
|
||||
case PROG_EDIT_FORCE_INIT: {
|
||||
if (settings.led_prog[prog_type][prog_idx].type & 0x02) {
|
||||
return "Y";
|
||||
} else {
|
||||
return "N";
|
||||
}
|
||||
}
|
||||
case PROG_EDIT_PROG_ID: {
|
||||
prog_str[0] = 0;
|
||||
prog_str[1] = 0;
|
||||
strncat(prog_str, pirate_sitoa(settings.led_prog[prog_type][prog_idx].progidx, 10, 2), 4);
|
||||
if (prog_str[0] == 0x00 || prog_str[0] == 0x20) prog_str[0] = 0x30;
|
||||
return prog_str;
|
||||
}
|
||||
|
||||
default: {return "";}
|
||||
}
|
||||
}
|
||||
|
||||
char * prog_type_edit_str(uint16_t id) {
|
||||
switch (id) {
|
||||
case PROG_TYPE_SKULL: {strcpy(prog_str, "Skull "); prog_str[5] = 0; break;}
|
||||
case PROG_TYPE_BONES: {strcpy(prog_str, "Bones "); prog_str[5] = 0; break;}
|
||||
case PROG_TYPE_EYES: {strcpy(prog_str, "Eyes "); prog_str[5] = 0; break;}
|
||||
case PROG_TYPE_INFOPIR8: return "InfoPir8";
|
||||
}
|
||||
|
||||
if (menu_mode == MENU_MODE_PROGRAM_EDITOR) {
|
||||
if (prog_idx < PIRATE_PROG_SAVED_MAX) {
|
||||
strncat(prog_str, "#", 8);
|
||||
strncat(prog_str, pirate_sitoa(prog_idx + 1, 10, 2), 8);
|
||||
|
||||
if (prog_str[6] == 0x20 || prog_str[6] == 0x00) prog_str[6] = 0x30;
|
||||
}
|
||||
}
|
||||
|
||||
prog_str[8] = 0x00;
|
||||
|
||||
return prog_str;
|
||||
}
|
||||
|
||||
char * prog_dwell_str(uint16_t id)
|
||||
{
|
||||
strcpy(prog_str, pirate_sitoa(settings.led_prog[prog_type][prog_idx].dwell, 10, 2));
|
||||
|
||||
if (settings.led_prog[prog_type][prog_idx].dwell <= 99) {
|
||||
strncat(prog_str, "s", 4);
|
||||
}
|
||||
|
||||
return prog_str;
|
||||
}
|
||||
|
||||
char * prog_advanced_str(uint16_t id)
|
||||
{
|
||||
uint32_t work;
|
||||
|
||||
switch (menu_editing) {
|
||||
case PROG_EDIT_PROG_ID: {
|
||||
work = settings.led_prog[prog_type][prog_idx].progidx;
|
||||
strcpy(prog_str, pirate_sitoa(work, 10, 0));
|
||||
strncat(prog_str, ":", 19);
|
||||
strncat(prog_str, prog_name[prog_type][work], 19);
|
||||
prog_str[19] = 0;
|
||||
return prog_str;
|
||||
}
|
||||
case PROG_EDIT_CYCLESPEED: {
|
||||
work = settings.led_prog[prog_type][prog_idx].wait;
|
||||
strcpy(prog_str, pirate_sitoa(work, 10, 6));
|
||||
strncat(prog_str, "ms", 8);
|
||||
prog_str[8] = 0;
|
||||
return prog_str;
|
||||
}
|
||||
case PROG_EDIT_LED_LEVEL: {
|
||||
work = settings.led_prog[prog_type][prog_idx].level;
|
||||
strcpy(prog_str, " 0x");
|
||||
strncat(prog_str, pirate_itoa(work, 16, 4), 6);
|
||||
|
||||
for (work = 3; work < 6; work++) {
|
||||
if (prog_str[work] == 0x00 || prog_str[work] == 0x20) prog_str[work] = 0x30;
|
||||
}
|
||||
|
||||
prog_str[8] = 0;
|
||||
return prog_str;
|
||||
}
|
||||
case PROG_EDIT_LED_OFFSET: {
|
||||
work = settings.led_prog[prog_type][prog_idx].offset;
|
||||
strncpy(prog_str, pirate_itoa(work, 16, 8), 8);
|
||||
|
||||
for (work = 0; work < 8; work++) {
|
||||
if (prog_str[work] == 0x00 || prog_str[work] == 0x20) prog_str[work] = 0x30;
|
||||
}
|
||||
|
||||
prog_str[8] = 0;
|
||||
return prog_str;
|
||||
}
|
||||
case PROG_EDIT_LED_OPTIONS: {
|
||||
work = settings.led_prog[prog_type][prog_idx].option;
|
||||
strncpy(prog_str, pirate_itoa(work, 16, 8), 8);
|
||||
|
||||
for (work = 0; work < 8; work++) {
|
||||
if (prog_str[work] == 0x00 || prog_str[work] == 0x20) prog_str[work] = 0x30;
|
||||
}
|
||||
|
||||
prog_str[8] = 0;
|
||||
return prog_str;
|
||||
}
|
||||
|
||||
default: {return "";}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* program editing */
|
||||
void menu_prog_edit_start(uint16_t id)
|
||||
{
|
||||
int cursor = 0;
|
||||
|
||||
menu_editing = id;
|
||||
|
||||
switch (id) {
|
||||
case PROG_EDIT_PROG_DWELL: {
|
||||
menu_newval = menu_oldval = settings.led_prog[prog_type][prog_idx].dwell;
|
||||
break;
|
||||
}
|
||||
|
||||
case PROG_GLOBAL_CHANGEIDX: {
|
||||
menu_newval = menu_oldval = prog_idx;
|
||||
break;
|
||||
}
|
||||
|
||||
case PROG_EDIT_PROG_ID: {
|
||||
menuc = (MenuItem *)&menu_prog_ledaitem;
|
||||
strcpy(lcd_line[0], "Choose: ");
|
||||
menu_oldval = settings.led_prog[prog_type][prog_idx].progidx;
|
||||
cursor = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case PROG_EDIT_CYCLESPEED: {
|
||||
menuc = (MenuItem *)&menu_prog_ledaitem;
|
||||
strcpy(lcd_line[0], "CycleSpd");
|
||||
menu_oldval = settings.led_prog[prog_type][prog_idx].wait;
|
||||
cursor = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cursor) {
|
||||
lcd_set_cursor(LCD_LINE_2 + 7, LCD_CMD_CURSOR_FLASH);
|
||||
}
|
||||
}
|
||||
|
||||
void prog_edit_tog_mode(uint16_t id)
|
||||
{
|
||||
int mode;
|
||||
|
||||
mode = (settings.led_prog_mode >> (prog_type << 1)) & 0b11;
|
||||
mode++;
|
||||
|
||||
if (mode > 2) mode = 0;
|
||||
|
||||
settings.led_prog_mode &= ~(0b11 << (prog_type << 1));
|
||||
settings.led_prog_mode |= (mode << (prog_type << 1));
|
||||
}
|
||||
|
||||
void prog_edit_tog_enable(uint16_t id)
|
||||
{
|
||||
if (prog_idx < PIRATE_PROG_SAVED_MAX) {
|
||||
if (settings.led_prog[prog_type][prog_idx].type & 0x80) {
|
||||
settings.led_prog[prog_type][prog_idx].type &= 0x7f;
|
||||
} else {
|
||||
settings.led_prog[prog_type][prog_idx].type |= 0x80;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void prog_edit_tog_type(uint16_t id)
|
||||
{
|
||||
if (prog_idx < PIRATE_PROG_SAVED_MAX) {
|
||||
if (settings.led_prog[prog_type][prog_idx].type & 0x01) {
|
||||
settings.led_prog[prog_type][prog_idx].type &= 0xfe;
|
||||
} else {
|
||||
settings.led_prog[prog_type][prog_idx].type |= 0x01;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void prog_edit_tog_force_init(uint16_t id)
|
||||
{
|
||||
if (prog_idx < PIRATE_PROG_SAVED_MAX) {
|
||||
if (settings.led_prog[prog_type][prog_idx].type & 0x02) {
|
||||
settings.led_prog[prog_type][prog_idx].type &= 0xfd;
|
||||
} else {
|
||||
settings.led_prog[prog_type][prog_idx].type |= 0x02;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* program button handlers */
|
||||
static void menu_btn_prog_prev()
|
||||
{
|
||||
int do_beep = 0;
|
||||
uint32_t work;
|
||||
|
||||
switch (menu_editing) {
|
||||
case 0: {
|
||||
menu_btn_prev();
|
||||
break;
|
||||
}
|
||||
|
||||
case PROG_EDIT_PROG_DWELL: {
|
||||
if (menu_newval > 1) {
|
||||
menu_newval--;
|
||||
settings.led_prog[prog_type][prog_idx].dwell = menu_newval;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PROG_GLOBAL_CHANGEIDX: {
|
||||
if (menu_newval) {
|
||||
menu_newval--;
|
||||
prog_idx = menu_newval;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROG_EDIT_PROG_ID: {
|
||||
if (settings.led_prog[prog_type][prog_idx].progidx) {
|
||||
settings.led_prog[prog_type][prog_idx].progidx--;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROG_EDIT_CYCLESPEED: {
|
||||
work = settings.led_prog[prog_type][prog_idx].wait;
|
||||
do_beep = settings.beeper;
|
||||
|
||||
if (work > 1000) {
|
||||
settings.led_prog[prog_type][prog_idx].wait -= 50;
|
||||
} else if (work > 100) {
|
||||
settings.led_prog[prog_type][prog_idx].wait -= 20;
|
||||
} else if (work > 10) {
|
||||
settings.led_prog[prog_type][prog_idx].wait -= 5;
|
||||
} else if (work > 1) {
|
||||
settings.led_prog[prog_type][prog_idx].wait--;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_beep) {
|
||||
beep(settings.beep_type[0], 10);
|
||||
}
|
||||
|
||||
lcd_menu_linescroll_reset(1);
|
||||
}
|
||||
|
||||
static void menu_btn_prog_next()
|
||||
{
|
||||
int do_beep = 0;
|
||||
uint32_t work;
|
||||
|
||||
switch (menu_editing) {
|
||||
case 0: {
|
||||
menu_btn_next();
|
||||
break;
|
||||
}
|
||||
|
||||
case PROG_EDIT_PROG_DWELL: {
|
||||
if (menu_newval < 240) {
|
||||
menu_newval++;
|
||||
settings.led_prog[prog_type][prog_idx].dwell = menu_newval;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PROG_GLOBAL_CHANGEIDX: {
|
||||
if (menu_newval < PIRATE_PROG_SAVED_MAX - 1) {
|
||||
menu_newval++;
|
||||
prog_idx = menu_newval;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROG_EDIT_PROG_ID: {
|
||||
if (settings.led_prog[prog_type][prog_idx].progidx < (prog_count[prog_type] - 1)) {
|
||||
settings.led_prog[prog_type][prog_idx].progidx++;
|
||||
do_beep = settings.beeper;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PROG_EDIT_CYCLESPEED: {
|
||||
work = settings.led_prog[prog_type][prog_idx].wait;
|
||||
do_beep = settings.beeper;
|
||||
|
||||
if (work < 10) {
|
||||
settings.led_prog[prog_type][prog_idx].wait++;
|
||||
} else if (work < 100) {
|
||||
settings.led_prog[prog_type][prog_idx].wait += 5;
|
||||
} else if (work < 1000) {
|
||||
settings.led_prog[prog_type][prog_idx].wait += 20;
|
||||
} else if (work < 5000) {
|
||||
settings.led_prog[prog_type][prog_idx].wait += 50;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_beep) {
|
||||
beep(settings.beep_type[0], 10);
|
||||
}
|
||||
|
||||
lcd_menu_linescroll_reset(1);
|
||||
}
|
||||
|
||||
static void menu_btn_prog_menu()
|
||||
{
|
||||
switch (menu_editing) {
|
||||
case 0: {
|
||||
menuc = (MenuItem *)&menu_prog_ritem[prog_type];
|
||||
|
||||
prog_type = 0;
|
||||
prog_idx = 0;
|
||||
|
||||
menu_btntype_menus();
|
||||
|
||||
if (settings.beeper) {
|
||||
beep(settings.beep_type[0] - 1, 10);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case PROG_EDIT_PROG_DWELL: {
|
||||
settings.led_prog[prog_type][prog_idx].dwell = menu_oldval;
|
||||
break;
|
||||
}
|
||||
|
||||
case PROG_GLOBAL_CHANGEIDX: {
|
||||
prog_idx = menu_oldval;
|
||||
break;
|
||||
}
|
||||
|
||||
case PROG_EDIT_PROG_ID: {
|
||||
settings.led_prog[prog_type][prog_idx].progidx = menu_oldval;
|
||||
strcpy(lcd_line[0], prog_type_edit_str(prog_type));
|
||||
menuc = (MenuItem *)&menu_prog_leditem[5];
|
||||
break;
|
||||
}
|
||||
case PROG_EDIT_CYCLESPEED: {
|
||||
settings.led_prog[prog_type][prog_idx].wait = menu_oldval;
|
||||
strcpy(lcd_line[0], prog_type_edit_str(prog_type));
|
||||
menuc = (MenuItem *)&menu_prog_leditem[6];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
menu_editing = 0;
|
||||
|
||||
lcd_set_cursor(LCD_LINE_2 + 7, LCD_CMD_NO_CURSOR_FLASH);
|
||||
|
||||
if (settings.beeper) {
|
||||
beep(settings.beep_type[0], 10);
|
||||
}
|
||||
}
|
||||
|
||||
static void menu_btn_prog_ok()
|
||||
{
|
||||
switch (menu_editing) {
|
||||
case 0: {
|
||||
menu_btn_ok();
|
||||
return;
|
||||
}
|
||||
|
||||
case PROG_GLOBAL_CHANGEIDX: {
|
||||
strcpy(lcd_line[0], prog_type_edit_str(prog_type));
|
||||
break;
|
||||
}
|
||||
|
||||
case PROG_EDIT_PROG_ID: {
|
||||
strcpy(lcd_line[0], prog_type_edit_str(prog_type));
|
||||
menuc = (MenuItem *)&menu_prog_leditem[5];
|
||||
break;
|
||||
}
|
||||
case PROG_EDIT_CYCLESPEED: {
|
||||
strcpy(lcd_line[0], prog_type_edit_str(prog_type));
|
||||
menuc = (MenuItem *)&menu_prog_leditem[6];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
menu_editing = 0;
|
||||
|
||||
lcd_set_cursor(LCD_LINE_2 + 7, LCD_CMD_NO_CURSOR_FLASH);
|
||||
|
||||
if (settings.beeper) {
|
||||
beep(settings.beep_type[0] + 1, 10);
|
||||
}
|
||||
}
|
||||
|
||||
static void menu_prog_hexedit_adj(uint32_t val, uint8_t offset, uint8_t size, uint8_t direction)
|
||||
{
|
||||
uint32_t mask;
|
||||
uint32_t work;
|
||||
uint8_t nybble;
|
||||
|
||||
nybble = (offset + size - menu_oldval - 1) << 2;
|
||||
|
||||
// create a mask of the affected bits
|
||||
mask = (0xf << nybble);
|
||||
// extract and shift the working bits
|
||||
work = ((val & mask) >> (nybble)) & 0xf;
|
||||
// clear working bits in value
|
||||
val &= ~mask;
|
||||
// increment/decrement them
|
||||
if (direction) work++; else work--;
|
||||
// shift them back and restore them to value
|
||||
val |= (work << nybble) & mask;
|
||||
|
||||
switch (menu_editing) {
|
||||
case PROG_EDIT_LED_LEVEL: {
|
||||
settings.led_prog[prog_type][prog_idx].level = (uint16_t)val;
|
||||
break;
|
||||
}
|
||||
case PROG_EDIT_LED_OFFSET: {
|
||||
settings.led_prog[prog_type][prog_idx].offset = val;
|
||||
break;
|
||||
}
|
||||
case PROG_EDIT_LED_OPTIONS: {
|
||||
settings.led_prog[prog_type][prog_idx].option = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void menu_prog_hexedit_prev()
|
||||
{
|
||||
uint32_t val = 0;
|
||||
uint8_t size = 8;
|
||||
uint8_t start = 0;
|
||||
|
||||
switch (menu_editing) {
|
||||
case PROG_EDIT_LED_LEVEL: {
|
||||
val = settings.led_prog[prog_type][prog_idx].level;
|
||||
size = 4;
|
||||
start = 3;
|
||||
break;
|
||||
}
|
||||
case PROG_EDIT_LED_OFFSET: {
|
||||
val = settings.led_prog[prog_type][prog_idx].offset;
|
||||
break;
|
||||
}
|
||||
case PROG_EDIT_LED_OPTIONS: {
|
||||
val = settings.led_prog[prog_type][prog_idx].option;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (menu_newval) {
|
||||
menu_prog_hexedit_adj(val, start, size, 0);
|
||||
} else {
|
||||
if (menu_oldval > start) {
|
||||
menu_oldval--;
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.beeper) {
|
||||
beep(settings.beep_type[0], 10);
|
||||
}
|
||||
|
||||
lcd_set_cursor(LCD_LINE_2 + menu_oldval, 0);
|
||||
}
|
||||
|
||||
static void menu_prog_hexedit_next()
|
||||
{
|
||||
uint32_t val = 0;
|
||||
uint8_t size = 8;
|
||||
uint8_t start = 0;
|
||||
uint8_t end = 7;
|
||||
|
||||
switch (menu_editing) {
|
||||
case PROG_EDIT_LED_LEVEL: {
|
||||
val = settings.led_prog[prog_type][prog_idx].level;
|
||||
size = 4;
|
||||
start = 3;
|
||||
end = 6;
|
||||
break;
|
||||
}
|
||||
case PROG_EDIT_LED_OFFSET: {
|
||||
val = settings.led_prog[prog_type][prog_idx].offset;
|
||||
break;
|
||||
}
|
||||
case PROG_EDIT_LED_OPTIONS: {
|
||||
val = settings.led_prog[prog_type][prog_idx].option;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (menu_newval) {
|
||||
menu_prog_hexedit_adj(val, start, size, 1);
|
||||
} else {
|
||||
if (menu_oldval < end) {
|
||||
menu_oldval++;
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.beeper) {
|
||||
beep(settings.beep_type[0], 10);
|
||||
}
|
||||
|
||||
lcd_set_cursor(LCD_LINE_2 + menu_oldval, 0);
|
||||
}
|
||||
|
||||
static void menu_prog_hexedit_ok()
|
||||
{
|
||||
menu_newval ^= 1;
|
||||
|
||||
if (menu_newval) {
|
||||
lcd_set_cursor(LCD_LINE_2 + menu_oldval, LCD_CMD_CURSOR_FLASH);
|
||||
} else {
|
||||
lcd_set_cursor(LCD_LINE_2 + menu_oldval, LCD_CMD_CURSOR_UNDER);
|
||||
}
|
||||
|
||||
if (settings.beeper) {
|
||||
beep(settings.beep_type[0] + 1, 10);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void menu_prog_hexedit_menu()
|
||||
{
|
||||
int id;
|
||||
|
||||
switch (menu_editing) {
|
||||
case PROG_EDIT_LED_LEVEL: {id = 7; break;}
|
||||
case PROG_EDIT_LED_OFFSET: {id = 8; break;}
|
||||
case PROG_EDIT_LED_OPTIONS: {id = 9; break;}
|
||||
default: {id = 0; break;}
|
||||
}
|
||||
|
||||
strcpy(lcd_line[0], prog_type_edit_str(prog_type));
|
||||
|
||||
menu_editing = 0;
|
||||
|
||||
lcd_set_cursor(LCD_LINE_2 + 7, LCD_CMD_NO_CURSOR_FLASH);
|
||||
|
||||
menuc = (MenuItem *)&menu_prog_leditem[id];
|
||||
menu_btntype_program();
|
||||
|
||||
if (settings.beeper) {
|
||||
beep(settings.beep_type[0] - 1, 10);
|
||||
}
|
||||
}
|
||||
|
||||
void menu_btntype_program()
|
||||
{
|
||||
menu_mode = MENU_MODE_PROGRAM_EDITOR;
|
||||
|
||||
lcd_btn_fn[BTN_UP] = menu_btn_prog_prev;
|
||||
lcd_btn_fn[BTN_MENU] = menu_btn_prog_menu;
|
||||
lcd_btn_fn[BTN_OK] = menu_btn_prog_ok;
|
||||
lcd_btn_fn[BTN_DOWN] = menu_btn_prog_next;
|
||||
}
|
||||
|
||||
static void menu_prog_enter_led(uint16_t id)
|
||||
{
|
||||
prog_type = id;
|
||||
prog_idx = 0;
|
||||
|
||||
menuc = (MenuItem *)&menu_prog_leditem[0];
|
||||
|
||||
menu_btntype_program();
|
||||
|
||||
strcpy(lcd_line[0], prog_type_edit_str(id));
|
||||
}
|
||||
|
||||
static void menu_prog_hexedit_start(uint16_t id)
|
||||
{
|
||||
// oldval is cursor pos, newval is editing-is-on
|
||||
menu_newval = 0;
|
||||
menu_editing = id;
|
||||
|
||||
menuc = (MenuItem *)&menu_prog_ledaitem;
|
||||
|
||||
switch (id) {
|
||||
case PROG_EDIT_LED_LEVEL: {
|
||||
strcpy(lcd_line[0], "Level: ");
|
||||
menu_oldval = 3;
|
||||
prog_hex_val = settings.led_prog[prog_type][prog_idx].level;
|
||||
break;
|
||||
}
|
||||
case PROG_EDIT_LED_OFFSET: {
|
||||
strcpy(lcd_line[0], "Offset: ");
|
||||
menu_oldval = 0;
|
||||
prog_hex_val = settings.led_prog[prog_type][prog_idx].offset;
|
||||
break;
|
||||
}
|
||||
case PROG_EDIT_LED_OPTIONS: {
|
||||
strcpy(lcd_line[0], "Options:");
|
||||
menu_oldval = 0;
|
||||
prog_hex_val = settings.led_prog[prog_type][prog_idx].option;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lcd_set_cursor(LCD_LINE_2 + menu_oldval, LCD_CMD_CURSOR_UNDER);
|
||||
|
||||
lcd_btn_fn[BTN_UP] = menu_prog_hexedit_prev;
|
||||
lcd_btn_fn[BTN_MENU] = menu_prog_hexedit_menu;
|
||||
lcd_btn_fn[BTN_OK] = menu_prog_hexedit_ok;
|
||||
lcd_btn_fn[BTN_DOWN] = menu_prog_hexedit_next;
|
||||
}
|
||||
|
||||
|
||||
/* menu construction */
|
||||
// programs menu
|
||||
const MenuData menu_prog_rdata[] = {
|
||||
{"", prog_type_edit_str, PROG_TYPE_SKULL, 0, 0, 0, 0, menu_prog_enter_led, PROG_TYPE_SKULL},
|
||||
{"", prog_type_edit_str, PROG_TYPE_BONES, 0, 0, 0, 0, menu_prog_enter_led, PROG_TYPE_BONES},
|
||||
{"", prog_type_edit_str, PROG_TYPE_EYES, 0, 0, 0, 0, menu_prog_enter_led, PROG_TYPE_EYES},
|
||||
{"", prog_type_edit_str, PROG_TYPE_INFOPIR8, 0, 0, 0, 0, NULL, 0},
|
||||
};
|
||||
const MenuItem menu_prog_ritem[] = {
|
||||
{&menu_ritem[LCD_MENU_ROOT_PROGRAMS], 0, &menu_prog_ritem[1], 0, &menu_prog_rdata[0]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_PROGRAMS], &menu_prog_ritem[0], &menu_prog_ritem[2], 0, &menu_prog_rdata[1]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_PROGRAMS], &menu_prog_ritem[1], &menu_prog_ritem[3], 0, &menu_prog_rdata[2]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_PROGRAMS], &menu_prog_ritem[2], 0, 0, &menu_prog_rdata[3]},
|
||||
};
|
||||
|
||||
const MenuData menu_prog_leddata[] = {
|
||||
{"Mode", menu_prog_disp, PROG_GLOBAL_MODE, 0, 0, 0, 0, prog_edit_tog_mode, 0},
|
||||
{"Edit ", menu_prog_disp, PROG_GLOBAL_CHANGEIDX, 0, 0, 0, 0, menu_prog_edit_start, PROG_GLOBAL_CHANGEIDX},
|
||||
{"Enable ", menu_prog_disp, PROG_EDIT_ENABLE, 0, 0, 0, 0, prog_edit_tog_enable, 0},
|
||||
{"Dwell", prog_dwell_str, PROG_EDIT_PROG_DWELL, 0, 0, 0, 0, menu_prog_edit_start, PROG_EDIT_PROG_DWELL},
|
||||
{"PID #", menu_prog_disp, PROG_EDIT_PROG_ID, 0, 0, 0, 0, menu_prog_edit_start, PROG_EDIT_PROG_ID},
|
||||
{"CycleSpd", NULL, 0, 0, 0, 0, 0, menu_prog_edit_start, PROG_EDIT_CYCLESPEED},
|
||||
{"LEDLevel", NULL, 0, 0, 0, 0, 0, menu_prog_hexedit_start, PROG_EDIT_LED_LEVEL},
|
||||
{"Offset", NULL, 0, 0, 0, 0, 0, menu_prog_hexedit_start, PROG_EDIT_LED_OFFSET},
|
||||
{"Options", NULL, 0, 0, 0, 0, 0, menu_prog_hexedit_start, PROG_EDIT_LED_OPTIONS},
|
||||
{"InitFn?", menu_prog_disp, PROG_EDIT_FORCE_INIT, 0, 0, 0, 0, prog_edit_tog_force_init, PROG_EDIT_FORCE_INIT}
|
||||
};
|
||||
const MenuItem menu_prog_leditem[] = {
|
||||
{(MenuItem *)255, 0, &menu_prog_leditem[1], 0, &menu_prog_leddata[0]},
|
||||
{(MenuItem *)255, &menu_prog_leditem[0], &menu_prog_leditem[2], 0, &menu_prog_leddata[1]},
|
||||
{(MenuItem *)255, &menu_prog_leditem[1], &menu_prog_leditem[3], 0, &menu_prog_leddata[2]},
|
||||
{(MenuItem *)255, &menu_prog_leditem[2], &menu_prog_leditem[4], 0, &menu_prog_leddata[3]},
|
||||
{(MenuItem *)255, &menu_prog_leditem[3], &menu_prog_leditem[5], 0, &menu_prog_leddata[4]},
|
||||
{(MenuItem *)255, &menu_prog_leditem[4], &menu_prog_leditem[6], 0, &menu_prog_leddata[5]},
|
||||
{(MenuItem *)255, &menu_prog_leditem[5], &menu_prog_leditem[7], 0, &menu_prog_leddata[6]},
|
||||
{(MenuItem *)255, &menu_prog_leditem[6], &menu_prog_leditem[8], 0, &menu_prog_leddata[7]},
|
||||
{(MenuItem *)255, &menu_prog_leditem[7], &menu_prog_leditem[9], 0, &menu_prog_leddata[8]},
|
||||
{(MenuItem *)255, &menu_prog_leditem[8], 0, 0, &menu_prog_leddata[9]}
|
||||
};
|
||||
|
||||
// advanced LED menu editor target menu
|
||||
const MenuData menu_prog_ledadata = {
|
||||
"", prog_advanced_str, 0, 4, LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0
|
||||
};
|
||||
const MenuItem menu_prog_ledaitem = {(MenuItem *)255, 0, 0, 0, &menu_prog_ledadata};
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* menu_program.h: led and lcd program selection and configuration
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: menu_program.h 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_MENU_PROGRAM_H
|
||||
#define __PIRATE_MENU_PROGRAM_H
|
||||
|
||||
|
||||
|
||||
/* program specifics */
|
||||
#define PROG_TYPE_SKULL 0x00
|
||||
#define PROG_TYPE_BONES 0x01
|
||||
#define PROG_TYPE_EYES 0x02
|
||||
#define PROG_TYPE_INFOPIR8 0x10
|
||||
|
||||
#define PROG_GLOBAL_MODE 0x0200
|
||||
#define PROG_GLOBAL_CHANGEIDX 0x0210
|
||||
|
||||
#define PROG_EDIT_ENABLE 0x0220
|
||||
#define PROG_EDIT_FORCE_INIT 0x0221
|
||||
#define PROG_EDIT_PROG_DWELL 0x0222
|
||||
#define PROG_EDIT_TYPE 0x0223
|
||||
#define PROG_EDIT_PROG_ID 0x0224
|
||||
#define PROG_EDIT_CYCLESPEED 0x0225
|
||||
#define PROG_EDIT_LED_LEVEL 0x0226
|
||||
#define PROG_EDIT_LED_OFFSET 0x0227
|
||||
#define PROG_EDIT_LED_OPTIONS 0x0228
|
||||
|
||||
|
||||
/* program menus */
|
||||
extern const MenuItem menu_prog_ritem[];
|
||||
extern const MenuItem menu_prog_leditem[];
|
||||
|
||||
|
||||
/* variables */
|
||||
extern uint8_t prog_id[3];
|
||||
extern uint16_t prog_dwell[3];
|
||||
|
||||
|
||||
/* prototypes */
|
||||
void prog_init();
|
||||
uint8_t prog_get_mode(uint8_t id);
|
||||
|
||||
uint8_t menu_prog_get_type();
|
||||
uint8_t menu_prog_get_idx();
|
||||
|
||||
void menu_btntype_program();
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,196 @@
|
|||
/**
|
||||
* menu_radio.c: cool radio tricks
|
||||
* 2015 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
**/
|
||||
|
||||
#include <pirate.h>
|
||||
|
||||
#include "../device/radio/nrf.h"
|
||||
|
||||
#include "lcd_menu.h"
|
||||
#include "menu_radio.h"
|
||||
|
||||
// radio comms
|
||||
char comm_str[12];
|
||||
|
||||
// pingpong
|
||||
uint8_t comm_ping_idx;
|
||||
uint8_t comm_pingpong_timeout;
|
||||
uint8_t comm_pong_last_idx;
|
||||
uint8_t comm_pong_timeout;
|
||||
|
||||
// radio menu forward declaration
|
||||
MenuItem menu_comm_pingitem;
|
||||
const MenuItem menu_comm_dc23item[5];
|
||||
|
||||
|
||||
/* special functions */
|
||||
void menu_comm_dc23cmd(uint16_t id)
|
||||
{
|
||||
if (id < 255) {
|
||||
// music
|
||||
nrf_tx_buf[0] = NRF_CMD_MUSICLIBRARY;
|
||||
nrf_tx_buf[1] = (id > 127) ? 22 : 23;
|
||||
if (id > 127) id -= 128;
|
||||
nrf_tx_buf[2] = id & 0xff;
|
||||
nrf_tx_buf[3] = 0;
|
||||
nrf_tx_buf[4] = 0;
|
||||
nrf_tx_buf[5] = 60000 >> 8;
|
||||
nrf_tx_buf[6] = 60000 & 0xff;
|
||||
nrf_tx_buf[7] = nrf_checksum(nrf_tx_buf, 7, 0) & 0xff;
|
||||
nRF24_packet_tx(nrf_tx_buf, NRF_PAYLOAD_LEN, 1);
|
||||
} else {
|
||||
switch (id) {
|
||||
case 301: {
|
||||
// cawks go a-flyin'
|
||||
nrf_tx_buf[0] = NRF_CMD_ANIMATION;
|
||||
nrf_tx_buf[1] = 22;
|
||||
nrf_tx_buf[2] = 0x00;
|
||||
nrf_tx_buf[3] = 'B';
|
||||
nrf_tx_buf[4] = 'K';
|
||||
nrf_tx_buf[5] = '<';
|
||||
nrf_tx_buf[6] = '3';
|
||||
nrf_tx_buf[7] = nrf_checksum(nrf_tx_buf, 7, 0) & 0xff;
|
||||
nRF24_packet_tx(nrf_tx_buf, NRF_PAYLOAD_LEN, 1);
|
||||
break;
|
||||
}
|
||||
case 401: {
|
||||
// name auto-tx mode, timeout in minutes
|
||||
dc23_nametx++;
|
||||
dc23_nametx %= 16;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* external program functions */
|
||||
char * menu_comm_disp(uint16_t id)
|
||||
{
|
||||
switch (id) {
|
||||
case COMM_TEST_PING: {
|
||||
if (!comm_pingpong_timeout) {
|
||||
// set our timeout to start this process again
|
||||
comm_pingpong_timeout = 100;
|
||||
|
||||
// increment our ping output index
|
||||
comm_ping_idx++;
|
||||
if (comm_ping_idx == 0) comm_ping_idx++;
|
||||
|
||||
// and build and send a ping command packet
|
||||
// 1 byte command, 1 byte class/sub, 1 byte byte index, 4 bytes data, 1 byte checksum
|
||||
nrf_tx_buf[0] = NRF_CMD_PING;
|
||||
nrf_tx_buf[1] = 22;
|
||||
nrf_tx_buf[2] = comm_ping_idx;
|
||||
nrf_tx_buf[3] = nrf_tx_buf[4] = nrf_tx_buf[5] = nrf_tx_buf[6] = 0;
|
||||
nrf_tx_buf[7] = nrf_checksum(nrf_tx_buf, 7, 0) & 0xff;
|
||||
nRF24_packet_tx(nrf_tx_buf, NRF_PAYLOAD_LEN, 1);
|
||||
} else {
|
||||
comm_pingpong_timeout--;
|
||||
}
|
||||
|
||||
// show our address and index on the screen
|
||||
strcpy(comm_str, pirate_itoa(nrf_myaddr, 16, 2));
|
||||
strcat(comm_str, pirate_itoa(comm_ping_idx, 16, 2));
|
||||
|
||||
// fix up then return
|
||||
if (comm_str[0] == 0x00 || comm_str[0] == 0x20) comm_str[0] = 0x30;
|
||||
if (comm_str[2] == 0x00 || comm_str[2] == 0x20) comm_str[2] = 0x30;
|
||||
comm_str[4] = 0;
|
||||
return comm_str;
|
||||
}
|
||||
case COMM_TEST_PONG: {
|
||||
if (!comm_pingpong_timeout) {
|
||||
// set our timeout to start this process again
|
||||
comm_pingpong_timeout = 25;
|
||||
|
||||
// clear ping receipt variables
|
||||
if (nrf_last_ping_idx) {
|
||||
// mismatch or unset?
|
||||
if ((nrf_last_ping_idx != comm_pong_last_idx) || (comm_pong_last_idx == 0)) {
|
||||
// ok, then start over
|
||||
comm_pong_timeout = 6;
|
||||
comm_pong_last_idx = nrf_last_ping_idx;
|
||||
} else if (!comm_pong_timeout) {
|
||||
nrf_last_ping_idx = comm_pong_last_idx = 0;
|
||||
} else {
|
||||
comm_pong_timeout--;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
comm_pingpong_timeout--;
|
||||
}
|
||||
|
||||
if (!nrf_last_ping_idx) {
|
||||
return "----";
|
||||
} else {
|
||||
// show received address and index on the screen
|
||||
strcpy(comm_str, pirate_itoa(nrf_last_ping_id, 16, 2));
|
||||
strcat(comm_str, pirate_itoa(nrf_last_ping_idx, 16, 2));
|
||||
|
||||
// fix up then return
|
||||
if (comm_str[0] == 0x00 || comm_str[0] == 0x20) comm_str[0] = 0x30;
|
||||
if (comm_str[2] == 0x00 || comm_str[2] == 0x20) comm_str[2] = 0x30;
|
||||
comm_str[4] = 0;
|
||||
return comm_str;
|
||||
}
|
||||
}
|
||||
|
||||
case COMM_RADIOSTATUS: { // radio detected?
|
||||
if (nrf_detected) return "Radio OK";
|
||||
else return "No Radio";
|
||||
}
|
||||
|
||||
case COMM_DC23NAMETX: {
|
||||
strncpy(comm_str, pirate_itoa(dc23_nametx, 10, 2), 2);
|
||||
comm_str[8] = 0;
|
||||
return comm_str;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
/* menu construction */
|
||||
// main menu
|
||||
const MenuData menu_comm_rdata[] = {
|
||||
{"DC22Page", NULL, 0, 0, LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0},
|
||||
{"DC23Page", NULL, 0, 0, LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0},
|
||||
{"DC23Cmds", NULL, 0, 0, LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0},
|
||||
{"Ping", menu_comm_disp, COMM_TEST_PING, 0, LCD_DEF_SPACING, 100, 100, NULL, 0},
|
||||
{"Pong", menu_comm_disp, COMM_TEST_PONG, 0, LCD_DEF_SPACING, 100, 100, NULL, 0},
|
||||
{"", menu_comm_disp, COMM_RADIOSTATUS, 0, LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0} // radio-detect
|
||||
};
|
||||
const MenuItem menu_comm_ritem[] = {
|
||||
{&menu_ritem[LCD_MENU_ROOT_COMMS], 0, &menu_comm_ritem[1], NULL, &menu_comm_rdata[0]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_COMMS], &menu_comm_ritem[0], &menu_comm_ritem[2], NULL, &menu_comm_rdata[1]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_COMMS], &menu_comm_ritem[1], &menu_comm_ritem[3], &menu_comm_dc23item[0], &menu_comm_rdata[2]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_COMMS], &menu_comm_ritem[2], &menu_comm_ritem[4], NULL, &menu_comm_rdata[3]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_COMMS], &menu_comm_ritem[3], &menu_comm_ritem[5], NULL, &menu_comm_rdata[4]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_COMMS], &menu_comm_ritem[4], 0, NULL, &menu_comm_rdata[5]}
|
||||
};
|
||||
|
||||
// pinger
|
||||
const MenuData menu_comm_pingdata = {"", NULL, 0, 0, LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0};
|
||||
|
||||
// dc23 stuff
|
||||
const MenuData menu_comm_dc23data[5] = {
|
||||
{"S:URAPr8", NULL, 0, 0, LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, menu_comm_dc23cmd, 0},
|
||||
{"M:URAPrL", NULL, 0, 0, LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, menu_comm_dc23cmd, 129},
|
||||
{"S:PwrRgr", NULL, 0, 0, LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, menu_comm_dc23cmd, 2},
|
||||
{"CawkSpam", NULL, 0, 0, LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, menu_comm_dc23cmd, 301},
|
||||
{"NameTx", menu_comm_disp, COMM_DC23NAMETX, 0, LCD_DEF_SPACING, 10, 10, menu_comm_dc23cmd, 401},
|
||||
};
|
||||
const MenuItem menu_comm_dc23item[5] = {
|
||||
{&menu_comm_ritem[2], 0, &menu_comm_dc23item[1], 0, &menu_comm_dc23data[0]},
|
||||
{&menu_comm_ritem[2], &menu_comm_dc23item[0], &menu_comm_dc23item[2], 0, &menu_comm_dc23data[1]},
|
||||
{&menu_comm_ritem[2], &menu_comm_dc23item[1], &menu_comm_dc23item[3], 0, &menu_comm_dc23data[2]},
|
||||
{&menu_comm_ritem[2], &menu_comm_dc23item[2], &menu_comm_dc23item[4], 0, &menu_comm_dc23data[3]},
|
||||
{&menu_comm_ritem[2], &menu_comm_dc23item[3], 0, 0, &menu_comm_dc23data[4]},
|
||||
};
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* menu_radio.h: cool radio tricks
|
||||
* 2015 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_MENU_RADIO_H
|
||||
#define __PIRATE_MENU_RADIO_H
|
||||
|
||||
|
||||
|
||||
/* menus */
|
||||
extern const MenuItem menu_comm_ritem[];
|
||||
|
||||
/* menu types */
|
||||
#define COMM_TEST_PING 0x01e0
|
||||
#define COMM_TEST_PONG 0x01e1
|
||||
|
||||
#define COMM_RADIOSTATUS 0x01ff
|
||||
|
||||
#define COMM_DC23NAMETX 0x0201
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,212 @@
|
|||
/**
|
||||
* menu_sensors.c: sensors menu
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: menu_sensors.c 350 2015-05-28 02:23:03Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#include <pirate.h>
|
||||
|
||||
#include "../interface/adc.h"
|
||||
|
||||
#include "lcd_menu.h"
|
||||
#include "menu_sensors.h"
|
||||
|
||||
|
||||
/* menu functions */
|
||||
// feedback display
|
||||
char * menu_sens_disp(uint16_t id)
|
||||
{
|
||||
switch (id) {
|
||||
case SENSOR_LIGHT_CURRENTGAIN: {
|
||||
return pirate_sitoa(light_gain, 10, 3);
|
||||
}
|
||||
case SENSOR_LIGHT_SETTINGSGAIN: {
|
||||
return pirate_sitoa(settings.light_setgain, 10, 3);
|
||||
}
|
||||
case SENSOR_LIGHT_LEVEL: {
|
||||
return pirate_sitoa(light_level, 10, 3);
|
||||
}
|
||||
|
||||
case SENSOR_MIC_CAL_LOW:
|
||||
case SENSOR_MIC_CAL_HIGH: {
|
||||
if (menu_editing == SENSOR_MIC_CAL_LOW) {
|
||||
if (settings.mic_cal[0] > mic_peak) {
|
||||
settings.mic_cal[0] = mic_peak - (mic_peak >> 6);
|
||||
}
|
||||
} else if (menu_editing == SENSOR_MIC_CAL_HIGH) {
|
||||
if (settings.mic_cal[1] < mic_peak) {
|
||||
settings.mic_cal[1] = mic_peak + (mic_peak >> 6);
|
||||
}
|
||||
}
|
||||
|
||||
return pirate_sitoa(settings.mic_cal[id - SENSOR_MIC_CAL_LOW], 10, 4);
|
||||
}
|
||||
|
||||
case SENSOR_TEMP_CALVALUE: {
|
||||
return pirate_sitoa(temperature_cal, 10, 3);
|
||||
}
|
||||
|
||||
default: {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char * menu_sensor_batt_disp(uint16_t id)
|
||||
{
|
||||
int i;
|
||||
static char volt[6];
|
||||
uint16_t raw;
|
||||
|
||||
// get voltage, clear target array
|
||||
raw = pirate_batt_voltage();
|
||||
for (i = 0; i < 6; i++) {
|
||||
volt[i] = 0;
|
||||
}
|
||||
|
||||
// voltage whole number
|
||||
strcpy(volt, pirate_sitoa(raw / 100, 10, 0));
|
||||
|
||||
// voltage decimal start
|
||||
if (raw % 100 <= 9) {
|
||||
strncat(volt, ".0", 6);
|
||||
} else {
|
||||
strncat(volt, ".", 6);
|
||||
}
|
||||
|
||||
// voltage decimal
|
||||
strncat(volt, pirate_sitoa(raw % 100, 10, 0), 5);
|
||||
|
||||
// voltage postfix
|
||||
volt[4] = 'V';
|
||||
volt[5] = 0;
|
||||
|
||||
return volt;
|
||||
}
|
||||
char * menu_sensor_temp_disp(uint16_t id)
|
||||
{
|
||||
static char temp[7];
|
||||
uint16_t raw;
|
||||
|
||||
raw = pirate_thermometer(id);
|
||||
|
||||
if (!id) {
|
||||
strcpy(temp, pirate_sitoa(raw / 10, 10, 0));
|
||||
strncat(temp, ".", 7);
|
||||
strncat(temp, pirate_sitoa(raw % 10, 10, 0), 6);
|
||||
strncat(temp, "C", 7);
|
||||
temp[6] = 0;
|
||||
} else {
|
||||
strcpy(temp, pirate_sitoa(raw, 10, 0));
|
||||
strncat(temp, "F", 5);
|
||||
temp[4] = 0;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
char * menu_sensor_mic_disp(uint16_t id)
|
||||
{
|
||||
uint16_t w;
|
||||
|
||||
if (!id) {
|
||||
return pirate_sitoa(mic_peak, 10, 4);
|
||||
} else {
|
||||
w = (settings.mic_cal[1] - settings.mic_cal[0]);
|
||||
return pirate_sitoa(((mic_peak - settings.mic_cal[0]) * 100) / w, 10, 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// menu actions
|
||||
void menu_sensor_mic_cal_start(uint16_t id)
|
||||
{
|
||||
if (menu_editing) {
|
||||
menu_editing = 0;
|
||||
} else {
|
||||
menu_editing = id;
|
||||
settings.mic_cal[id - SENSOR_MIC_CAL_LOW] = mic_peak;
|
||||
}
|
||||
|
||||
menu_btntype_editing();
|
||||
}
|
||||
|
||||
|
||||
/* menu construction */
|
||||
// forward declaration
|
||||
const MenuItem menu_sens_viewitem[];
|
||||
|
||||
const MenuItem menu_sens_setitem[];
|
||||
const MenuItem menu_sens_set_lightitem[];
|
||||
const MenuItem menu_sens_set_micitem[];
|
||||
|
||||
|
||||
// main menu
|
||||
const MenuData menu_sens_rdata[] = {
|
||||
{"View", NULL, 0, 0, LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0},
|
||||
{"Setup", NULL, 0, 0, LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0}
|
||||
};
|
||||
const MenuItem menu_sens_ritem[] = {
|
||||
{&menu_ritem[LCD_MENU_ROOT_SENSORS], 0, &menu_sens_ritem[1], &menu_sens_viewitem[0], &menu_sens_rdata[0]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_SENSORS], &menu_sens_ritem[0], 0, &menu_sens_setitem[0], &menu_sens_rdata[1]}
|
||||
};
|
||||
|
||||
|
||||
// "view" menu
|
||||
const MenuData menu_sens_viewdata[] = {
|
||||
{"Bat", menu_sensor_batt_disp, 0, 20, 4, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0},
|
||||
{"Tmp", menu_sensor_temp_disp, 0, 20, 4, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0},
|
||||
{"Tmp ", menu_sensor_temp_disp, 1, 20, 4, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0},
|
||||
{"MicR", menu_sensor_mic_disp, 0, 12, 4, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0},
|
||||
{"Mic%", menu_sensor_mic_disp, 1, 12, 4, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0},
|
||||
{"LitGn", menu_sens_disp, SENSOR_LIGHT_CURRENTGAIN, 12, 4, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0},
|
||||
{"LitLv", menu_sens_disp, SENSOR_LIGHT_LEVEL, 12, 4, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0}
|
||||
};
|
||||
const MenuItem menu_sens_viewitem[] = {
|
||||
{&menu_sens_ritem[0], 0, &menu_sens_viewitem[1], 0, &menu_sens_viewdata[0]},
|
||||
{&menu_sens_ritem[0], &menu_sens_viewitem[0], &menu_sens_viewitem[2], 0, &menu_sens_viewdata[1]},
|
||||
{&menu_sens_ritem[0], &menu_sens_viewitem[1], &menu_sens_viewitem[3], 0, &menu_sens_viewdata[2]},
|
||||
{&menu_sens_ritem[0], &menu_sens_viewitem[2], &menu_sens_viewitem[4], 0, &menu_sens_viewdata[3]},
|
||||
{&menu_sens_ritem[0], &menu_sens_viewitem[3], &menu_sens_viewitem[5], 0, &menu_sens_viewdata[4]},
|
||||
{&menu_sens_ritem[0], &menu_sens_viewitem[4], &menu_sens_viewitem[6], 0, &menu_sens_viewdata[5]},
|
||||
{&menu_sens_ritem[0], &menu_sens_viewitem[5], 0, 0, &menu_sens_viewdata[6]}
|
||||
};
|
||||
|
||||
// "setup" menu and submenus
|
||||
const MenuData menu_sens_setdata[] = {
|
||||
{"LightSensor", NULL, 0, 0,
|
||||
LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0},
|
||||
{"Mic", NULL, 0, 0, LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0},
|
||||
{"T-Cal", menu_sens_disp, SENSOR_TEMP_CALVALUE, 0,
|
||||
LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, menu_edit_start, SENSOR_TEMP_CALVALUE}
|
||||
};
|
||||
const MenuItem menu_sens_setitem[] = {
|
||||
{&menu_sens_ritem[1], 0, &menu_sens_setitem[1], &menu_sens_set_lightitem[0], &menu_sens_setdata[0]},
|
||||
{&menu_sens_ritem[1], &menu_sens_setitem[0], &menu_sens_setitem[2], &menu_sens_set_micitem[0], &menu_sens_setdata[1]},
|
||||
{&menu_sens_ritem[1], &menu_sens_setitem[1], 0, 0, &menu_sens_setdata[2]}
|
||||
};
|
||||
|
||||
// setup/lightsensor
|
||||
const MenuData menu_sens_set_lightdata[] = {
|
||||
{"Gain ", menu_sens_disp, SENSOR_LIGHT_CURRENTGAIN, 4, 0, 0, 0, NULL, 0},
|
||||
{"Fixed", menu_sens_disp, SENSOR_LIGHT_SETTINGSGAIN, 4, 0, 0, 0, menu_edit_start, SENSOR_LIGHT_SETTINGSGAIN}
|
||||
};
|
||||
const MenuItem menu_sens_set_lightitem[] = {
|
||||
{&menu_sens_setitem[0], 0, &menu_sens_set_lightitem[1], 0, &menu_sens_set_lightdata[0]},
|
||||
{&menu_sens_setitem[0], &menu_sens_set_lightitem[0], &menu_sens_set_lightitem[2], 0, &menu_sens_set_lightdata[1]},
|
||||
{&menu_sens_setitem[0], &menu_sens_set_lightitem[1], 0, 0, &menu_sens_set_lightdata[2]}
|
||||
};
|
||||
|
||||
// setup/mic
|
||||
const MenuData menu_sens_set_micdata[] = {
|
||||
{"CLow", menu_sens_disp, SENSOR_MIC_CAL_LOW, 1, 0, 0, 0, menu_sensor_mic_cal_start, SENSOR_MIC_CAL_LOW},
|
||||
{"CHi ", menu_sens_disp, SENSOR_MIC_CAL_HIGH, 1, 0, 0, 0, menu_sensor_mic_cal_start, SENSOR_MIC_CAL_HIGH}
|
||||
};
|
||||
const MenuItem menu_sens_set_micitem[] = {
|
||||
{&menu_sens_setitem[1], 0, &menu_sens_set_micitem[1], 0, &menu_sens_set_micdata[0]},
|
||||
{&menu_sens_setitem[1], &menu_sens_set_micitem[0], 0, 0, &menu_sens_set_micdata[1]}
|
||||
};
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* menu_sensors.h: sensors menu
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: menu_sensors.h 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_MENU_SENSORS_H
|
||||
#define __PIRATE_MENU_SENSORS_H
|
||||
|
||||
|
||||
|
||||
/* menus */
|
||||
extern const MenuItem menu_sens_ritem[];
|
||||
|
||||
|
||||
/* sensors defines */
|
||||
#define SENSOR_LIGHT_CURRENTGAIN 0x0400
|
||||
#define SENSOR_LIGHT_SETTINGSGAIN 0x0401
|
||||
|
||||
#define SENSOR_LIGHT_LEVEL 0x0404
|
||||
|
||||
#define SENSOR_MIC_CAL_LOW 0x0410
|
||||
#define SENSOR_MIC_CAL_HIGH 0x0411
|
||||
|
||||
#define SENSOR_TEMP_CALVALUE 0x0420
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,459 @@
|
|||
/**
|
||||
* menu_settings.c: setting shit up for pirates since
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: menu_settings.c 375 2015-07-06 02:52:40Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#include <pirate.h>
|
||||
|
||||
#include "../device/lcd.h"
|
||||
|
||||
#include "../device/lightsensor.h" // for lightsensor default defines
|
||||
#include "../device/attiny.h" // eyes program set for favcolor editor
|
||||
#include "../device/beep.h"
|
||||
|
||||
#include "lcd_menu.h"
|
||||
#include "menu_settings.h"
|
||||
|
||||
// menus
|
||||
uint32_t menu_oldval;
|
||||
uint32_t menu_newval;
|
||||
|
||||
// settings
|
||||
PirateSettings *settings_eeprom = (PirateSettings *)PIRATE_SETTINGS_EEPROM_ADDR;
|
||||
|
||||
|
||||
/* settings functions */
|
||||
void menu_settings_save(uint16_t id)
|
||||
{
|
||||
settings_save();
|
||||
}
|
||||
|
||||
void settings_save()
|
||||
{
|
||||
uint32_t *active = (uint32_t *)&settings;
|
||||
|
||||
int i;
|
||||
|
||||
DATA_EEPROM_Unlock();
|
||||
|
||||
// make sure the first name byte is set to something not considered invalid
|
||||
// if it isn't set we set it to be a space
|
||||
if (settings.name[0] == 0x00 || settings.name[0] == 0xff) {
|
||||
settings.name[0] = 0x20;
|
||||
}
|
||||
|
||||
// write data
|
||||
for (i = 0; i < sizeof(settings); i += 4) {
|
||||
DATA_EEPROM_ProgramWord(PIRATE_SETTINGS_EEPROM_ADDR + i, *active++);
|
||||
}
|
||||
|
||||
DATA_EEPROM_Lock();
|
||||
}
|
||||
|
||||
void settings_restore(uint8_t load_defaults)
|
||||
{
|
||||
uint32_t *active = (uint32_t *)&settings;
|
||||
uint32_t *stored = (uint32_t *)PIRATE_SETTINGS_EEPROM_ADDR;
|
||||
|
||||
int i;
|
||||
int j;
|
||||
uint8_t valid = 0;
|
||||
|
||||
// see if valid settings are in EEPROM
|
||||
if (!(settings_eeprom->name[0] == 0x00 || settings_eeprom->name[0] == 0xff)) {
|
||||
// seems valid, copy it
|
||||
for (i = 0; i < sizeof(settings); i += 4) {
|
||||
*active++ = *stored++;
|
||||
}
|
||||
valid = 1;
|
||||
}
|
||||
|
||||
if (!valid || load_defaults) {
|
||||
// not valid, set defaults
|
||||
if (load_defaults & 0x02) {
|
||||
// only reset name if invalid settings, or if second bit is set
|
||||
strncpy(settings.name, " ", 8);
|
||||
}
|
||||
|
||||
settings.fav_color[0] = 0x80;
|
||||
settings.fav_color[1] = 0x10;
|
||||
settings.fav_color[2] = 0;
|
||||
|
||||
settings.beeper = 0x80 + 31;
|
||||
settings.beep_type[0] = 24;
|
||||
settings.beep_type[1] = 30;
|
||||
settings.beep_type[2] = 28;
|
||||
|
||||
settings.contrast = 0x15; // gives great readability with scrolling on my badge
|
||||
|
||||
settings.autorun = 0;
|
||||
|
||||
settings.led_autoadjust = 0x88;
|
||||
settings.led_autogain_lev_min = LIGHTSENS_AUTOGAIN_LEVEL_MIN;
|
||||
settings.led_autogain_lev_max = LIGHTSENS_AUTOGAIN_LEVEL_MAX;
|
||||
settings.led_autothresh[0] = LIGHTSENS_THRESH_DAY;
|
||||
settings.led_autothresh[1] = LIGHTSENS_THRESH_TOP_BRIGHT;
|
||||
settings.led_autothresh[2] = LIGHTSENS_THRESH_TOP_NORM;
|
||||
settings.led_autothresh[3] = LIGHTSENS_THRESH_TOP_DIM;
|
||||
settings.led_autothresh[4] = LIGHTSENS_THRESH_TOP_DARK;
|
||||
|
||||
settings.lcd_autobrite = 1;
|
||||
settings.lcd_brightness = 50;
|
||||
|
||||
settings.light_setgain = 0;
|
||||
|
||||
for (i = 0; i < PIRATE_PROG_SAVED_MAX; i++) {
|
||||
for (j = 0; j < 3; j++) {
|
||||
settings.led_prog[j][i].type = 0b00000010; // not enabled, will init, program mode
|
||||
settings.led_prog[j][i].progidx = 0;
|
||||
settings.led_prog[j][i].wait = 80;
|
||||
settings.led_prog[j][i].level = 0;
|
||||
settings.led_prog[j][i].offset = 0;
|
||||
settings.led_prog[j][i].option = 0;
|
||||
settings.led_prog[j][i].dwell = 10;
|
||||
}
|
||||
}
|
||||
|
||||
settings.led_prog_mode = 0b00010101; // all program types set to normal run
|
||||
|
||||
settings.mic_cal[0] = 2300;
|
||||
settings.mic_cal[1] = 2800;
|
||||
|
||||
/* default programs */
|
||||
#include "menu_settings_defprog.h"
|
||||
|
||||
// fix the null name issue
|
||||
if (settings.name[0] == 0x00) {
|
||||
strncpy(settings.name, " ", 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* menu functions */
|
||||
// feedback display
|
||||
static char * menu_pref_disp(uint16_t id)
|
||||
{
|
||||
switch (id) {
|
||||
case SETTING_NAME: {
|
||||
return settings.name;
|
||||
}
|
||||
case SETTING_AUTORUN_ENA: {
|
||||
return settings.autorun & 0x01 ? "Y" : "N";
|
||||
}
|
||||
case SETTING_ALWAYS_RUN_PROG_ENA: {
|
||||
return settings.autorun & 0x02 ? "Y" : "N";
|
||||
}
|
||||
|
||||
case SETTING_FAVCOLOR_RED:
|
||||
case SETTING_FAVCOLOR_GREEN:
|
||||
case SETTING_FAVCOLOR_BLUE: {
|
||||
return pirate_sitoa(settings.fav_color[id - SETTING_FAVCOLOR_RED], 16, 2);
|
||||
}
|
||||
|
||||
case SETTING_BEEPER_ENA: {
|
||||
return (settings.beeper & 0x80) ? " On" : "Off";
|
||||
}
|
||||
case SETTING_BEEP_TYPE_BUTTON:
|
||||
case SETTING_BEEP_TYPE_PAGING:
|
||||
case SETTING_BEEP_TYPE_ALARM: {
|
||||
return pirate_sitoa(settings.beep_type[id - SETTING_BEEP_TYPE_BUTTON], 10, 2);
|
||||
}
|
||||
|
||||
case SETTING_BRITE_AUTO_ENA: {
|
||||
return (settings.led_autoadjust & 0x80) ? " On" : " Off";
|
||||
}
|
||||
|
||||
case SETTING_BRITE_AUTO_SPEED: {
|
||||
switch (settings.led_autoadjust & 0x7f) {
|
||||
case 0: return " Off";
|
||||
case 2: return "Hypr";
|
||||
case 4: return "High";
|
||||
case 6: return " Med";
|
||||
case 8: return "Norm";
|
||||
case 10: return "Slow";
|
||||
default: return pirate_sitoa(settings.led_autoadjust, 10, 4);
|
||||
}
|
||||
}
|
||||
case SETTING_BRITE_LCD_AUTO: {
|
||||
return (settings.lcd_autobrite) ? "Auto" : "Manu";
|
||||
}
|
||||
case SETTING_BRITE_LCD_VALUE: {
|
||||
return pirate_sitoa(settings.lcd_brightness, 10, 3);
|
||||
}
|
||||
case SETTING_BRITE_AUTOGAIN_LO: {
|
||||
return pirate_sitoa(settings.led_autogain_lev_min, 10, 2);
|
||||
}
|
||||
case SETTING_BRITE_AUTOGAIN_HI: {
|
||||
return pirate_sitoa(settings.led_autogain_lev_max, 10, 2);
|
||||
}
|
||||
case SETTING_BRITE_THRESH0:
|
||||
case SETTING_BRITE_THRESH1:
|
||||
case SETTING_BRITE_THRESH2:
|
||||
case SETTING_BRITE_THRESH3:
|
||||
case SETTING_BRITE_THRESH4: {
|
||||
return pirate_sitoa(settings.led_autothresh[id - SETTING_BRITE_THRESH0], 10, 2);
|
||||
}
|
||||
|
||||
default: {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char * menu_pref_run_prog_disp(uint16_t id)
|
||||
{
|
||||
if (settings.autorun & 0x02) {
|
||||
return "RunProg:Always!";
|
||||
} else {
|
||||
return "RunProg:Runmode";
|
||||
}
|
||||
}
|
||||
|
||||
// name changing handler
|
||||
void menu_pref_name_next()
|
||||
{
|
||||
if (menu_newval) {
|
||||
if (settings.name[menu_oldval] < 0x20) {
|
||||
settings.name[menu_oldval] = 0x20;
|
||||
} else if (settings.name[menu_oldval] < 0x5e) {
|
||||
settings.name[menu_oldval]++;
|
||||
} else if (settings.name[menu_oldval] == 0x5e) {
|
||||
settings.name[menu_oldval] = 0x61;
|
||||
} else if (settings.name[menu_oldval] < 0x7d) {
|
||||
settings.name[menu_oldval]++;
|
||||
}
|
||||
} else {
|
||||
if (menu_oldval < 7) {
|
||||
menu_oldval++;
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.beeper) {
|
||||
beep(settings.beep_type[0], 10);
|
||||
}
|
||||
|
||||
lcd_set_cursor(LCD_LINE_2 + menu_oldval, 0);
|
||||
}
|
||||
|
||||
void menu_pref_name_prev()
|
||||
{
|
||||
if (menu_newval) {
|
||||
if (settings.name[menu_oldval] > 0x7a) {
|
||||
settings.name[menu_oldval] = 0x7a;
|
||||
} else if (settings.name[menu_oldval] > 0x61) {
|
||||
settings.name[menu_oldval]--;
|
||||
} else if (settings.name[menu_oldval] == 0x61) {
|
||||
settings.name[menu_oldval] = 0x5e;
|
||||
} else if (settings.name[menu_oldval] > 0x20) {
|
||||
settings.name[menu_oldval]--;
|
||||
}
|
||||
} else {
|
||||
if (menu_oldval) {
|
||||
menu_oldval--;
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.beeper) {
|
||||
beep(settings.beep_type[0], 10);
|
||||
}
|
||||
|
||||
lcd_set_cursor(LCD_LINE_2 + menu_oldval, 0);
|
||||
}
|
||||
|
||||
void menu_pref_name_menu()
|
||||
{
|
||||
menuc = (MenuItem *)&menu_pref_ritem[0];
|
||||
menu_btntype_menus();
|
||||
|
||||
if (settings.beeper) {
|
||||
beep(settings.beep_type[0] - 1, 10);
|
||||
}
|
||||
}
|
||||
|
||||
void menu_pref_name_ok()
|
||||
{
|
||||
menu_newval ^= 1;
|
||||
|
||||
if (menu_newval) {
|
||||
lcd_set_cursor(LCD_LINE_2 + menu_oldval, LCD_CMD_CURSOR_FLASH);
|
||||
} else {
|
||||
lcd_set_cursor(LCD_LINE_2 + menu_oldval, LCD_CMD_CURSOR_UNDER);
|
||||
}
|
||||
|
||||
if (settings.beeper) {
|
||||
beep(settings.beep_type[0] + 1, 10);
|
||||
}
|
||||
}
|
||||
|
||||
static void menu_pref_name_start(uint16_t id)
|
||||
{
|
||||
// oldval is cursor pos, newval is editing-is-on
|
||||
menu_oldval = menu_newval = 0;
|
||||
lcd_set_cursor(LCD_LINE_2, LCD_CMD_CURSOR_UNDER);
|
||||
|
||||
lcd_btn_fn[BTN_UP] = menu_pref_name_prev;
|
||||
lcd_btn_fn[BTN_MENU] = menu_pref_name_menu;
|
||||
lcd_btn_fn[BTN_OK] = menu_pref_name_ok;
|
||||
lcd_btn_fn[BTN_DOWN] = menu_pref_name_next;
|
||||
}
|
||||
|
||||
static void menu_pref_favcolor_start(uint16_t id)
|
||||
{
|
||||
led_eyes_set_program(1, 1, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
// other settings
|
||||
static void menu_pref_autorun_set(uint16_t id)
|
||||
{
|
||||
if (settings.autorun & 0x01) {
|
||||
settings.autorun &= 0xfe;
|
||||
} else {
|
||||
settings.autorun |= 0x01;
|
||||
}
|
||||
}
|
||||
|
||||
static void menu_pref_alwaysrun_tog(uint16_t id)
|
||||
{
|
||||
if (settings.autorun & 0x02) {
|
||||
settings.autorun &= 0xfd;
|
||||
} else {
|
||||
settings.autorun |= 0x02;
|
||||
}
|
||||
}
|
||||
|
||||
static void menu_pref_beepena_set(uint16_t id)
|
||||
{
|
||||
if (settings.beeper & 0x80) {
|
||||
settings.beeper = 0;
|
||||
} else {
|
||||
settings.beeper |= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
static void menu_pref_brite_auto_ena_set(uint16_t id)
|
||||
{
|
||||
if (settings.led_autoadjust & 0x80) {
|
||||
settings.led_autoadjust &= 0x7f;
|
||||
} else {
|
||||
settings.led_autoadjust |= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
static void menu_pref_brite_auto_spd_set(uint16_t id)
|
||||
{
|
||||
if ((settings.led_autoadjust & 0x7f) >= 10) {
|
||||
settings.led_autoadjust &= 0x80;
|
||||
} else {
|
||||
settings.led_autoadjust += 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void menu_pref_brite_lcd_auto_set(uint16_t id)
|
||||
{
|
||||
if (settings.lcd_autobrite) {
|
||||
settings.lcd_autobrite = 0;
|
||||
} else {
|
||||
settings.lcd_autobrite = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* menu construction */
|
||||
// declaration
|
||||
const MenuItem menu_pref_nameitem[];
|
||||
const MenuItem menu_pref_favcitem[];
|
||||
const MenuItem menu_pref_beepitem[];
|
||||
const MenuItem menu_pref_briteitem[];
|
||||
|
||||
|
||||
// main menu
|
||||
const MenuData menu_pref_rdata[] = {
|
||||
{"Set Name", NULL, 0, 0, 0, 0, 0, menu_pref_name_start, 0},
|
||||
{"FavColor", NULL, 0, 0, 0, 0, 0, menu_pref_favcolor_start, 0},
|
||||
{"", menu_pref_run_prog_disp, 0, 4,
|
||||
LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, menu_pref_alwaysrun_tog, 0},
|
||||
{"Contrast", NULL, 0, 0, 0, 0, 0, menu_edit_start, SETTING_CONTRAST},
|
||||
{"Beeps", menu_pref_disp, SETTING_BEEPER_ENA, 4, 0, 0, 0, menu_pref_beepena_set, 0},
|
||||
{"BeepMenu", NULL, 0, 0, 0, 0, 0, NULL, 0},
|
||||
{"Brightness", NULL, 0, 0,
|
||||
LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0},
|
||||
{"AutoRun", menu_pref_disp, SETTING_AUTORUN_ENA, 4, 0, 0, 0, menu_pref_autorun_set, 0}
|
||||
};
|
||||
|
||||
const MenuItem menu_pref_ritem[] = {
|
||||
{&menu_ritem[LCD_MENU_ROOT_SETTINGS], 0, &menu_pref_ritem[1], &menu_pref_nameitem[0], &menu_pref_rdata[0]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_SETTINGS], &menu_pref_ritem[0], &menu_pref_ritem[2], &menu_pref_favcitem[0], &menu_pref_rdata[1]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_SETTINGS], &menu_pref_ritem[1], &menu_pref_ritem[3], 0, &menu_pref_rdata[2]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_SETTINGS], &menu_pref_ritem[2], &menu_pref_ritem[4], 0, &menu_pref_rdata[3]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_SETTINGS], &menu_pref_ritem[3], &menu_pref_ritem[5], 0, &menu_pref_rdata[4]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_SETTINGS], &menu_pref_ritem[4], &menu_pref_ritem[6], &menu_pref_beepitem[0], &menu_pref_rdata[5]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_SETTINGS], &menu_pref_ritem[5], &menu_pref_ritem[7], &menu_pref_briteitem[0], &menu_pref_rdata[6]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_SETTINGS], &menu_pref_ritem[6], 0, 0, &menu_pref_rdata[7]}
|
||||
};
|
||||
|
||||
// name editing
|
||||
const MenuData menu_pref_namedata[] = {
|
||||
{"", menu_pref_disp, SETTING_NAME, 4, 0, 0, 0, NULL, 0}
|
||||
};
|
||||
const MenuItem menu_pref_nameitem[] = {
|
||||
{&menu_pref_ritem[0], 0, 0, 0, &menu_pref_namedata[0]}
|
||||
};
|
||||
|
||||
// fav color menu
|
||||
const MenuData menu_pref_favcdata[] = {
|
||||
{"Red ", menu_pref_disp, SETTING_FAVCOLOR_RED, 4, 0, 0, 0, menu_edit_start, SETTING_FAVCOLOR_RED},
|
||||
{"Green ", menu_pref_disp, SETTING_FAVCOLOR_GREEN, 4, 0, 0, 0, menu_edit_start, SETTING_FAVCOLOR_GREEN},
|
||||
{"Blue ", menu_pref_disp, SETTING_FAVCOLOR_BLUE, 4, 0, 0, 0, menu_edit_start, SETTING_FAVCOLOR_BLUE}
|
||||
};
|
||||
const MenuItem menu_pref_favcitem[] = {
|
||||
{&menu_pref_ritem[1], 0, &menu_pref_favcitem[1], 0, &menu_pref_favcdata[0]},
|
||||
{&menu_pref_ritem[1], &menu_pref_favcitem[0], &menu_pref_favcitem[2], 0, &menu_pref_favcdata[1]},
|
||||
{&menu_pref_ritem[1], &menu_pref_favcitem[1], 0, 0, &menu_pref_favcdata[2]}
|
||||
};
|
||||
|
||||
// beeper config menu
|
||||
const MenuData menu_pref_beepdata[] = {
|
||||
{"Button", menu_pref_disp, SETTING_BEEP_TYPE_BUTTON, 4, 0, 0, 0, menu_edit_start, SETTING_BEEP_TYPE_BUTTON},
|
||||
{"Paging", menu_pref_disp, SETTING_BEEP_TYPE_PAGING, 4, 0, 0, 0, menu_edit_start, SETTING_BEEP_TYPE_PAGING},
|
||||
{"Alarm ", menu_pref_disp, SETTING_BEEP_TYPE_ALARM, 4, 0, 0, 0, menu_edit_start, SETTING_BEEP_TYPE_ALARM}
|
||||
};
|
||||
const MenuItem menu_pref_beepitem[] = {
|
||||
{&menu_pref_ritem[5], 0, &menu_pref_beepitem[1], 0, &menu_pref_beepdata[0]},
|
||||
{&menu_pref_ritem[5], &menu_pref_beepitem[0], &menu_pref_beepitem[2], 0, &menu_pref_beepdata[1]},
|
||||
{&menu_pref_ritem[5], &menu_pref_beepitem[1], 0, 0, &menu_pref_beepdata[2]}
|
||||
};
|
||||
|
||||
// brightness menu
|
||||
const MenuData menu_pref_britedata[] = {
|
||||
{"Auto", menu_pref_disp, SETTING_BRITE_AUTO_ENA, 4, 0, 0, 0, menu_pref_brite_auto_ena_set, 0},
|
||||
{"Spd ", menu_pref_disp, SETTING_BRITE_AUTO_SPEED, 4, 0, 0, 0, menu_pref_brite_auto_spd_set, 0},
|
||||
{"LCD ", menu_pref_disp, SETTING_BRITE_LCD_AUTO, 4, 0, 0, 0, menu_pref_brite_lcd_auto_set, 0},
|
||||
{"LCDlv", menu_pref_disp, SETTING_BRITE_LCD_VALUE, 4, 0, 0, 0, menu_edit_start, SETTING_BRITE_LCD_VALUE},
|
||||
{"AGNLo", menu_pref_disp, SETTING_BRITE_AUTOGAIN_LO, 4, 0, 0, 0, menu_edit_start, SETTING_BRITE_AUTOGAIN_LO},
|
||||
{"AGNHi", menu_pref_disp, SETTING_BRITE_AUTOGAIN_HI, 4, 0, 0, 0, menu_edit_start, SETTING_BRITE_AUTOGAIN_HI},
|
||||
{"GnDay ", menu_pref_disp, SETTING_BRITE_THRESH0, 4, 0, 0, 0, menu_edit_start, SETTING_BRITE_THRESH0},
|
||||
{"GnBrt ", menu_pref_disp, SETTING_BRITE_THRESH1, 4, 0, 0, 0, menu_edit_start, SETTING_BRITE_THRESH1},
|
||||
{"GnNrm ", menu_pref_disp, SETTING_BRITE_THRESH2, 4, 0, 0, 0, menu_edit_start, SETTING_BRITE_THRESH2},
|
||||
{"GnDim ", menu_pref_disp, SETTING_BRITE_THRESH3, 4, 0, 0, 0, menu_edit_start, SETTING_BRITE_THRESH3},
|
||||
{"GnDrk ", menu_pref_disp, SETTING_BRITE_THRESH4, 4, 0, 0, 0, menu_edit_start, SETTING_BRITE_THRESH4}
|
||||
};
|
||||
const MenuItem menu_pref_briteitem[] = {
|
||||
{&menu_pref_ritem[6], 0, &menu_pref_briteitem[1], 0, &menu_pref_britedata[0]},
|
||||
{&menu_pref_ritem[6], &menu_pref_briteitem[0], &menu_pref_briteitem[2], 0, &menu_pref_britedata[1]},
|
||||
{&menu_pref_ritem[6], &menu_pref_briteitem[1], &menu_pref_briteitem[3], 0, &menu_pref_britedata[2]},
|
||||
{&menu_pref_ritem[6], &menu_pref_briteitem[2], &menu_pref_briteitem[4], 0, &menu_pref_britedata[3]},
|
||||
{&menu_pref_ritem[6], &menu_pref_briteitem[3], &menu_pref_briteitem[5], 0, &menu_pref_britedata[4]},
|
||||
{&menu_pref_ritem[6], &menu_pref_briteitem[4], &menu_pref_briteitem[6], 0, &menu_pref_britedata[5]},
|
||||
{&menu_pref_ritem[6], &menu_pref_briteitem[5], &menu_pref_briteitem[7], 0, &menu_pref_britedata[6]},
|
||||
{&menu_pref_ritem[6], &menu_pref_briteitem[6], &menu_pref_briteitem[8], 0, &menu_pref_britedata[7]},
|
||||
{&menu_pref_ritem[6], &menu_pref_briteitem[7], &menu_pref_briteitem[9], 0, &menu_pref_britedata[8]},
|
||||
{&menu_pref_ritem[6], &menu_pref_briteitem[8], &menu_pref_briteitem[10], 0, &menu_pref_britedata[9]},
|
||||
{&menu_pref_ritem[6], &menu_pref_briteitem[9], 0, 0, &menu_pref_britedata[10]}
|
||||
};
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* menu_settings.h: setting shit up for pirates since
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: menu_settings.h 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_MENU_SETTINGS_H
|
||||
#define __PIRATE_MENU_SETTINGS_H
|
||||
|
||||
|
||||
|
||||
extern const MenuItem menu_pref_ritem[];
|
||||
|
||||
|
||||
/* settings defines */
|
||||
#define SETTING_NAME 0x0101
|
||||
|
||||
#define SETTING_AUTORUN_ENA 0x0105
|
||||
#define SETTING_ALWAYS_RUN_PROG_ENA 0x0106
|
||||
|
||||
#define SETTING_CONTRAST 0x0107
|
||||
|
||||
#define SETTING_FAVCOLOR_RED 0x0109
|
||||
#define SETTING_FAVCOLOR_GREEN 0x010a
|
||||
#define SETTING_FAVCOLOR_BLUE 0x010b
|
||||
|
||||
#define SETTING_BEEPER_ENA 0x0110
|
||||
#define SETTING_BEEP_TYPE_BUTTON 0x0111
|
||||
#define SETTING_BEEP_TYPE_PAGING 0x0112
|
||||
#define SETTING_BEEP_TYPE_ALARM 0x0113
|
||||
|
||||
#define SETTING_BRITE_AUTO_ENA 0x0120
|
||||
#define SETTING_BRITE_AUTO_SPEED 0x0121
|
||||
#define SETTING_BRITE_LCD_AUTO 0x0122
|
||||
#define SETTING_BRITE_LCD_VALUE 0x0123
|
||||
#define SETTING_BRITE_AUTOGAIN_LO 0x0124
|
||||
#define SETTING_BRITE_AUTOGAIN_HI 0x0125
|
||||
#define SETTING_BRITE_THRESH0 0x012a
|
||||
#define SETTING_BRITE_THRESH1 0x012b
|
||||
#define SETTING_BRITE_THRESH2 0x012c
|
||||
#define SETTING_BRITE_THRESH3 0x012d
|
||||
#define SETTING_BRITE_THRESH4 0x012e
|
||||
|
||||
|
||||
/* prototypes */
|
||||
void menu_settings_save(uint16_t id);
|
||||
|
||||
void settings_save();
|
||||
void settings_restore(uint8_t load_defaults);
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* menu_settings_defprog.h: firmware default LED programs
|
||||
* 2014 by true
|
||||
*
|
||||
* $Id: menu_settings_defprog.h 375 2015-07-06 02:52:40Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
/* SKULL */
|
||||
// random flashing
|
||||
settings.led_prog[0][0].type = 0b10000000; // enabled, no init, program mode
|
||||
settings.led_prog[0][0].dwell = 8;
|
||||
settings.led_prog[0][0].progidx = 4;
|
||||
settings.led_prog[0][0].wait = 80;
|
||||
settings.led_prog[0][0].level = 0xffe0;
|
||||
settings.led_prog[0][0].offset = 0x00;
|
||||
settings.led_prog[0][0].option = 0x03;
|
||||
|
||||
// loops with trails clockwise
|
||||
settings.led_prog[0][1].type = 0b10000000; // enabled, no init, program mode
|
||||
settings.led_prog[0][1].dwell = 7;
|
||||
settings.led_prog[0][1].progidx = 1;
|
||||
settings.led_prog[0][1].wait = 80;
|
||||
settings.led_prog[0][1].level = 0xfff0;
|
||||
settings.led_prog[0][1].offset = 0x80;
|
||||
settings.led_prog[0][1].option = 0xc3;
|
||||
|
||||
// loops with trails white changes direction
|
||||
settings.led_prog[0][2].type = 0b10000000; // enabled, no init, program mode
|
||||
settings.led_prog[0][2].dwell = 7;
|
||||
settings.led_prog[0][2].progidx = 3;
|
||||
settings.led_prog[0][2].wait = 80;
|
||||
settings.led_prog[0][2].level = 0xfff0;
|
||||
settings.led_prog[0][2].offset = 0x00000000;
|
||||
settings.led_prog[0][2].option = 0x400f00c7;
|
||||
|
||||
// purple haze
|
||||
settings.led_prog[0][3].type = 0b10000000; // enabled, no init, program mode
|
||||
settings.led_prog[0][3].dwell = 3;
|
||||
settings.led_prog[0][3].progidx = 4;
|
||||
settings.led_prog[0][3].wait = 15;
|
||||
settings.led_prog[0][3].level = 0xff10;
|
||||
settings.led_prog[0][3].offset = 0x00;
|
||||
settings.led_prog[0][3].option = 0xc3;
|
||||
|
||||
|
||||
/* BONES */
|
||||
// clockwise rotation
|
||||
settings.led_prog[1][0].type = 0b10000000; // enabled, no init, program mode
|
||||
settings.led_prog[1][0].dwell = 15;
|
||||
settings.led_prog[1][0].progidx = 1;
|
||||
settings.led_prog[1][0].wait = 160;
|
||||
settings.led_prog[1][0].level = 0xf0;
|
||||
settings.led_prog[1][0].offset = 0x00;
|
||||
settings.led_prog[1][0].option = 0x50;
|
||||
|
||||
// up-down scrubbing
|
||||
settings.led_prog[1][1].type = 0b10000010; // enabled, init, program mode
|
||||
settings.led_prog[1][1].dwell = 9;
|
||||
settings.led_prog[1][1].progidx = 2;
|
||||
settings.led_prog[1][1].wait = 100;
|
||||
settings.led_prog[1][1].level = 0xff;
|
||||
settings.led_prog[1][1].offset = 0x00;
|
||||
settings.led_prog[1][1].option = 0x50;
|
||||
|
||||
// all on
|
||||
settings.led_prog[1][2].type = 0b10000010; // enabled, init, program mode
|
||||
settings.led_prog[1][2].dwell = 1;
|
||||
settings.led_prog[1][2].progidx = 0;
|
||||
settings.led_prog[1][2].wait = 80;
|
||||
settings.led_prog[1][2].level = 0xf0;
|
||||
settings.led_prog[1][2].offset = 0x00;
|
||||
settings.led_prog[1][2].option = 0x00;
|
||||
|
||||
|
||||
/* EYES */
|
||||
// red with green flashes
|
||||
settings.led_prog[2][0].type = 0b10000000; // enabled, no init, program mode
|
||||
settings.led_prog[2][0].dwell = 15;
|
||||
settings.led_prog[2][0].progidx = 2;
|
||||
settings.led_prog[2][0].wait = 30;
|
||||
settings.led_prog[2][0].level = 0x00;
|
||||
settings.led_prog[2][0].offset = 0x00f000e6;
|
||||
settings.led_prog[2][0].option = 0x14000001;
|
||||
|
||||
// pink-ized "cop mode-lite"
|
||||
settings.led_prog[2][1].type = 0b10000000; // enabled, no init, program mode
|
||||
settings.led_prog[2][1].dwell = 10;
|
||||
settings.led_prog[2][1].progidx = 2;
|
||||
settings.led_prog[2][1].wait = 50;
|
||||
settings.led_prog[2][1].level = 0x00;
|
||||
settings.led_prog[2][1].offset = 0x0000f090;
|
||||
settings.led_prog[2][1].option = 0x20001001;
|
||||
|
||||
// candle flicker with favcolor
|
||||
settings.led_prog[2][2].type = 0b10000000; // enabled, no init, program mode
|
||||
settings.led_prog[2][2].dwell = 18;
|
||||
settings.led_prog[2][2].progidx = 1;
|
||||
settings.led_prog[2][2].wait = 80;
|
||||
settings.led_prog[2][2].level = 0x00;
|
||||
settings.led_prog[2][2].offset = 0x00000000;
|
||||
settings.led_prog[2][2].option = 0x00000000;
|
||||
|
||||
// turquoise-type pulse with red fail-flicker
|
||||
settings.led_prog[2][3].type = 0b10000000; // enabled, no init, program mode
|
||||
settings.led_prog[2][3].dwell = 7;
|
||||
settings.led_prog[2][3].progidx = 2;
|
||||
settings.led_prog[2][3].wait = 20;
|
||||
settings.led_prog[2][3].level = 0x00;
|
||||
settings.led_prog[2][3].offset = 0x00f93012;
|
||||
settings.led_prog[2][3].option = 0x70000001;
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* menu_testing.c: test menu and testing functions
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: menu_testing.c 350 2015-05-28 02:23:03Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#include <pirate.h>
|
||||
|
||||
#include "lcd_menu.h"
|
||||
#include "menu_testing.h"
|
||||
|
||||
|
||||
// testing
|
||||
static uint8_t buzzer_select;
|
||||
static uint8_t matrix_select;
|
||||
|
||||
|
||||
/* menu functions */
|
||||
static char * lcd_menu_testing_buzzer(uint16_t id)
|
||||
{
|
||||
return pirate_sitoa(buzzer_select, 10, 0);
|
||||
}
|
||||
|
||||
static char * lcd_menu_testing_matrix(uint16_t id)
|
||||
{
|
||||
return pirate_sitoa(matrix_select, 10, 0);
|
||||
}
|
||||
|
||||
static char * lcd_menu_testing_boneled(uint16_t id)
|
||||
{
|
||||
return pirate_sitoa(matrix_select, 10, 0);
|
||||
}
|
||||
|
||||
static char * lcd_menu_testing_settings_bytes(uint16_t id)
|
||||
{
|
||||
static char size[12];
|
||||
|
||||
strcpy(size, pirate_sitoa(sizeof(settings), 10, 0));
|
||||
strncat(size, "bytes", 12);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* menu construction */
|
||||
const MenuData menu_test_rdata[] = {
|
||||
{"Buzz ", lcd_menu_testing_buzzer, 0, 0, 0, 0, 0, NULL, 0},
|
||||
{"MPurp ", lcd_menu_testing_matrix, 0, 0, 0, 0, 0, NULL, 0},
|
||||
{"MWht ", lcd_menu_testing_matrix, 0, 0, 0, 0, 0, NULL, 0},
|
||||
{"Bone ", lcd_menu_testing_boneled, 0, 0, 0, 0, 0, NULL, 0},
|
||||
{"NVRAM", lcd_menu_testing_settings_bytes, 0, 10, LCD_DEF_SPACING, LCD_DEF_SCROLL_WAIT, LCD_DEF_SCROLL_RUN, NULL, 0}
|
||||
};
|
||||
|
||||
const MenuItem menu_test_ritem[] = {
|
||||
{&menu_ritem[LCD_MENU_ROOT_TESTING], 0, &menu_test_ritem[1], 0, &menu_test_rdata[0]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_TESTING], &menu_test_ritem[0], &menu_test_ritem[2], 0, &menu_test_rdata[1]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_TESTING], &menu_test_ritem[1], &menu_test_ritem[3], 0, &menu_test_rdata[2]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_TESTING], &menu_test_ritem[2], &menu_test_ritem[4], 0, &menu_test_rdata[3]},
|
||||
{&menu_ritem[LCD_MENU_ROOT_TESTING], &menu_test_ritem[3], 0, 0, &menu_test_rdata[4]}
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* menu_testing.h: test menu and testing functions
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: menu_testing.h 327 2015-02-18 04:43:42Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef __PIRATE_MENU_TESTING_H
|
||||
#define __PIRATE_MENU_TESTING_H
|
||||
|
||||
|
||||
|
||||
/* menus */
|
||||
extern const MenuItem menu_test_ritem[];
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,241 @@
|
|||
/**
|
||||
* pirate.c: yarrrgh mateys miscellaneous shit and system-wide common crap
|
||||
* 2014 by true
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* $Id: pirate.c 505 2021-09-05 19:07:51Z true $
|
||||
*
|
||||
**/
|
||||
|
||||
|
||||
#include "pirate.h"
|
||||
|
||||
#include "device/attiny.h"
|
||||
#include "device/lcd.h"
|
||||
#include "display/cgram/cgram.h"
|
||||
|
||||
|
||||
uint8_t temperature; // pirate.h
|
||||
int8_t temperature_cal; // pirate.h
|
||||
uint8_t light_level; // pirate.h
|
||||
uint8_t light_gain; // pirate.h
|
||||
uint16_t mic_peak; // pirate.h
|
||||
|
||||
uint8_t dc23_nametx;
|
||||
|
||||
|
||||
PirateSettings settings;
|
||||
|
||||
|
||||
/********
|
||||
* CEASE ALL OPERATIONS
|
||||
* note: we still consume ~7mA like this, probably because of circuit design fuckup
|
||||
********/
|
||||
void pirate_shutdown(uint16_t type)
|
||||
{
|
||||
int i;
|
||||
|
||||
// turn off eyes LEDs
|
||||
for (i = 0; i < 8; i++) {
|
||||
led_eyes_set_level(i, 0);
|
||||
}
|
||||
led_eyes_tx();
|
||||
|
||||
// put attiny to sleep
|
||||
attiny_sleep();
|
||||
|
||||
// enable cgram
|
||||
lcd_cmd(LCD_CMD_SINGLEHEIGHT & 0xfe);
|
||||
|
||||
// send crown data
|
||||
for (i = 1; i <= 6; i++) {
|
||||
lcd_print(0x40 + (i << 3), (uint8_t *)cgram_crown[i - 1], 8);
|
||||
}
|
||||
|
||||
// print shutdown message
|
||||
static const uint8_t line1[8] = {0x01, 0x02, 0x03, 'T', 'h', 'r', 'e', 'e'};
|
||||
static const uint8_t line2[8] = {0x04, 0x05, 0x06, 'K', 'i', 'n', 'g', 's'};
|
||||
|
||||
lcd_print(LCD_LINE_1, (uint8_t *)line1, 8);
|
||||
lcd_print(LCD_LINE_2, (uint8_t *)line2, 8);
|
||||
|
||||
// turn off CPU and all peripherals
|
||||
PWR_EnterSTANDBYMode();
|
||||
}
|
||||
|
||||
/********
|
||||
* update the pirate quick pseudorng
|
||||
********/
|
||||
uint32_t pirate_prng_val = 1;
|
||||
uint8_t pirate_prng()
|
||||
{
|
||||
int lsb = pirate_prng_val & 1;
|
||||
pirate_prng_val >>= 1;
|
||||
if (lsb) pirate_prng_val ^= 0x7ffff159;
|
||||
|
||||
return (uint8_t)pirate_prng_val;
|
||||
}
|
||||
|
||||
/********
|
||||
* a really shitty hackish delay function
|
||||
********/
|
||||
void pirate_delay(uint16_t ms)
|
||||
{
|
||||
uint32_t wait;
|
||||
|
||||
wait = ((SystemCoreClock / 2000) * ms) - 20;
|
||||
while (wait--) asm volatile("nop");
|
||||
}
|
||||
|
||||
/********
|
||||
* scale an int16_t from one range to another
|
||||
********/
|
||||
int16_t pirate_scale(int16_t value, int16_t src_min, int16_t src_max, int16_t dest_min, int16_t dest_max)
|
||||
{
|
||||
int32_t w;
|
||||
|
||||
if (dest_min == dest_max) return dest_min;
|
||||
if (value < src_min) return dest_min;
|
||||
if (value > src_max) return dest_max;
|
||||
|
||||
w = (dest_max - dest_min) * (value - src_min);
|
||||
w /= (src_max - src_min);
|
||||
w += dest_min;
|
||||
|
||||
return (int16_t)w;
|
||||
}
|
||||
|
||||
/********
|
||||
* itoa for pirates
|
||||
********/
|
||||
char * pirate_itoa(uint32_t val, uint8_t base, uint8_t leftpad)
|
||||
{
|
||||
static char buf[11] = {0};
|
||||
int i;
|
||||
int j;
|
||||
|
||||
buf[10] = 0;
|
||||
|
||||
if (val == 0) {
|
||||
buf[9] = '0';
|
||||
i = 8;
|
||||
} else {
|
||||
for (i = 9; val && i; --i, val /= base)
|
||||
buf[i] = "0123456789ABCDEF"[val % base];
|
||||
}
|
||||
|
||||
if (leftpad) {
|
||||
j = 9 - leftpad;
|
||||
while (j < i) {
|
||||
buf[i] = 0x20;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
return &buf[i + 1];
|
||||
}
|
||||
|
||||
char * pirate_sitoa(int32_t val, uint8_t base, uint8_t leftpad)
|
||||
{
|
||||
static char buf[11] = {0};
|
||||
int neg;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
buf[10] = 0;
|
||||
|
||||
neg = val < 0 ? 1 : 0;
|
||||
val = abs(val);
|
||||
|
||||
if (val == 0) {
|
||||
buf[9] = '0';
|
||||
i = 8;
|
||||
} else {
|
||||
for (i = 9; val && i; --i, val /= base)
|
||||
buf[i] = "0123456789ABCDEF"[val % base];
|
||||
}
|
||||
|
||||
if (neg) {
|
||||
buf[i] = '-';
|
||||
i--;
|
||||
}
|
||||
|
||||
if (leftpad) {
|
||||
j = 9 - leftpad;
|
||||
while (j < i) {
|
||||
buf[i] = 0x20;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
return &buf[i + 1];
|
||||
}
|
||||
|
||||
/********
|
||||
* battery voltage
|
||||
********/
|
||||
static uint8_t pirate_batt_histlog = 0;
|
||||
static uint16_t pirate_batt_history[32];
|
||||
uint16_t pirate_batt_voltage()
|
||||
{
|
||||
int i;
|
||||
uint32_t t = 0;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
t += pirate_batt_history[i];
|
||||
}
|
||||
|
||||
return t >> 5;
|
||||
}
|
||||
|
||||
void pirate_batt_log(uint16_t rawvalue)
|
||||
{
|
||||
int t;
|
||||
|
||||
t = (rawvalue << 4) / 195;
|
||||
|
||||
pirate_batt_history[pirate_batt_histlog] = t;
|
||||
|
||||
pirate_batt_histlog++;
|
||||
pirate_batt_histlog &= 0x1f;
|
||||
}
|
||||
|
||||
/********
|
||||
* pirate temperature (always hot like a mofo)
|
||||
********/
|
||||
static uint8_t pirate_temp_histlog = 0;
|
||||
static uint8_t pirate_temp_history[20];
|
||||
uint16_t pirate_thermometer(uint8_t deg_f) {
|
||||
int i;
|
||||
uint32_t t = 0;
|
||||
|
||||
for (i = 0; i < 20; i++) {
|
||||
t += pirate_temp_history[i];
|
||||
}
|
||||
|
||||
t >>= 1;
|
||||
|
||||
if (deg_f) {
|
||||
return (((t * 9) / 5) / 10) + 32;
|
||||
} else {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
void pirate_thermometer_log(uint8_t temp)
|
||||
{
|
||||
pirate_temp_history[pirate_temp_histlog] = temp;
|
||||
|
||||
pirate_temp_histlog++;
|
||||
if (pirate_temp_histlog > 20) pirate_temp_histlog = 0;
|
||||
}
|
||||
|
||||
|
||||
/********
|
||||
* shit used by USB
|
||||
********/
|
||||
void Error_Handler()
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file ADC/ADC1_AnalogWatchdog/stm32l1xx_it.c
|
||||
* @author MCD Application Team
|
||||
* @version V1.2.2
|
||||
* @date 17-November-2021
|
||||
* @brief Main Interrupt Service Routines.
|
||||
* This file provides template for all exceptions handler and peripherals
|
||||
* interrupt service routine.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2015 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32l1xx_it.h"
|
||||
|
||||
#ifdef USE_STM32L152D_EVAL
|
||||
#include "stm32l152d_eval.h"
|
||||
#elif defined USE_STM32L152_EVAL
|
||||
#include "stm32l152_eval.h"
|
||||
#endif
|
||||
|
||||
/** @addtogroup STM32L1xx_StdPeriph_Examples
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup ADC1_AnalogWatchdog
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/******************************************************************************/
|
||||
/* Cortex-M3 Processor Exceptions Handlers */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief This function handles NMI exception.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void NMI_Handler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Hard Fault exception.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void HardFault_Handler(void)
|
||||
{
|
||||
/* Go to infinite loop when Hard Fault exception occurs */
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Memory Manage exception.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void MemManage_Handler(void)
|
||||
{
|
||||
/* Go to infinite loop when Memory Manage exception occurs */
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Bus Fault exception.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void BusFault_Handler(void)
|
||||
{
|
||||
/* Go to infinite loop when Bus Fault exception occurs */
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Usage Fault exception.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void UsageFault_Handler(void)
|
||||
{
|
||||
/* Go to infinite loop when Usage Fault exception occurs */
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles SVCall exception.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void SVC_Handler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Debug Monitor exception.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void DebugMon_Handler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles PendSV_Handler exception.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void PendSV_Handler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles SysTick Handler.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* STM32L1xx Peripherals Interrupt Handlers */
|
||||
/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */
|
||||
/* available peripheral interrupt handler's name please refer to the startup */
|
||||
/* file (startup_stm32l1xx_xx.s). */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief This function handles PPP interrupt request.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
/*void PPP_IRQHandler(void)
|
||||
{
|
||||
}*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
@ -0,0 +1,525 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file system_stm32l1xx.c
|
||||
* @author MCD Application Team
|
||||
* @version V1.2.2
|
||||
* @date 17-November-2021
|
||||
* @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Source File.
|
||||
* This file contains the system clock configuration for STM32L1xx Ultra
|
||||
* Low Power devices, and is generated by the clock configuration
|
||||
* tool "STM32L1xx_Clock_Configuration_V1.1.0.xls".
|
||||
*
|
||||
* 1. This file provides two functions and one global variable to be called from
|
||||
* user application:
|
||||
* - SystemInit(): Setups the system clock (System clock source, PLL Multiplier
|
||||
* and Divider factors, AHB/APBx prescalers and Flash settings),
|
||||
* depending on the configuration made in the clock xls tool.
|
||||
* This function is called at startup just after reset and
|
||||
* before branch to main program. This call is made inside
|
||||
* the "startup_stm32l1xx_xx.s" file.
|
||||
*
|
||||
* - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
|
||||
* by the user application to setup the SysTick
|
||||
* timer or configure other parameters.
|
||||
*
|
||||
* - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
|
||||
* be called whenever the core clock is changed
|
||||
* during program execution.
|
||||
*
|
||||
* 2. After each device reset the MSI (2.1 MHz Range) is used as system clock source.
|
||||
* Then SystemInit() function is called, in "startup_stm32l1xx_xx.s" file, to
|
||||
* configure the system clock before to branch to main program.
|
||||
*
|
||||
* 3. If the system clock source selected by user fails to startup, the SystemInit()
|
||||
* function will do nothing and MSI still used as system clock source. User can
|
||||
* add some code to deal with this issue inside the SetSysClock() function.
|
||||
*
|
||||
* 4. The default value of HSE crystal is set to 8MHz, refer to "HSE_VALUE" define
|
||||
* in "stm32l1xx.h" file. When HSE is used as system clock source, directly or
|
||||
* through PLL, and you are using different crystal you have to adapt the HSE
|
||||
* value to your own configuration.
|
||||
*
|
||||
* 5. This file configures the system clock as follows:
|
||||
*=============================================================================
|
||||
* System Clock Configuration
|
||||
*=============================================================================
|
||||
* System Clock source | PLL(HSE)
|
||||
*-----------------------------------------------------------------------------
|
||||
* SYSCLK | 32000000 Hz
|
||||
*-----------------------------------------------------------------------------
|
||||
* HCLK | 32000000 Hz
|
||||
*-----------------------------------------------------------------------------
|
||||
* AHB Prescaler | 1
|
||||
*-----------------------------------------------------------------------------
|
||||
* APB1 Prescaler | 1
|
||||
*-----------------------------------------------------------------------------
|
||||
* APB2 Prescaler | 1
|
||||
*-----------------------------------------------------------------------------
|
||||
* HSE Frequency | 8000000 Hz
|
||||
*-----------------------------------------------------------------------------
|
||||
* PLL DIV | 3
|
||||
*-----------------------------------------------------------------------------
|
||||
* PLL MUL | 12
|
||||
*-----------------------------------------------------------------------------
|
||||
* VDD | 3.3 V
|
||||
*-----------------------------------------------------------------------------
|
||||
* Vcore | 1.8 V (Range 1)
|
||||
*-----------------------------------------------------------------------------
|
||||
* Flash Latency | 1 WS
|
||||
*-----------------------------------------------------------------------------
|
||||
* SDIO clock (SDIOCLK) | 48000000 Hz
|
||||
*-----------------------------------------------------------------------------
|
||||
* Require 48MHz for USB clock | Disabled
|
||||
*-----------------------------------------------------------------------------
|
||||
*=============================================================================
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2015 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup CMSIS
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup stm32l1xx_system
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32L1xx_System_Private_Includes
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "stm32l1xx.h"
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32L1xx_System_Private_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32L1xx_System_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!< Uncomment the following line if you need to use external SRAM mounted
|
||||
on STM32L152D_EVAL board as data memory */
|
||||
/* #define DATA_IN_ExtSRAM */
|
||||
|
||||
/*!< Uncomment the following line if you need to relocate your vector Table in
|
||||
Internal SRAM. */
|
||||
/* #define VECT_TAB_SRAM */
|
||||
#define VECT_TAB_OFFSET 0x0 /*!< Vector Table base offset field.
|
||||
This value must be a multiple of 0x200. */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32L1xx_System_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32L1xx_System_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
uint32_t SystemCoreClock = 32000000;
|
||||
__I uint8_t PLLMulTable[9] = {3, 4, 6, 8, 12, 16, 24, 32, 48};
|
||||
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32L1xx_System_Private_FunctionPrototypes
|
||||
* @{
|
||||
*/
|
||||
|
||||
static void SetSysClock(void);
|
||||
#ifdef DATA_IN_ExtSRAM
|
||||
static void SystemInit_ExtMemCtl(void);
|
||||
#endif /* DATA_IN_ExtSRAM */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32L1xx_System_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Setup the microcontroller system.
|
||||
* Initialize the Embedded Flash Interface, the PLL and update the
|
||||
* SystemCoreClock variable.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void SystemInit (void)
|
||||
{
|
||||
/*!< Set MSION bit */
|
||||
RCC->CR |= (uint32_t)0x00000100;
|
||||
|
||||
/*!< Reset SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], MCOSEL[2:0] and MCOPRE[2:0] bits */
|
||||
RCC->CFGR &= (uint32_t)0x88FFC00C;
|
||||
|
||||
/*!< Reset HSION, HSEON, CSSON and PLLON bits */
|
||||
RCC->CR &= (uint32_t)0xEEFEFFFE;
|
||||
|
||||
/*!< Reset HSEBYP bit */
|
||||
RCC->CR &= (uint32_t)0xFFFBFFFF;
|
||||
|
||||
/*!< Reset PLLSRC, PLLMUL[3:0] and PLLDIV[1:0] bits */
|
||||
RCC->CFGR &= (uint32_t)0xFF02FFFF;
|
||||
|
||||
/*!< Disable all interrupts */
|
||||
RCC->CIR = 0x00000000;
|
||||
|
||||
#ifdef DATA_IN_ExtSRAM
|
||||
SystemInit_ExtMemCtl();
|
||||
#endif /* DATA_IN_ExtSRAM */
|
||||
|
||||
/* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */
|
||||
SetSysClock();
|
||||
|
||||
#ifdef VECT_TAB_SRAM
|
||||
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
|
||||
#else
|
||||
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update SystemCoreClock according to Clock Register Values
|
||||
* The SystemCoreClock variable contains the core clock (HCLK), it can
|
||||
* be used by the user application to setup the SysTick timer or configure
|
||||
* other parameters.
|
||||
*
|
||||
* @note Each time the core clock (HCLK) changes, this function must be called
|
||||
* to update SystemCoreClock variable value. Otherwise, any configuration
|
||||
* based on this variable will be incorrect.
|
||||
*
|
||||
* @note - The system frequency computed by this function is not the real
|
||||
* frequency in the chip. It is calculated based on the predefined
|
||||
* constant and the selected clock source:
|
||||
*
|
||||
* - If SYSCLK source is MSI, SystemCoreClock will contain the MSI
|
||||
* value as defined by the MSI range.
|
||||
*
|
||||
* - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
|
||||
*
|
||||
* - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
|
||||
*
|
||||
* - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
|
||||
* or HSI_VALUE(*) multiplied/divided by the PLL factors.
|
||||
*
|
||||
* (*) HSI_VALUE is a constant defined in stm32l1xx.h file (default value
|
||||
* 16 MHz) but the real value may vary depending on the variations
|
||||
* in voltage and temperature.
|
||||
*
|
||||
* (**) HSE_VALUE is a constant defined in stm32l1xx.h file (default value
|
||||
* 8 MHz), user has to ensure that HSE_VALUE is same as the real
|
||||
* frequency of the crystal used. Otherwise, this function may
|
||||
* have wrong result.
|
||||
*
|
||||
* - The result of this function could be not correct when using fractional
|
||||
* value for HSE crystal.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void SystemCoreClockUpdate (void)
|
||||
{
|
||||
uint32_t tmp = 0, pllmul = 0, plldiv = 0, pllsource = 0, msirange = 0;
|
||||
|
||||
/* Get SYSCLK source -------------------------------------------------------*/
|
||||
tmp = RCC->CFGR & RCC_CFGR_SWS;
|
||||
|
||||
switch (tmp)
|
||||
{
|
||||
case 0x00: /* MSI used as system clock */
|
||||
msirange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE) >> 13;
|
||||
SystemCoreClock = (32768 * (1 << (msirange + 1)));
|
||||
break;
|
||||
case 0x04: /* HSI used as system clock */
|
||||
SystemCoreClock = HSI_VALUE;
|
||||
break;
|
||||
case 0x08: /* HSE used as system clock */
|
||||
SystemCoreClock = HSE_VALUE;
|
||||
break;
|
||||
case 0x0C: /* PLL used as system clock */
|
||||
/* Get PLL clock source and multiplication factor ----------------------*/
|
||||
pllmul = RCC->CFGR & RCC_CFGR_PLLMUL;
|
||||
plldiv = RCC->CFGR & RCC_CFGR_PLLDIV;
|
||||
pllmul = PLLMulTable[(pllmul >> 18)];
|
||||
plldiv = (plldiv >> 22) + 1;
|
||||
|
||||
pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
|
||||
|
||||
if (pllsource == 0x00)
|
||||
{
|
||||
/* HSI oscillator clock selected as PLL clock entry */
|
||||
SystemCoreClock = (((HSI_VALUE) * pllmul) / plldiv);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* HSE selected as PLL clock entry */
|
||||
SystemCoreClock = (((HSE_VALUE) * pllmul) / plldiv);
|
||||
}
|
||||
break;
|
||||
default: /* MSI used as system clock */
|
||||
msirange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE) >> 13;
|
||||
SystemCoreClock = (32768 * (1 << (msirange + 1)));
|
||||
break;
|
||||
}
|
||||
/* Compute HCLK clock frequency --------------------------------------------*/
|
||||
/* Get HCLK prescaler */
|
||||
tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
|
||||
/* HCLK clock frequency */
|
||||
SystemCoreClock >>= tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the System clock frequency, AHB/APBx prescalers and Flash
|
||||
* settings.
|
||||
* @note This function should be called only once the RCC clock configuration
|
||||
* is reset to the default reset state (done in SystemInit() function).
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void SetSysClock(void)
|
||||
{
|
||||
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
||||
|
||||
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
|
||||
/* Enable HSE */
|
||||
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
|
||||
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CR & RCC_CR_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
|
||||
{
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
}
|
||||
|
||||
if (HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
/* Enable 64-bit access */
|
||||
FLASH->ACR |= FLASH_ACR_ACC64;
|
||||
|
||||
/* Enable Prefetch Buffer */
|
||||
FLASH->ACR |= FLASH_ACR_PRFTEN;
|
||||
|
||||
/* Flash 1 wait state */
|
||||
FLASH->ACR |= FLASH_ACR_LATENCY;
|
||||
|
||||
/* Power enable */
|
||||
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
|
||||
|
||||
/* Select the Voltage Range 1 (1.8 V) */
|
||||
PWR->CR = PWR_CR_VOS_0;
|
||||
|
||||
/* Wait Until the Voltage Regulator is ready */
|
||||
while((PWR->CSR & PWR_CSR_VOSF) != RESET)
|
||||
{
|
||||
}
|
||||
|
||||
/* HCLK = SYSCLK /1*/
|
||||
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
|
||||
|
||||
/* PCLK2 = HCLK /1*/
|
||||
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
|
||||
|
||||
/* PCLK1 = HCLK /1*/
|
||||
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
|
||||
|
||||
/* PLL configuration */
|
||||
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL |
|
||||
RCC_CFGR_PLLDIV));
|
||||
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMUL12 | RCC_CFGR_PLLDIV3);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CR & RCC_CR_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
|
||||
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
|
||||
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If HSE fails to start-up, the application will have wrong clock
|
||||
configuration. User can add here some code to deal with this error */
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DATA_IN_ExtSRAM
|
||||
/**
|
||||
* @brief Setup the external memory controller.
|
||||
* Called in SystemInit() function before jump to main.
|
||||
* This function configures the external SRAM mounted on STM32L152D_EVAL board
|
||||
* This SRAM will be used as program data memory (including heap and stack).
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void SystemInit_ExtMemCtl(void)
|
||||
{
|
||||
/*-- GPIOs Configuration -----------------------------------------------------*/
|
||||
/*
|
||||
+-------------------+--------------------+------------------+------------------+
|
||||
+ SRAM pins assignment +
|
||||
+-------------------+--------------------+------------------+------------------+
|
||||
| PD0 <-> FSMC_D2 | PE0 <-> FSMC_NBL0 | PF0 <-> FSMC_A0 | PG0 <-> FSMC_A10 |
|
||||
| PD1 <-> FSMC_D3 | PE1 <-> FSMC_NBL1 | PF1 <-> FSMC_A1 | PG1 <-> FSMC_A11 |
|
||||
| PD4 <-> FSMC_NOE | PE7 <-> FSMC_D4 | PF2 <-> FSMC_A2 | PG2 <-> FSMC_A12 |
|
||||
| PD5 <-> FSMC_NWE | PE8 <-> FSMC_D5 | PF3 <-> FSMC_A3 | PG3 <-> FSMC_A13 |
|
||||
| PD8 <-> FSMC_D13 | PE9 <-> FSMC_D6 | PF4 <-> FSMC_A4 | PG4 <-> FSMC_A14 |
|
||||
| PD9 <-> FSMC_D14 | PE10 <-> FSMC_D7 | PF5 <-> FSMC_A5 | PG5 <-> FSMC_A15 |
|
||||
| PD10 <-> FSMC_D15 | PE11 <-> FSMC_D8 | PF12 <-> FSMC_A6 | PG10<-> FSMC_NE2 |
|
||||
| PD11 <-> FSMC_A16 | PE12 <-> FSMC_D9 | PF13 <-> FSMC_A7 |------------------+
|
||||
| PD12 <-> FSMC_A17 | PE13 <-> FSMC_D10 | PF14 <-> FSMC_A8 |
|
||||
| PD13 <-> FSMC_A18 | PE14 <-> FSMC_D11 | PF15 <-> FSMC_A9 |
|
||||
| PD14 <-> FSMC_D0 | PE15 <-> FSMC_D12 |------------------+
|
||||
| PD15 <-> FSMC_D1 |--------------------+
|
||||
+-------------------+
|
||||
*/
|
||||
|
||||
/* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */
|
||||
RCC->AHBENR = 0x000080D8;
|
||||
|
||||
/* Connect PDx pins to FSMC Alternate function */
|
||||
GPIOD->AFR[0] = 0x00CC00CC;
|
||||
GPIOD->AFR[1] = 0xCCCCCCCC;
|
||||
/* Configure PDx pins in Alternate function mode */
|
||||
GPIOD->MODER = 0xAAAA0A0A;
|
||||
/* Configure PDx pins speed to 40 MHz */
|
||||
GPIOD->OSPEEDR = 0xFFFF0F0F;
|
||||
/* Configure PDx pins Output type to push-pull */
|
||||
GPIOD->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PDx pins */
|
||||
GPIOD->PUPDR = 0x00000000;
|
||||
|
||||
/* Connect PEx pins to FSMC Alternate function */
|
||||
GPIOE->AFR[0] = 0xC00000CC;
|
||||
GPIOE->AFR[1] = 0xCCCCCCCC;
|
||||
/* Configure PEx pins in Alternate function mode */
|
||||
GPIOE->MODER = 0xAAAA800A;
|
||||
/* Configure PEx pins speed to 40 MHz */
|
||||
GPIOE->OSPEEDR = 0xFFFFC00F;
|
||||
/* Configure PEx pins Output type to push-pull */
|
||||
GPIOE->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PEx pins */
|
||||
GPIOE->PUPDR = 0x00000000;
|
||||
|
||||
/* Connect PFx pins to FSMC Alternate function */
|
||||
GPIOF->AFR[0] = 0x00CCCCCC;
|
||||
GPIOF->AFR[1] = 0xCCCC0000;
|
||||
/* Configure PFx pins in Alternate function mode */
|
||||
GPIOF->MODER = 0xAA000AAA;
|
||||
/* Configure PFx pins speed to 40 MHz */
|
||||
GPIOF->OSPEEDR = 0xFF000FFF;
|
||||
/* Configure PFx pins Output type to push-pull */
|
||||
GPIOF->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PFx pins */
|
||||
GPIOF->PUPDR = 0x00000000;
|
||||
|
||||
/* Connect PGx pins to FSMC Alternate function */
|
||||
GPIOG->AFR[0] = 0x00CCCCCC;
|
||||
GPIOG->AFR[1] = 0x00000C00;
|
||||
/* Configure PGx pins in Alternate function mode */
|
||||
GPIOG->MODER = 0x00200AAA;
|
||||
/* Configure PGx pins speed to 40 MHz */
|
||||
GPIOG->OSPEEDR = 0x00300FFF;
|
||||
/* Configure PGx pins Output type to push-pull */
|
||||
GPIOG->OTYPER = 0x00000000;
|
||||
/* No pull-up, pull-down for PGx pins */
|
||||
GPIOG->PUPDR = 0x00000000;
|
||||
|
||||
/*-- FSMC Configuration ------------------------------------------------------*/
|
||||
/* Enable the FSMC interface clock */
|
||||
RCC->AHBENR = 0x400080D8;
|
||||
|
||||
/* Configure and enable Bank1_SRAM3 */
|
||||
FSMC_Bank1->BTCR[4] = 0x00001011;
|
||||
FSMC_Bank1->BTCR[5] = 0x00000300;
|
||||
FSMC_Bank1E->BWTR[4] = 0x0FFFFFFF;
|
||||
/*
|
||||
Bank1_SRAM3 is configured as follow:
|
||||
|
||||
p.FSMC_AddressSetupTime = 0;
|
||||
p.FSMC_AddressHoldTime = 0;
|
||||
p.FSMC_DataSetupTime = 3;
|
||||
p.FSMC_BusTurnAroundDuration = 0;
|
||||
p.FSMC_CLKDivision = 0;
|
||||
p.FSMC_DataLatency = 0;
|
||||
p.FSMC_AccessMode = FSMC_AccessMode_A;
|
||||
|
||||
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3;
|
||||
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
|
||||
FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
|
||||
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
|
||||
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
|
||||
FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
|
||||
FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
|
||||
FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
|
||||
FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
|
||||
FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
|
||||
FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
|
||||
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
|
||||
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
|
||||
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
|
||||
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
|
||||
|
||||
FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
|
||||
|
||||
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE);
|
||||
*/
|
||||
|
||||
}
|
||||
#endif /* DATA_IN_ExtSRAM */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,259 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_core.h
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 28-August-2012
|
||||
* @brief Standard protocol processing functions prototypes
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USB_CORE_H
|
||||
#define __USB_CORE_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
typedef enum _CONTROL_STATE
|
||||
{
|
||||
WAIT_SETUP, /* 0 */
|
||||
SETTING_UP, /* 1 */
|
||||
IN_DATA, /* 2 */
|
||||
OUT_DATA, /* 3 */
|
||||
LAST_IN_DATA, /* 4 */
|
||||
LAST_OUT_DATA, /* 5 */
|
||||
WAIT_STATUS_IN, /* 7 */
|
||||
WAIT_STATUS_OUT, /* 8 */
|
||||
STALLED, /* 9 */
|
||||
PAUSE /* 10 */
|
||||
} CONTROL_STATE; /* The state machine states of a control pipe */
|
||||
|
||||
typedef struct OneDescriptor
|
||||
{
|
||||
uint8_t *Descriptor;
|
||||
uint16_t Descriptor_Size;
|
||||
}
|
||||
ONE_DESCRIPTOR, *PONE_DESCRIPTOR;
|
||||
/* All the request process routines return a value of this type
|
||||
If the return value is not SUCCESS or NOT_READY,
|
||||
the software will STALL the correspond endpoint */
|
||||
typedef enum _RESULT
|
||||
{
|
||||
USB_SUCCESS = 0, /* Process successfully */
|
||||
USB_ERROR,
|
||||
USB_UNSUPPORT,
|
||||
USB_NOT_READY /* The process has not been finished, endpoint will be
|
||||
NAK to further request */
|
||||
} RESULT;
|
||||
|
||||
|
||||
/*-*-*-*-*-*-*-*-*-*-* Definitions for endpoint level -*-*-*-*-*-*-*-*-*-*-*-*/
|
||||
typedef struct _ENDPOINT_INFO
|
||||
{
|
||||
/* When send data out of the device,
|
||||
CopyData() is used to get data buffer 'Length' bytes data
|
||||
if Length is 0,
|
||||
CopyData() returns the total length of the data
|
||||
if the request is not supported, returns 0
|
||||
(NEW Feature )
|
||||
if CopyData() returns -1, the calling routine should not proceed
|
||||
further and will resume the SETUP process by the class device
|
||||
if Length is not 0,
|
||||
CopyData() returns a pointer to indicate the data location
|
||||
Usb_wLength is the data remain to be sent,
|
||||
Usb_wOffset is the Offset of original data
|
||||
When receive data from the host,
|
||||
CopyData() is used to get user data buffer which is capable
|
||||
of Length bytes data to copy data from the endpoint buffer.
|
||||
if Length is 0,
|
||||
CopyData() returns the available data length,
|
||||
if Length is not 0,
|
||||
CopyData() returns user buffer address
|
||||
Usb_rLength is the data remain to be received,
|
||||
Usb_rPointer is the Offset of data buffer
|
||||
*/
|
||||
uint16_t Usb_wLength;
|
||||
uint16_t Usb_wOffset;
|
||||
uint16_t PacketSize;
|
||||
uint8_t *(*CopyData)(uint16_t Length);
|
||||
}ENDPOINT_INFO;
|
||||
|
||||
/*-*-*-*-*-*-*-*-*-*-*-* Definitions for device level -*-*-*-*-*-*-*-*-*-*-*-*/
|
||||
|
||||
typedef struct _DEVICE
|
||||
{
|
||||
uint8_t Total_Endpoint; /* Number of endpoints that are used */
|
||||
uint8_t Total_Configuration;/* Number of configuration available */
|
||||
}
|
||||
DEVICE;
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint16_t w;
|
||||
struct BW
|
||||
{
|
||||
uint8_t bb1;
|
||||
uint8_t bb0;
|
||||
}
|
||||
bw;
|
||||
} uint16_t_uint8_t;
|
||||
|
||||
typedef struct _DEVICE_INFO
|
||||
{
|
||||
uint8_t USBbmRequestType; /* bmRequestType */
|
||||
uint8_t USBbRequest; /* bRequest */
|
||||
uint16_t_uint8_t USBwValues; /* wValue */
|
||||
uint16_t_uint8_t USBwIndexs; /* wIndex */
|
||||
uint16_t_uint8_t USBwLengths; /* wLength */
|
||||
|
||||
uint8_t ControlState; /* of type CONTROL_STATE */
|
||||
uint8_t Current_Feature;
|
||||
uint8_t Current_Configuration; /* Selected configuration */
|
||||
uint8_t Current_Interface; /* Selected interface of current configuration */
|
||||
uint8_t Current_AlternateSetting;/* Selected Alternate Setting of current
|
||||
interface*/
|
||||
|
||||
ENDPOINT_INFO Ctrl_Info;
|
||||
}DEVICE_INFO;
|
||||
|
||||
typedef struct _DEVICE_PROP
|
||||
{
|
||||
void (*Init)(void); /* Initialize the device */
|
||||
void (*Reset)(void); /* Reset routine of this device */
|
||||
|
||||
/* Device dependent process after the status stage */
|
||||
void (*Process_Status_IN)(void);
|
||||
void (*Process_Status_OUT)(void);
|
||||
|
||||
/* Procedure of process on setup stage of a class specified request with data stage */
|
||||
/* All class specified requests with data stage are processed in Class_Data_Setup
|
||||
Class_Data_Setup()
|
||||
responses to check all special requests and fills ENDPOINT_INFO
|
||||
according to the request
|
||||
If IN tokens are expected, then wLength & wOffset will be filled
|
||||
with the total transferring bytes and the starting position
|
||||
If OUT tokens are expected, then rLength & rOffset will be filled
|
||||
with the total expected bytes and the starting position in the buffer
|
||||
|
||||
If the request is valid, Class_Data_Setup returns SUCCESS, else UNSUPPORT
|
||||
|
||||
CAUTION:
|
||||
Since GET_CONFIGURATION & GET_INTERFACE are highly related to
|
||||
the individual classes, they will be checked and processed here.
|
||||
*/
|
||||
RESULT (*Class_Data_Setup)(uint8_t RequestNo);
|
||||
|
||||
/* Procedure of process on setup stage of a class specified request without data stage */
|
||||
/* All class specified requests without data stage are processed in Class_NoData_Setup
|
||||
Class_NoData_Setup
|
||||
responses to check all special requests and perform the request
|
||||
|
||||
CAUTION:
|
||||
Since SET_CONFIGURATION & SET_INTERFACE are highly related to
|
||||
the individual classes, they will be checked and processed here.
|
||||
*/
|
||||
RESULT (*Class_NoData_Setup)(uint8_t RequestNo);
|
||||
|
||||
/*Class_Get_Interface_Setting
|
||||
This function is used by the file usb_core.c to test if the selected Interface
|
||||
and Alternate Setting (uint8_t Interface, uint8_t AlternateSetting) are supported by
|
||||
the application.
|
||||
This function is writing by user. It should return "SUCCESS" if the Interface
|
||||
and Alternate Setting are supported by the application or "UNSUPPORT" if they
|
||||
are not supported. */
|
||||
|
||||
RESULT (*Class_Get_Interface_Setting)(uint8_t Interface, uint8_t AlternateSetting);
|
||||
|
||||
uint8_t* (*GetDeviceDescriptor)(uint16_t Length);
|
||||
uint8_t* (*GetConfigDescriptor)(uint16_t Length);
|
||||
uint8_t* (*GetStringDescriptor)(uint16_t Length);
|
||||
|
||||
/* This field is not used in current library version. It is kept only for
|
||||
compatibility with previous versions */
|
||||
void* RxEP_buffer;
|
||||
|
||||
uint8_t MaxPacketSize;
|
||||
|
||||
}DEVICE_PROP;
|
||||
|
||||
typedef struct _USER_STANDARD_REQUESTS
|
||||
{
|
||||
void (*User_GetConfiguration)(void); /* Get Configuration */
|
||||
void (*User_SetConfiguration)(void); /* Set Configuration */
|
||||
void (*User_GetInterface)(void); /* Get Interface */
|
||||
void (*User_SetInterface)(void); /* Set Interface */
|
||||
void (*User_GetStatus)(void); /* Get Status */
|
||||
void (*User_ClearFeature)(void); /* Clear Feature */
|
||||
void (*User_SetEndPointFeature)(void); /* Set Endpoint Feature */
|
||||
void (*User_SetDeviceFeature)(void); /* Set Device Feature */
|
||||
void (*User_SetDeviceAddress)(void); /* Set Device Address */
|
||||
}
|
||||
USER_STANDARD_REQUESTS;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
#define Type_Recipient (pInformation->USBbmRequestType & (REQUEST_TYPE | RECIPIENT))
|
||||
|
||||
#define Usb_rLength Usb_wLength
|
||||
#define Usb_rOffset Usb_wOffset
|
||||
|
||||
#define USBwValue USBwValues.w
|
||||
#define USBwValue0 USBwValues.bw.bb0
|
||||
#define USBwValue1 USBwValues.bw.bb1
|
||||
#define USBwIndex USBwIndexs.w
|
||||
#define USBwIndex0 USBwIndexs.bw.bb0
|
||||
#define USBwIndex1 USBwIndexs.bw.bb1
|
||||
#define USBwLength USBwLengths.w
|
||||
#define USBwLength0 USBwLengths.bw.bb0
|
||||
#define USBwLength1 USBwLengths.bw.bb1
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
uint8_t Setup0_Process(void);
|
||||
uint8_t Post0_Process(void);
|
||||
uint8_t Out0_Process(void);
|
||||
uint8_t In0_Process(void);
|
||||
|
||||
RESULT Standard_SetEndPointFeature(void);
|
||||
RESULT Standard_SetDeviceFeature(void);
|
||||
|
||||
uint8_t *Standard_GetConfiguration(uint16_t Length);
|
||||
RESULT Standard_SetConfiguration(void);
|
||||
uint8_t *Standard_GetInterface(uint16_t Length);
|
||||
RESULT Standard_SetInterface(void);
|
||||
uint8_t *Standard_GetDescriptorData(uint16_t Length, PONE_DESCRIPTOR pDesc);
|
||||
|
||||
uint8_t *Standard_GetStatus(uint16_t Length);
|
||||
RESULT Standard_ClearFeature(void);
|
||||
void SetDeviceAddress(uint8_t);
|
||||
void NOP_Process(void);
|
||||
|
||||
extern DEVICE_PROP Device_Property;
|
||||
extern USER_STANDARD_REQUESTS User_Standard_Requests;
|
||||
extern DEVICE Device_Table;
|
||||
extern DEVICE_INFO Device_Info;
|
||||
|
||||
/* cells saving status during interrupt servicing */
|
||||
extern __IO uint16_t SaveRState;
|
||||
extern __IO uint16_t SaveTState;
|
||||
|
||||
#endif /* __USB_CORE_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_def.h
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 28-August-2012
|
||||
* @brief Definitions related to USB Core
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USB_DEF_H
|
||||
#define __USB_DEF_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
typedef enum _RECIPIENT_TYPE
|
||||
{
|
||||
DEVICE_RECIPIENT, /* Recipient device */
|
||||
INTERFACE_RECIPIENT, /* Recipient interface */
|
||||
ENDPOINT_RECIPIENT, /* Recipient endpoint */
|
||||
OTHER_RECIPIENT
|
||||
} RECIPIENT_TYPE;
|
||||
|
||||
|
||||
typedef enum _STANDARD_REQUESTS
|
||||
{
|
||||
GET_STATUS = 0,
|
||||
CLEAR_FEATURE,
|
||||
RESERVED1,
|
||||
SET_FEATURE,
|
||||
RESERVED2,
|
||||
SET_ADDRESS,
|
||||
GET_DESCRIPTOR,
|
||||
SET_DESCRIPTOR,
|
||||
GET_CONFIGURATION,
|
||||
SET_CONFIGURATION,
|
||||
GET_INTERFACE,
|
||||
SET_INTERFACE,
|
||||
TOTAL_sREQUEST, /* Total number of Standard request */
|
||||
SYNCH_FRAME = 12
|
||||
} STANDARD_REQUESTS;
|
||||
|
||||
/* Definition of "USBwValue" */
|
||||
typedef enum _DESCRIPTOR_TYPE
|
||||
{
|
||||
DEVICE_DESCRIPTOR = 1,
|
||||
CONFIG_DESCRIPTOR,
|
||||
STRING_DESCRIPTOR,
|
||||
INTERFACE_DESCRIPTOR,
|
||||
ENDPOINT_DESCRIPTOR
|
||||
} DESCRIPTOR_TYPE;
|
||||
|
||||
/* Feature selector of a SET_FEATURE or CLEAR_FEATURE */
|
||||
typedef enum _FEATURE_SELECTOR
|
||||
{
|
||||
ENDPOINT_STALL,
|
||||
DEVICE_REMOTE_WAKEUP
|
||||
} FEATURE_SELECTOR;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Definition of "USBbmRequestType" */
|
||||
#define REQUEST_TYPE 0x60 /* Mask to get request type */
|
||||
#define STANDARD_REQUEST 0x00 /* Standard request */
|
||||
#define CLASS_REQUEST 0x20 /* Class request */
|
||||
#define VENDOR_REQUEST 0x40 /* Vendor request */
|
||||
|
||||
#define RECIPIENT 0x1F /* Mask to get recipient */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
#endif /* __USB_DEF_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_init.c
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 28-August-2012
|
||||
* @brief Initialization routines & global variables
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_lib.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* The number of current endpoint, it will be used to specify an endpoint */
|
||||
uint8_t EPindex;
|
||||
/* The number of current device, it is an index to the Device_Table */
|
||||
/* uint8_t Device_no; */
|
||||
/* Points to the DEVICE_INFO structure of current device */
|
||||
/* The purpose of this register is to speed up the execution */
|
||||
DEVICE_INFO *pInformation;
|
||||
/* Points to the DEVICE_PROP structure of current device */
|
||||
/* The purpose of this register is to speed up the execution */
|
||||
DEVICE_PROP *pProperty;
|
||||
/* Temporary save the state of Rx & Tx status. */
|
||||
/* Whenever the Rx or Tx state is changed, its value is saved */
|
||||
/* in this variable first and will be set to the EPRB or EPRA */
|
||||
/* at the end of interrupt process */
|
||||
uint16_t SaveState ;
|
||||
uint16_t wInterrupt_Mask;
|
||||
DEVICE_INFO Device_Info;
|
||||
USER_STANDARD_REQUESTS *pUser_Standard_Requests;
|
||||
|
||||
/* Extern variables ----------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : USB_Init
|
||||
* Description : USB system initialization
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void USB_Init(void)
|
||||
{
|
||||
pInformation = &Device_Info;
|
||||
pInformation->ControlState = 2;
|
||||
pProperty = &Device_Property;
|
||||
pUser_Standard_Requests = &User_Standard_Requests;
|
||||
/* Initialize devices one by one */
|
||||
pProperty->Init();
|
||||
}
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_init.h
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 28-August-2012
|
||||
* @brief Initialization routines & global variables
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USB_INIT_H
|
||||
#define __USB_INIT_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void USB_Init(void);
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
/* The number of current endpoint, it will be used to specify an endpoint */
|
||||
extern uint8_t EPindex;
|
||||
/* The number of current device, it is an index to the Device_Table */
|
||||
/*extern uint8_t Device_no; */
|
||||
/* Points to the DEVICE_INFO structure of current device */
|
||||
/* The purpose of this register is to speed up the execution */
|
||||
extern DEVICE_INFO* pInformation;
|
||||
/* Points to the DEVICE_PROP structure of current device */
|
||||
/* The purpose of this register is to speed up the execution */
|
||||
extern DEVICE_PROP* pProperty;
|
||||
/* Temporary save the state of Rx & Tx status. */
|
||||
/* Whenever the Rx or Tx state is changed, its value is saved */
|
||||
/* in this variable first and will be set to the EPRB or EPRA */
|
||||
/* at the end of interrupt process */
|
||||
extern USER_STANDARD_REQUESTS *pUser_Standard_Requests;
|
||||
|
||||
extern uint16_t SaveState ;
|
||||
extern uint16_t wInterrupt_Mask;
|
||||
|
||||
#endif /* __USB_INIT_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,195 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_int.c
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 28-August-2012
|
||||
* @brief Endpoint CTR (Low and High) interrupt's service routines
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_lib.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
__IO uint16_t SaveRState;
|
||||
__IO uint16_t SaveTState;
|
||||
|
||||
/* Extern variables ----------------------------------------------------------*/
|
||||
extern void (*pEpInt_IN[7])(void); /* Handles IN interrupts */
|
||||
extern void (*pEpInt_OUT[7])(void); /* Handles OUT interrupts */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : CTR_LP.
|
||||
* Description : Low priority Endpoint Correct Transfer interrupt's service
|
||||
* routine.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void CTR_LP(void)
|
||||
{
|
||||
__IO uint16_t wEPVal = 0;
|
||||
/* stay in loop while pending interrupts */
|
||||
while (((wIstr = _GetISTR()) & ISTR_CTR) != 0)
|
||||
{
|
||||
/* extract highest priority endpoint number */
|
||||
EPindex = (uint8_t)(wIstr & ISTR_EP_ID);
|
||||
if (EPindex == 0)
|
||||
{
|
||||
/* Decode and service control endpoint interrupt */
|
||||
/* calling related service routine */
|
||||
/* (Setup0_Process, In0_Process, Out0_Process) */
|
||||
|
||||
/* save RX & TX status */
|
||||
/* and set both to NAK */
|
||||
|
||||
SaveRState = _GetENDPOINT(ENDP0);
|
||||
SaveTState = SaveRState & EPTX_STAT;
|
||||
SaveRState &= EPRX_STAT;
|
||||
|
||||
_SetEPRxTxStatus(ENDP0,EP_RX_NAK,EP_TX_NAK);
|
||||
|
||||
/* DIR bit = origin of the interrupt */
|
||||
|
||||
if ((wIstr & ISTR_DIR) == 0)
|
||||
{
|
||||
/* DIR = 0 */
|
||||
|
||||
/* DIR = 0 => IN int */
|
||||
/* DIR = 0 implies that (EP_CTR_TX = 1) always */
|
||||
|
||||
_ClearEP_CTR_TX(ENDP0);
|
||||
In0_Process();
|
||||
|
||||
/* before terminate set Tx & Rx status */
|
||||
|
||||
_SetEPRxTxStatus(ENDP0,SaveRState,SaveTState);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* DIR = 1 */
|
||||
|
||||
/* DIR = 1 & CTR_RX => SETUP or OUT int */
|
||||
/* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
|
||||
|
||||
wEPVal = _GetENDPOINT(ENDP0);
|
||||
|
||||
if ((wEPVal &EP_SETUP) != 0)
|
||||
{
|
||||
_ClearEP_CTR_RX(ENDP0); /* SETUP bit kept frozen while CTR_RX = 1 */
|
||||
Setup0_Process();
|
||||
/* before terminate set Tx & Rx status */
|
||||
|
||||
_SetEPRxTxStatus(ENDP0,SaveRState,SaveTState);
|
||||
return;
|
||||
}
|
||||
|
||||
else if ((wEPVal & EP_CTR_RX) != 0)
|
||||
{
|
||||
_ClearEP_CTR_RX(ENDP0);
|
||||
Out0_Process();
|
||||
/* before terminate set Tx & Rx status */
|
||||
|
||||
_SetEPRxTxStatus(ENDP0,SaveRState,SaveTState);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}/* if(EPindex == 0) */
|
||||
else
|
||||
{
|
||||
/* Decode and service non control endpoints interrupt */
|
||||
|
||||
/* process related endpoint register */
|
||||
wEPVal = _GetENDPOINT(EPindex);
|
||||
if ((wEPVal & EP_CTR_RX) != 0)
|
||||
{
|
||||
/* clear int flag */
|
||||
_ClearEP_CTR_RX(EPindex);
|
||||
|
||||
/* call OUT service function */
|
||||
(*pEpInt_OUT[EPindex-1])();
|
||||
|
||||
} /* if((wEPVal & EP_CTR_RX) */
|
||||
|
||||
if ((wEPVal & EP_CTR_TX) != 0)
|
||||
{
|
||||
/* clear int flag */
|
||||
_ClearEP_CTR_TX(EPindex);
|
||||
|
||||
/* call IN service function */
|
||||
(*pEpInt_IN[EPindex-1])();
|
||||
} /* if((wEPVal & EP_CTR_TX) != 0) */
|
||||
|
||||
}/* if(EPindex == 0) else */
|
||||
|
||||
}/* while(...) */
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : CTR_HP.
|
||||
* Description : High Priority Endpoint Correct Transfer interrupt's service
|
||||
* routine.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void CTR_HP(void)
|
||||
{
|
||||
uint32_t wEPVal = 0;
|
||||
|
||||
while (((wIstr = _GetISTR()) & ISTR_CTR) != 0)
|
||||
{
|
||||
_SetISTR((uint16_t)CLR_CTR); /* clear CTR flag */
|
||||
/* extract highest priority endpoint number */
|
||||
EPindex = (uint8_t)(wIstr & ISTR_EP_ID);
|
||||
/* process related endpoint register */
|
||||
wEPVal = _GetENDPOINT(EPindex);
|
||||
if ((wEPVal & EP_CTR_RX) != 0)
|
||||
{
|
||||
/* clear int flag */
|
||||
_ClearEP_CTR_RX(EPindex);
|
||||
|
||||
/* call OUT service function */
|
||||
(*pEpInt_OUT[EPindex-1])();
|
||||
|
||||
} /* if((wEPVal & EP_CTR_RX) */
|
||||
else if ((wEPVal & EP_CTR_TX) != 0)
|
||||
{
|
||||
/* clear int flag */
|
||||
_ClearEP_CTR_TX(EPindex);
|
||||
|
||||
/* call IN service function */
|
||||
(*pEpInt_IN[EPindex-1])();
|
||||
|
||||
|
||||
} /* if((wEPVal & EP_CTR_TX) != 0) */
|
||||
|
||||
}/* while(...) */
|
||||
}
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_int.h
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 28-August-2012
|
||||
* @brief Endpoint CTR (Low and High) interrupt's service routines prototypes
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USB_INT_H
|
||||
#define __USB_INT_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void CTR_LP(void);
|
||||
void CTR_HP(void);
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
|
||||
#endif /* __USB_INT_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_lib.h
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 28-August-2012
|
||||
* @brief USB library include files
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USB_LIB_H
|
||||
#define __USB_LIB_H
|
||||
|
||||
#include <pirate.h>
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_type.h"
|
||||
#include "usb_regs.h"
|
||||
#include "usb_def.h"
|
||||
#include "usb_core.h"
|
||||
#include "usb_init.h"
|
||||
#include "usb_sil.h"
|
||||
#include "usb_mem.h"
|
||||
#include "usb_int.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
/* External variables --------------------------------------------------------*/
|
||||
|
||||
#endif /* __USB_LIB_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_mem.c
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 28-August-2012
|
||||
* @brief Utility functions for memory transfers to/from PMA
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_lib.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Extern variables ----------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : UserToPMABufferCopy
|
||||
* Description : Copy a buffer from user memory area to packet memory area (PMA)
|
||||
* Input : - pbUsrBuf: pointer to user memory area.
|
||||
* - wPMABufAddr: address into PMA.
|
||||
* - wNBytes: no. of bytes to be copied.
|
||||
* Output : None.
|
||||
* Return : None .
|
||||
*******************************************************************************/
|
||||
void UserToPMABufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
|
||||
{
|
||||
uint32_t n = (wNBytes + 1) >> 1; /* n = (wNBytes + 1) / 2 */
|
||||
uint32_t i, temp1, temp2;
|
||||
uint16_t *pdwVal;
|
||||
pdwVal = (uint16_t *)(wPMABufAddr * 2 + PMAAddr);
|
||||
for (i = n; i != 0; i--)
|
||||
{
|
||||
temp1 = (uint16_t) * pbUsrBuf;
|
||||
pbUsrBuf++;
|
||||
temp2 = temp1 | (uint16_t) * pbUsrBuf << 8;
|
||||
*pdwVal++ = temp2;
|
||||
pdwVal++;
|
||||
pbUsrBuf++;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : PMAToUserBufferCopy
|
||||
* Description : Copy a buffer from user memory area to packet memory area (PMA)
|
||||
* Input : - pbUsrBuf = pointer to user memory area.
|
||||
* - wPMABufAddr = address into PMA.
|
||||
* - wNBytes = no. of bytes to be copied.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void PMAToUserBufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
|
||||
{
|
||||
uint32_t n = (wNBytes + 1) >> 1;/* /2*/
|
||||
uint32_t i;
|
||||
uint32_t *pdwVal;
|
||||
pdwVal = (uint32_t *)(wPMABufAddr * 2 + PMAAddr);
|
||||
for (i = n; i != 0; i--)
|
||||
{
|
||||
*(uint16_t*)pbUsrBuf++ = *pdwVal++;
|
||||
pbUsrBuf++;
|
||||
}
|
||||
}
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_mem.h
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 28-August-2012
|
||||
* @brief Utility prototypes functions for memory/PMA transfers
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USB_MEM_H
|
||||
#define __USB_MEM_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void UserToPMABufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes);
|
||||
void PMAToUserBufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes);
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
|
||||
#endif /*__USB_MEM_H*/
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,760 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_regs.c
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 28-August-2012
|
||||
* @brief Interface functions to USB cell registers
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_lib.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Extern variables ----------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetCNTR.
|
||||
* Description : Set the CNTR register value.
|
||||
* Input : wRegValue: new register value.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetCNTR(uint16_t wRegValue)
|
||||
{
|
||||
_SetCNTR(wRegValue);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : GetCNTR.
|
||||
* Description : returns the CNTR register value.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : CNTR register Value.
|
||||
*******************************************************************************/
|
||||
uint16_t GetCNTR(void)
|
||||
{
|
||||
return(_GetCNTR());
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetISTR.
|
||||
* Description : Set the ISTR register value.
|
||||
* Input : wRegValue: new register value.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetISTR(uint16_t wRegValue)
|
||||
{
|
||||
_SetISTR(wRegValue);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : GetISTR
|
||||
* Description : Returns the ISTR register value.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : ISTR register Value
|
||||
*******************************************************************************/
|
||||
uint16_t GetISTR(void)
|
||||
{
|
||||
return(_GetISTR());
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : GetFNR
|
||||
* Description : Returns the FNR register value.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : FNR register Value
|
||||
*******************************************************************************/
|
||||
uint16_t GetFNR(void)
|
||||
{
|
||||
return(_GetFNR());
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetDADDR
|
||||
* Description : Set the DADDR register value.
|
||||
* Input : wRegValue: new register value.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetDADDR(uint16_t wRegValue)
|
||||
{
|
||||
_SetDADDR(wRegValue);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : GetDADDR
|
||||
* Description : Returns the DADDR register value.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : DADDR register Value
|
||||
*******************************************************************************/
|
||||
uint16_t GetDADDR(void)
|
||||
{
|
||||
return(_GetDADDR());
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetBTABLE
|
||||
* Description : Set the BTABLE.
|
||||
* Input : wRegValue: New register value.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetBTABLE(uint16_t wRegValue)
|
||||
{
|
||||
_SetBTABLE(wRegValue);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : GetBTABLE.
|
||||
* Description : Returns the BTABLE register value.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : BTABLE address.
|
||||
*******************************************************************************/
|
||||
uint16_t GetBTABLE(void)
|
||||
{
|
||||
return(_GetBTABLE());
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetENDPOINT
|
||||
* Description : Set the Endpoint register value.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wRegValue.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetENDPOINT(uint8_t bEpNum, uint16_t wRegValue)
|
||||
{
|
||||
_SetENDPOINT(bEpNum, wRegValue);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : GetENDPOINT
|
||||
* Description : Return the Endpoint register value.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Endpoint register value.
|
||||
*******************************************************************************/
|
||||
uint16_t GetENDPOINT(uint8_t bEpNum)
|
||||
{
|
||||
return(_GetENDPOINT(bEpNum));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPType
|
||||
* Description : sets the type in the endpoint register.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wType: type definition.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPType(uint8_t bEpNum, uint16_t wType)
|
||||
{
|
||||
_SetEPType(bEpNum, wType);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPType
|
||||
* Description : Returns the endpoint type.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Endpoint Type
|
||||
*******************************************************************************/
|
||||
uint16_t GetEPType(uint8_t bEpNum)
|
||||
{
|
||||
return(_GetEPType(bEpNum));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPTxStatus
|
||||
* Description : Set the status of Tx endpoint.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wState: new state.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPTxStatus(uint8_t bEpNum, uint16_t wState)
|
||||
{
|
||||
_SetEPTxStatus(bEpNum, wState);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPRxStatus
|
||||
* Description : Set the status of Rx endpoint.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wState: new state.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPRxStatus(uint8_t bEpNum, uint16_t wState)
|
||||
{
|
||||
_SetEPRxStatus(bEpNum, wState);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetDouBleBuffEPStall
|
||||
* Description : sets the status for Double Buffer Endpoint to STALL
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* bDir: Endpoint direction.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetDouBleBuffEPStall(uint8_t bEpNum, uint8_t bDir)
|
||||
{
|
||||
uint16_t Endpoint_DTOG_Status;
|
||||
Endpoint_DTOG_Status = GetENDPOINT(bEpNum);
|
||||
if (bDir == EP_DBUF_OUT)
|
||||
{ /* OUT double buffered endpoint */
|
||||
_SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPRX_DTOG1);
|
||||
}
|
||||
else if (bDir == EP_DBUF_IN)
|
||||
{ /* IN double buffered endpoint */
|
||||
_SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPTX_DTOG1);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPTxStatus
|
||||
* Description : Returns the endpoint Tx status.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Endpoint TX Status
|
||||
*******************************************************************************/
|
||||
uint16_t GetEPTxStatus(uint8_t bEpNum)
|
||||
{
|
||||
return(_GetEPTxStatus(bEpNum));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPRxStatus
|
||||
* Description : Returns the endpoint Rx status.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Endpoint RX Status
|
||||
*******************************************************************************/
|
||||
uint16_t GetEPRxStatus(uint8_t bEpNum)
|
||||
{
|
||||
return(_GetEPRxStatus(bEpNum));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPTxValid
|
||||
* Description : Valid the endpoint Tx Status.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPTxValid(uint8_t bEpNum)
|
||||
{
|
||||
_SetEPTxStatus(bEpNum, EP_TX_VALID);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPRxValid
|
||||
* Description : Valid the endpoint Rx Status.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPRxValid(uint8_t bEpNum)
|
||||
{
|
||||
_SetEPRxStatus(bEpNum, EP_RX_VALID);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEP_KIND
|
||||
* Description : Clear the EP_KIND bit.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEP_KIND(uint8_t bEpNum)
|
||||
{
|
||||
_SetEP_KIND(bEpNum);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : ClearEP_KIND
|
||||
* Description : set the EP_KIND bit.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void ClearEP_KIND(uint8_t bEpNum)
|
||||
{
|
||||
_ClearEP_KIND(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : Clear_Status_Out
|
||||
* Description : Clear the Status Out of the related Endpoint
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void Clear_Status_Out(uint8_t bEpNum)
|
||||
{
|
||||
_ClearEP_KIND(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : Set_Status_Out
|
||||
* Description : Set the Status Out of the related Endpoint
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void Set_Status_Out(uint8_t bEpNum)
|
||||
{
|
||||
_SetEP_KIND(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPDoubleBuff
|
||||
* Description : Enable the double buffer feature for the endpoint.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPDoubleBuff(uint8_t bEpNum)
|
||||
{
|
||||
_SetEP_KIND(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : ClearEPDoubleBuff
|
||||
* Description : Disable the double buffer feature for the endpoint.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void ClearEPDoubleBuff(uint8_t bEpNum)
|
||||
{
|
||||
_ClearEP_KIND(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetTxStallStatus
|
||||
* Description : Returns the Stall status of the Tx endpoint.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Tx Stall status.
|
||||
*******************************************************************************/
|
||||
uint16_t GetTxStallStatus(uint8_t bEpNum)
|
||||
{
|
||||
return(_GetTxStallStatus(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetRxStallStatus
|
||||
* Description : Returns the Stall status of the Rx endpoint.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Rx Stall status.
|
||||
*******************************************************************************/
|
||||
uint16_t GetRxStallStatus(uint8_t bEpNum)
|
||||
{
|
||||
return(_GetRxStallStatus(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : ClearEP_CTR_RX
|
||||
* Description : Clear the CTR_RX bit.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void ClearEP_CTR_RX(uint8_t bEpNum)
|
||||
{
|
||||
_ClearEP_CTR_RX(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : ClearEP_CTR_TX
|
||||
* Description : Clear the CTR_TX bit.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void ClearEP_CTR_TX(uint8_t bEpNum)
|
||||
{
|
||||
_ClearEP_CTR_TX(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : ToggleDTOG_RX
|
||||
* Description : Toggle the DTOG_RX bit.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void ToggleDTOG_RX(uint8_t bEpNum)
|
||||
{
|
||||
_ToggleDTOG_RX(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : ToggleDTOG_TX
|
||||
* Description : Toggle the DTOG_TX bit.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void ToggleDTOG_TX(uint8_t bEpNum)
|
||||
{
|
||||
_ToggleDTOG_TX(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : ClearDTOG_RX.
|
||||
* Description : Clear the DTOG_RX bit.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void ClearDTOG_RX(uint8_t bEpNum)
|
||||
{
|
||||
_ClearDTOG_RX(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : ClearDTOG_TX.
|
||||
* Description : Clear the DTOG_TX bit.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void ClearDTOG_TX(uint8_t bEpNum)
|
||||
{
|
||||
_ClearDTOG_TX(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPAddress
|
||||
* Description : Set the endpoint address.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* bAddr: New endpoint address.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPAddress(uint8_t bEpNum, uint8_t bAddr)
|
||||
{
|
||||
_SetEPAddress(bEpNum, bAddr);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPAddress
|
||||
* Description : Get the endpoint address.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Endpoint address.
|
||||
*******************************************************************************/
|
||||
uint8_t GetEPAddress(uint8_t bEpNum)
|
||||
{
|
||||
return(_GetEPAddress(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPTxAddr
|
||||
* Description : Set the endpoint Tx buffer address.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wAddr: new address.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPTxAddr(uint8_t bEpNum, uint16_t wAddr)
|
||||
{
|
||||
_SetEPTxAddr(bEpNum, wAddr);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPRxAddr
|
||||
* Description : Set the endpoint Rx buffer address.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wAddr: new address.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPRxAddr(uint8_t bEpNum, uint16_t wAddr)
|
||||
{
|
||||
_SetEPRxAddr(bEpNum, wAddr);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPTxAddr
|
||||
* Description : Returns the endpoint Tx buffer address.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Rx buffer address.
|
||||
*******************************************************************************/
|
||||
uint16_t GetEPTxAddr(uint8_t bEpNum)
|
||||
{
|
||||
return(_GetEPTxAddr(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPRxAddr.
|
||||
* Description : Returns the endpoint Rx buffer address.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Rx buffer address.
|
||||
*******************************************************************************/
|
||||
uint16_t GetEPRxAddr(uint8_t bEpNum)
|
||||
{
|
||||
return(_GetEPRxAddr(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPTxCount.
|
||||
* Description : Set the Tx count.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wCount: new count value.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPTxCount(uint8_t bEpNum, uint16_t wCount)
|
||||
{
|
||||
_SetEPTxCount(bEpNum, wCount);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPCountRxReg.
|
||||
* Description : Set the Count Rx Register value.
|
||||
* Input : *pdwReg: point to the register.
|
||||
* wCount: the new register value.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPCountRxReg(uint32_t *pdwReg, uint16_t wCount)
|
||||
{
|
||||
_SetEPCountRxReg(dwReg, wCount);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPRxCount
|
||||
* Description : Set the Rx count.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wCount: the new count value.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPRxCount(uint8_t bEpNum, uint16_t wCount)
|
||||
{
|
||||
_SetEPRxCount(bEpNum, wCount);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPTxCount
|
||||
* Description : Get the Tx count.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None
|
||||
* Return : Tx count value.
|
||||
*******************************************************************************/
|
||||
uint16_t GetEPTxCount(uint8_t bEpNum)
|
||||
{
|
||||
return(_GetEPTxCount(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPRxCount
|
||||
* Description : Get the Rx count.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Rx count value.
|
||||
*******************************************************************************/
|
||||
uint16_t GetEPRxCount(uint8_t bEpNum)
|
||||
{
|
||||
return(_GetEPRxCount(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPDblBuffAddr
|
||||
* Description : Set the addresses of the buffer 0 and 1.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wBuf0Addr: new address of buffer 0.
|
||||
* wBuf1Addr: new address of buffer 1.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPDblBuffAddr(uint8_t bEpNum, uint16_t wBuf0Addr, uint16_t wBuf1Addr)
|
||||
{
|
||||
_SetEPDblBuffAddr(bEpNum, wBuf0Addr, wBuf1Addr);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPDblBuf0Addr
|
||||
* Description : Set the Buffer 1 address.
|
||||
* Input : bEpNum: Endpoint Number
|
||||
* wBuf0Addr: new address.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPDblBuf0Addr(uint8_t bEpNum, uint16_t wBuf0Addr)
|
||||
{
|
||||
_SetEPDblBuf0Addr(bEpNum, wBuf0Addr);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPDblBuf1Addr
|
||||
* Description : Set the Buffer 1 address.
|
||||
* Input : bEpNum: Endpoint Number
|
||||
* wBuf1Addr: new address.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPDblBuf1Addr(uint8_t bEpNum, uint16_t wBuf1Addr)
|
||||
{
|
||||
_SetEPDblBuf1Addr(bEpNum, wBuf1Addr);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPDblBuf0Addr
|
||||
* Description : Returns the address of the Buffer 0.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
uint16_t GetEPDblBuf0Addr(uint8_t bEpNum)
|
||||
{
|
||||
return(_GetEPDblBuf0Addr(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPDblBuf1Addr
|
||||
* Description : Returns the address of the Buffer 1.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Address of the Buffer 1.
|
||||
*******************************************************************************/
|
||||
uint16_t GetEPDblBuf1Addr(uint8_t bEpNum)
|
||||
{
|
||||
return(_GetEPDblBuf1Addr(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPDblBuffCount
|
||||
* Description : Set the number of bytes for a double Buffer
|
||||
* endpoint.
|
||||
* Input : bEpNum,bDir, wCount
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPDblBuffCount(uint8_t bEpNum, uint8_t bDir, uint16_t wCount)
|
||||
{
|
||||
_SetEPDblBuffCount(bEpNum, bDir, wCount);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPDblBuf0Count
|
||||
* Description : Set the number of bytes in the buffer 0 of a double Buffer
|
||||
* endpoint.
|
||||
* Input : bEpNum, bDir, wCount
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPDblBuf0Count(uint8_t bEpNum, uint8_t bDir, uint16_t wCount)
|
||||
{
|
||||
_SetEPDblBuf0Count(bEpNum, bDir, wCount);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPDblBuf1Count
|
||||
* Description : Set the number of bytes in the buffer 0 of a double Buffer
|
||||
* endpoint.
|
||||
* Input : bEpNum, bDir, wCount
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPDblBuf1Count(uint8_t bEpNum, uint8_t bDir, uint16_t wCount)
|
||||
{
|
||||
_SetEPDblBuf1Count(bEpNum, bDir, wCount);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPDblBuf0Count
|
||||
* Description : Returns the number of byte received in the buffer 0 of a double
|
||||
* Buffer endpoint.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Endpoint Buffer 0 count
|
||||
*******************************************************************************/
|
||||
uint16_t GetEPDblBuf0Count(uint8_t bEpNum)
|
||||
{
|
||||
return(_GetEPDblBuf0Count(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPDblBuf1Count
|
||||
* Description : Returns the number of data received in the buffer 1 of a double
|
||||
* Buffer endpoint.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Endpoint Buffer 1 count.
|
||||
*******************************************************************************/
|
||||
uint16_t GetEPDblBuf1Count(uint8_t bEpNum)
|
||||
{
|
||||
return(_GetEPDblBuf1Count(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPDblBufDir
|
||||
* Description : gets direction of the double buffered endpoint
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : EP_DBUF_OUT, EP_DBUF_IN,
|
||||
* EP_DBUF_ERR if the endpoint counter not yet programmed.
|
||||
*******************************************************************************/
|
||||
EP_DBUF_DIR GetEPDblBufDir(uint8_t bEpNum)
|
||||
{
|
||||
if ((uint16_t)(*_pEPRxCount(bEpNum) & 0xFC00) != 0)
|
||||
return(EP_DBUF_OUT);
|
||||
else if (((uint16_t)(*_pEPTxCount(bEpNum)) & 0x03FF) != 0)
|
||||
return(EP_DBUF_IN);
|
||||
else
|
||||
return(EP_DBUF_ERR);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : FreeUserBuffer
|
||||
* Description : free buffer used from the application realizing it to the line
|
||||
toggles bit SW_BUF in the double buffered endpoint register
|
||||
* Input : bEpNum, bDir
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void FreeUserBuffer(uint8_t bEpNum, uint8_t bDir)
|
||||
{
|
||||
if (bDir == EP_DBUF_OUT)
|
||||
{ /* OUT double buffered endpoint */
|
||||
_ToggleDTOG_TX(bEpNum);
|
||||
}
|
||||
else if (bDir == EP_DBUF_IN)
|
||||
{ /* IN double buffered endpoint */
|
||||
_ToggleDTOG_RX(bEpNum);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : ToWord
|
||||
* Description : merge two byte in a word.
|
||||
* Input : bh: byte high, bl: bytes low.
|
||||
* Output : None.
|
||||
* Return : resulted word.
|
||||
*******************************************************************************/
|
||||
uint16_t ToWord(uint8_t bh, uint8_t bl)
|
||||
{
|
||||
uint16_t wRet;
|
||||
wRet = (uint16_t)bl | ((uint16_t)bh << 8);
|
||||
return(wRet);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : ByteSwap
|
||||
* Description : Swap two byte in a word.
|
||||
* Input : wSwW: word to Swap.
|
||||
* Output : None.
|
||||
* Return : resulted word.
|
||||
*******************************************************************************/
|
||||
uint16_t ByteSwap(uint16_t wSwW)
|
||||
{
|
||||
uint8_t bTemp;
|
||||
uint16_t wRet;
|
||||
bTemp = (uint8_t)(wSwW & 0xff);
|
||||
wRet = (wSwW >> 8) | ((uint16_t)bTemp << 8);
|
||||
return(wRet);
|
||||
}
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,680 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_regs.h
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 28-August-2012
|
||||
* @brief Interface prototype functions to USB cell registers
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USB_REGS_H
|
||||
#define __USB_REGS_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
typedef enum _EP_DBUF_DIR
|
||||
{
|
||||
/* double buffered endpoint direction */
|
||||
EP_DBUF_ERR,
|
||||
EP_DBUF_OUT,
|
||||
EP_DBUF_IN
|
||||
}EP_DBUF_DIR;
|
||||
|
||||
/* endpoint buffer number */
|
||||
enum EP_BUF_NUM
|
||||
{
|
||||
EP_NOBUF,
|
||||
EP_BUF0,
|
||||
EP_BUF1
|
||||
};
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
#define RegBase (0x40005C00L) /* USB_IP Peripheral Registers base address */
|
||||
#define PMAAddr (0x40006000L) /* USB_IP Packet Memory Area base address */
|
||||
|
||||
/******************************************************************************/
|
||||
/* General registers */
|
||||
/******************************************************************************/
|
||||
|
||||
/* Control register */
|
||||
#define CNTR ((__IO unsigned *)(RegBase + 0x40))
|
||||
/* Interrupt status register */
|
||||
#define ISTR ((__IO unsigned *)(RegBase + 0x44))
|
||||
/* Frame number register */
|
||||
#define FNR ((__IO unsigned *)(RegBase + 0x48))
|
||||
/* Device address register */
|
||||
#define DADDR ((__IO unsigned *)(RegBase + 0x4C))
|
||||
/* Buffer Table address register */
|
||||
#define BTABLE ((__IO unsigned *)(RegBase + 0x50))
|
||||
/******************************************************************************/
|
||||
/* Endpoint registers */
|
||||
/******************************************************************************/
|
||||
#define EP0REG ((__IO unsigned *)(RegBase)) /* endpoint 0 register address */
|
||||
|
||||
/* Endpoint Addresses (w/direction) */
|
||||
#define EP0_OUT ((uint8_t)0x00)
|
||||
#define EP0_IN ((uint8_t)0x80)
|
||||
#define EP1_OUT ((uint8_t)0x01)
|
||||
#define EP1_IN ((uint8_t)0x81)
|
||||
#define EP2_OUT ((uint8_t)0x02)
|
||||
#define EP2_IN ((uint8_t)0x82)
|
||||
#define EP3_OUT ((uint8_t)0x03)
|
||||
#define EP3_IN ((uint8_t)0x83)
|
||||
#define EP4_OUT ((uint8_t)0x04)
|
||||
#define EP4_IN ((uint8_t)0x84)
|
||||
#define EP5_OUT ((uint8_t)0x05)
|
||||
#define EP5_IN ((uint8_t)0x85)
|
||||
#define EP6_OUT ((uint8_t)0x06)
|
||||
#define EP6_IN ((uint8_t)0x86)
|
||||
#define EP7_OUT ((uint8_t)0x07)
|
||||
#define EP7_IN ((uint8_t)0x87)
|
||||
|
||||
/* endpoints enumeration */
|
||||
#define ENDP0 ((uint8_t)0)
|
||||
#define ENDP1 ((uint8_t)1)
|
||||
#define ENDP2 ((uint8_t)2)
|
||||
#define ENDP3 ((uint8_t)3)
|
||||
#define ENDP4 ((uint8_t)4)
|
||||
#define ENDP5 ((uint8_t)5)
|
||||
#define ENDP6 ((uint8_t)6)
|
||||
#define ENDP7 ((uint8_t)7)
|
||||
|
||||
/******************************************************************************/
|
||||
/* ISTR interrupt events */
|
||||
/******************************************************************************/
|
||||
#define ISTR_CTR (0x8000) /* Correct TRansfer (clear-only bit) */
|
||||
#define ISTR_DOVR (0x4000) /* DMA OVeR/underrun (clear-only bit) */
|
||||
#define ISTR_ERR (0x2000) /* ERRor (clear-only bit) */
|
||||
#define ISTR_WKUP (0x1000) /* WaKe UP (clear-only bit) */
|
||||
#define ISTR_SUSP (0x0800) /* SUSPend (clear-only bit) */
|
||||
#define ISTR_RESET (0x0400) /* RESET (clear-only bit) */
|
||||
#define ISTR_SOF (0x0200) /* Start Of Frame (clear-only bit) */
|
||||
#define ISTR_ESOF (0x0100) /* Expected Start Of Frame (clear-only bit) */
|
||||
|
||||
|
||||
#define ISTR_DIR (0x0010) /* DIRection of transaction (read-only bit) */
|
||||
#define ISTR_EP_ID (0x000F) /* EndPoint IDentifier (read-only bit) */
|
||||
|
||||
#define CLR_CTR (~ISTR_CTR) /* clear Correct TRansfer bit */
|
||||
#define CLR_DOVR (~ISTR_DOVR) /* clear DMA OVeR/underrun bit*/
|
||||
#define CLR_ERR (~ISTR_ERR) /* clear ERRor bit */
|
||||
#define CLR_WKUP (~ISTR_WKUP) /* clear WaKe UP bit */
|
||||
#define CLR_SUSP (~ISTR_SUSP) /* clear SUSPend bit */
|
||||
#define CLR_RESET (~ISTR_RESET) /* clear RESET bit */
|
||||
#define CLR_SOF (~ISTR_SOF) /* clear Start Of Frame bit */
|
||||
#define CLR_ESOF (~ISTR_ESOF) /* clear Expected Start Of Frame bit */
|
||||
|
||||
/******************************************************************************/
|
||||
/* CNTR control register bits definitions */
|
||||
/******************************************************************************/
|
||||
#define CNTR_CTRM (0x8000) /* Correct TRansfer Mask */
|
||||
#define CNTR_DOVRM (0x4000) /* DMA OVeR/underrun Mask */
|
||||
#define CNTR_ERRM (0x2000) /* ERRor Mask */
|
||||
#define CNTR_WKUPM (0x1000) /* WaKe UP Mask */
|
||||
#define CNTR_SUSPM (0x0800) /* SUSPend Mask */
|
||||
#define CNTR_RESETM (0x0400) /* RESET Mask */
|
||||
#define CNTR_SOFM (0x0200) /* Start Of Frame Mask */
|
||||
#define CNTR_ESOFM (0x0100) /* Expected Start Of Frame Mask */
|
||||
|
||||
|
||||
#define CNTR_RESUME (0x0010) /* RESUME request */
|
||||
#define CNTR_FSUSP (0x0008) /* Force SUSPend */
|
||||
#define CNTR_LPMODE (0x0004) /* Low-power MODE */
|
||||
#define CNTR_PDWN (0x0002) /* Power DoWN */
|
||||
#define CNTR_FRES (0x0001) /* Force USB RESet */
|
||||
|
||||
/******************************************************************************/
|
||||
/* FNR Frame Number Register bit definitions */
|
||||
/******************************************************************************/
|
||||
#define FNR_RXDP (0x8000) /* status of D+ data line */
|
||||
#define FNR_RXDM (0x4000) /* status of D- data line */
|
||||
#define FNR_LCK (0x2000) /* LoCKed */
|
||||
#define FNR_LSOF (0x1800) /* Lost SOF */
|
||||
#define FNR_FN (0x07FF) /* Frame Number */
|
||||
/******************************************************************************/
|
||||
/* DADDR Device ADDRess bit definitions */
|
||||
/******************************************************************************/
|
||||
#define DADDR_EF (0x80)
|
||||
#define DADDR_ADD (0x7F)
|
||||
/******************************************************************************/
|
||||
/* Endpoint register */
|
||||
/******************************************************************************/
|
||||
/* bit positions */
|
||||
#define EP_CTR_RX (0x8000) /* EndPoint Correct TRansfer RX */
|
||||
#define EP_DTOG_RX (0x4000) /* EndPoint Data TOGGLE RX */
|
||||
#define EPRX_STAT (0x3000) /* EndPoint RX STATus bit field */
|
||||
#define EP_SETUP (0x0800) /* EndPoint SETUP */
|
||||
#define EP_T_FIELD (0x0600) /* EndPoint TYPE */
|
||||
#define EP_KIND (0x0100) /* EndPoint KIND */
|
||||
#define EP_CTR_TX (0x0080) /* EndPoint Correct TRansfer TX */
|
||||
#define EP_DTOG_TX (0x0040) /* EndPoint Data TOGGLE TX */
|
||||
#define EPTX_STAT (0x0030) /* EndPoint TX STATus bit field */
|
||||
#define EPADDR_FIELD (0x000F) /* EndPoint ADDRess FIELD */
|
||||
|
||||
/* EndPoint REGister MASK (no toggle fields) */
|
||||
#define EPREG_MASK (EP_CTR_RX|EP_SETUP|EP_T_FIELD|EP_KIND|EP_CTR_TX|EPADDR_FIELD)
|
||||
|
||||
/* EP_TYPE[1:0] EndPoint TYPE */
|
||||
#define EP_TYPE_MASK (0x0600) /* EndPoint TYPE Mask */
|
||||
#define EP_BULK (0x0000) /* EndPoint BULK */
|
||||
#define EP_CONTROL (0x0200) /* EndPoint CONTROL */
|
||||
#define EP_ISOCHRONOUS (0x0400) /* EndPoint ISOCHRONOUS */
|
||||
#define EP_INTERRUPT (0x0600) /* EndPoint INTERRUPT */
|
||||
#define EP_T_MASK (~EP_T_FIELD & EPREG_MASK)
|
||||
|
||||
|
||||
/* EP_KIND EndPoint KIND */
|
||||
#define EPKIND_MASK (~EP_KIND & EPREG_MASK)
|
||||
|
||||
/* STAT_TX[1:0] STATus for TX transfer */
|
||||
#define EP_TX_DIS (0x0000) /* EndPoint TX DISabled */
|
||||
#define EP_TX_STALL (0x0010) /* EndPoint TX STALLed */
|
||||
#define EP_TX_NAK (0x0020) /* EndPoint TX NAKed */
|
||||
#define EP_TX_VALID (0x0030) /* EndPoint TX VALID */
|
||||
#define EPTX_DTOG1 (0x0010) /* EndPoint TX Data TOGgle bit1 */
|
||||
#define EPTX_DTOG2 (0x0020) /* EndPoint TX Data TOGgle bit2 */
|
||||
#define EPTX_DTOGMASK (EPTX_STAT|EPREG_MASK)
|
||||
|
||||
/* STAT_RX[1:0] STATus for RX transfer */
|
||||
#define EP_RX_DIS (0x0000) /* EndPoint RX DISabled */
|
||||
#define EP_RX_STALL (0x1000) /* EndPoint RX STALLed */
|
||||
#define EP_RX_NAK (0x2000) /* EndPoint RX NAKed */
|
||||
#define EP_RX_VALID (0x3000) /* EndPoint RX VALID */
|
||||
#define EPRX_DTOG1 (0x1000) /* EndPoint RX Data TOGgle bit1 */
|
||||
#define EPRX_DTOG2 (0x2000) /* EndPoint RX Data TOGgle bit1 */
|
||||
#define EPRX_DTOGMASK (EPRX_STAT|EPREG_MASK)
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* SetCNTR */
|
||||
#define _SetCNTR(wRegValue) (*CNTR = (uint16_t)wRegValue)
|
||||
|
||||
/* SetISTR */
|
||||
#define _SetISTR(wRegValue) (*ISTR = (uint16_t)wRegValue)
|
||||
|
||||
/* SetDADDR */
|
||||
#define _SetDADDR(wRegValue) (*DADDR = (uint16_t)wRegValue)
|
||||
|
||||
/* SetBTABLE */
|
||||
#define _SetBTABLE(wRegValue)(*BTABLE = (uint16_t)(wRegValue & 0xFFF8))
|
||||
|
||||
/* GetCNTR */
|
||||
#define _GetCNTR() ((uint16_t) *CNTR)
|
||||
|
||||
/* GetISTR */
|
||||
#define _GetISTR() ((uint16_t) *ISTR)
|
||||
|
||||
/* GetFNR */
|
||||
#define _GetFNR() ((uint16_t) *FNR)
|
||||
|
||||
/* GetDADDR */
|
||||
#define _GetDADDR() ((uint16_t) *DADDR)
|
||||
|
||||
/* GetBTABLE */
|
||||
#define _GetBTABLE() ((uint16_t) *BTABLE)
|
||||
|
||||
/* SetENDPOINT */
|
||||
#define _SetENDPOINT(bEpNum,wRegValue) (*(EP0REG + bEpNum)= \
|
||||
(uint16_t)wRegValue)
|
||||
|
||||
/* GetENDPOINT */
|
||||
#define _GetENDPOINT(bEpNum) ((uint16_t)(*(EP0REG + bEpNum)))
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : SetEPType
|
||||
* Description : sets the type in the endpoint register(bits EP_TYPE[1:0])
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wType
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _SetEPType(bEpNum,wType) (_SetENDPOINT(bEpNum,\
|
||||
((_GetENDPOINT(bEpNum) & EP_T_MASK) | wType )))
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : GetEPType
|
||||
* Description : gets the type in the endpoint register(bits EP_TYPE[1:0])
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Endpoint Type
|
||||
*******************************************************************************/
|
||||
#define _GetEPType(bEpNum) (_GetENDPOINT(bEpNum) & EP_T_FIELD)
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : SetEPTxStatus
|
||||
* Description : sets the status for tx transfer (bits STAT_TX[1:0]).
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wState: new state
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _SetEPTxStatus(bEpNum,wState) {\
|
||||
register uint16_t _wRegVal; \
|
||||
_wRegVal = _GetENDPOINT(bEpNum) & EPTX_DTOGMASK;\
|
||||
/* toggle first bit ? */ \
|
||||
if((EPTX_DTOG1 & wState)!= 0) \
|
||||
_wRegVal ^= EPTX_DTOG1; \
|
||||
/* toggle second bit ? */ \
|
||||
if((EPTX_DTOG2 & wState)!= 0) \
|
||||
_wRegVal ^= EPTX_DTOG2; \
|
||||
_SetENDPOINT(bEpNum, (_wRegVal | EP_CTR_RX|EP_CTR_TX)); \
|
||||
} /* _SetEPTxStatus */
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : SetEPRxStatus
|
||||
* Description : sets the status for rx transfer (bits STAT_TX[1:0])
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wState: new state.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _SetEPRxStatus(bEpNum,wState) {\
|
||||
register uint16_t _wRegVal; \
|
||||
\
|
||||
_wRegVal = _GetENDPOINT(bEpNum) & EPRX_DTOGMASK;\
|
||||
/* toggle first bit ? */ \
|
||||
if((EPRX_DTOG1 & wState)!= 0) \
|
||||
_wRegVal ^= EPRX_DTOG1; \
|
||||
/* toggle second bit ? */ \
|
||||
if((EPRX_DTOG2 & wState)!= 0) \
|
||||
_wRegVal ^= EPRX_DTOG2; \
|
||||
_SetENDPOINT(bEpNum, (_wRegVal | EP_CTR_RX|EP_CTR_TX)); \
|
||||
} /* _SetEPRxStatus */
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : SetEPRxTxStatus
|
||||
* Description : sets the status for rx & tx (bits STAT_TX[1:0] & STAT_RX[1:0])
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wStaterx: new state.
|
||||
* wStatetx: new state.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _SetEPRxTxStatus(bEpNum,wStaterx,wStatetx) {\
|
||||
register uint32_t _wRegVal; \
|
||||
\
|
||||
_wRegVal = _GetENDPOINT(bEpNum) & (EPRX_DTOGMASK |EPTX_STAT) ;\
|
||||
/* toggle first bit ? */ \
|
||||
if((EPRX_DTOG1 & wStaterx)!= 0) \
|
||||
_wRegVal ^= EPRX_DTOG1; \
|
||||
/* toggle second bit ? */ \
|
||||
if((EPRX_DTOG2 & wStaterx)!= 0) \
|
||||
_wRegVal ^= EPRX_DTOG2; \
|
||||
/* toggle first bit ? */ \
|
||||
if((EPTX_DTOG1 & wStatetx)!= 0) \
|
||||
_wRegVal ^= EPTX_DTOG1; \
|
||||
/* toggle second bit ? */ \
|
||||
if((EPTX_DTOG2 & wStatetx)!= 0) \
|
||||
_wRegVal ^= EPTX_DTOG2; \
|
||||
_SetENDPOINT(bEpNum, _wRegVal | EP_CTR_RX|EP_CTR_TX); \
|
||||
} /* _SetEPRxTxStatus */
|
||||
/*******************************************************************************
|
||||
* Macro Name : GetEPTxStatus / GetEPRxStatus
|
||||
* Description : gets the status for tx/rx transfer (bits STAT_TX[1:0]
|
||||
* /STAT_RX[1:0])
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : status .
|
||||
*******************************************************************************/
|
||||
#define _GetEPTxStatus(bEpNum) ((uint16_t)_GetENDPOINT(bEpNum) & EPTX_STAT)
|
||||
|
||||
#define _GetEPRxStatus(bEpNum) ((uint16_t)_GetENDPOINT(bEpNum) & EPRX_STAT)
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : SetEPTxValid / SetEPRxValid
|
||||
* Description : sets directly the VALID tx/rx-status into the enpoint register
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _SetEPTxValid(bEpNum) (_SetEPTxStatus(bEpNum, EP_TX_VALID))
|
||||
|
||||
#define _SetEPRxValid(bEpNum) (_SetEPRxStatus(bEpNum, EP_RX_VALID))
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : GetTxStallStatus / GetRxStallStatus.
|
||||
* Description : checks stall condition in an endpoint.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : TRUE = endpoint in stall condition.
|
||||
*******************************************************************************/
|
||||
#define _GetTxStallStatus(bEpNum) (_GetEPTxStatus(bEpNum) \
|
||||
== EP_TX_STALL)
|
||||
#define _GetRxStallStatus(bEpNum) (_GetEPRxStatus(bEpNum) \
|
||||
== EP_RX_STALL)
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : SetEP_KIND / ClearEP_KIND.
|
||||
* Description : set & clear EP_KIND bit.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _SetEP_KIND(bEpNum) (_SetENDPOINT(bEpNum, \
|
||||
(EP_CTR_RX|EP_CTR_TX|((_GetENDPOINT(bEpNum) | EP_KIND) & EPREG_MASK))))
|
||||
#define _ClearEP_KIND(bEpNum) (_SetENDPOINT(bEpNum, \
|
||||
(EP_CTR_RX|EP_CTR_TX|(_GetENDPOINT(bEpNum) & EPKIND_MASK))))
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : Set_Status_Out / Clear_Status_Out.
|
||||
* Description : Sets/clears directly STATUS_OUT bit in the endpoint register.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _Set_Status_Out(bEpNum) _SetEP_KIND(bEpNum)
|
||||
#define _Clear_Status_Out(bEpNum) _ClearEP_KIND(bEpNum)
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : SetEPDoubleBuff / ClearEPDoubleBuff.
|
||||
* Description : Sets/clears directly EP_KIND bit in the endpoint register.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _SetEPDoubleBuff(bEpNum) _SetEP_KIND(bEpNum)
|
||||
#define _ClearEPDoubleBuff(bEpNum) _ClearEP_KIND(bEpNum)
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : ClearEP_CTR_RX / ClearEP_CTR_TX.
|
||||
* Description : Clears bit CTR_RX / CTR_TX in the endpoint register.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _ClearEP_CTR_RX(bEpNum) (_SetENDPOINT(bEpNum,\
|
||||
_GetENDPOINT(bEpNum) & 0x7FFF & EPREG_MASK))
|
||||
#define _ClearEP_CTR_TX(bEpNum) (_SetENDPOINT(bEpNum,\
|
||||
_GetENDPOINT(bEpNum) & 0xFF7F & EPREG_MASK))
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : ToggleDTOG_RX / ToggleDTOG_TX .
|
||||
* Description : Toggles DTOG_RX / DTOG_TX bit in the endpoint register.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _ToggleDTOG_RX(bEpNum) (_SetENDPOINT(bEpNum, \
|
||||
EP_CTR_RX|EP_CTR_TX|EP_DTOG_RX | (_GetENDPOINT(bEpNum) & EPREG_MASK)))
|
||||
#define _ToggleDTOG_TX(bEpNum) (_SetENDPOINT(bEpNum, \
|
||||
EP_CTR_RX|EP_CTR_TX|EP_DTOG_TX | (_GetENDPOINT(bEpNum) & EPREG_MASK)))
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : ClearDTOG_RX / ClearDTOG_TX.
|
||||
* Description : Clears DTOG_RX / DTOG_TX bit in the endpoint register.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _ClearDTOG_RX(bEpNum) if((_GetENDPOINT(bEpNum) & EP_DTOG_RX) != 0)\
|
||||
_ToggleDTOG_RX(bEpNum)
|
||||
#define _ClearDTOG_TX(bEpNum) if((_GetENDPOINT(bEpNum) & EP_DTOG_TX) != 0)\
|
||||
_ToggleDTOG_TX(bEpNum)
|
||||
/*******************************************************************************
|
||||
* Macro Name : SetEPAddress.
|
||||
* Description : Sets address in an endpoint register.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* bAddr: Address.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _SetEPAddress(bEpNum,bAddr) _SetENDPOINT(bEpNum,\
|
||||
EP_CTR_RX|EP_CTR_TX|(_GetENDPOINT(bEpNum) & EPREG_MASK) | bAddr)
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : GetEPAddress.
|
||||
* Description : Gets address in an endpoint register.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _GetEPAddress(bEpNum) ((uint8_t)(_GetENDPOINT(bEpNum) & EPADDR_FIELD))
|
||||
|
||||
#define _pEPTxAddr(bEpNum) ((uint32_t *)((_GetBTABLE()+bEpNum*8 )*2 + PMAAddr))
|
||||
#define _pEPTxCount(bEpNum) ((uint32_t *)((_GetBTABLE()+bEpNum*8+2)*2 + PMAAddr))
|
||||
#define _pEPRxAddr(bEpNum) ((uint32_t *)((_GetBTABLE()+bEpNum*8+4)*2 + PMAAddr))
|
||||
#define _pEPRxCount(bEpNum) ((uint32_t *)((_GetBTABLE()+bEpNum*8+6)*2 + PMAAddr))
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : SetEPTxAddr / SetEPRxAddr.
|
||||
* Description : sets address of the tx/rx buffer.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wAddr: address to be set (must be word aligned).
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _SetEPTxAddr(bEpNum,wAddr) (*_pEPTxAddr(bEpNum) = ((wAddr >> 1) << 1))
|
||||
#define _SetEPRxAddr(bEpNum,wAddr) (*_pEPRxAddr(bEpNum) = ((wAddr >> 1) << 1))
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : GetEPTxAddr / GetEPRxAddr.
|
||||
* Description : Gets address of the tx/rx buffer.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : address of the buffer.
|
||||
*******************************************************************************/
|
||||
#define _GetEPTxAddr(bEpNum) ((uint16_t)*_pEPTxAddr(bEpNum))
|
||||
#define _GetEPRxAddr(bEpNum) ((uint16_t)*_pEPRxAddr(bEpNum))
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : SetEPCountRxReg.
|
||||
* Description : Sets counter of rx buffer with no. of blocks.
|
||||
* Input : pdwReg: pointer to counter.
|
||||
* wCount: Counter.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _BlocksOf32(dwReg,wCount,wNBlocks) {\
|
||||
wNBlocks = wCount >> 5;\
|
||||
if((wCount & 0x1f) == 0)\
|
||||
wNBlocks--;\
|
||||
*pdwReg = (uint32_t)((wNBlocks << 10) | 0x8000);\
|
||||
}/* _BlocksOf32 */
|
||||
|
||||
#define _BlocksOf2(dwReg,wCount,wNBlocks) {\
|
||||
wNBlocks = wCount >> 1;\
|
||||
if((wCount & 0x1) != 0)\
|
||||
wNBlocks++;\
|
||||
*pdwReg = (uint32_t)(wNBlocks << 10);\
|
||||
}/* _BlocksOf2 */
|
||||
|
||||
#define _SetEPCountRxReg(dwReg,wCount) {\
|
||||
uint16_t wNBlocks;\
|
||||
if(wCount > 62){_BlocksOf32(dwReg,wCount,wNBlocks);}\
|
||||
else {_BlocksOf2(dwReg,wCount,wNBlocks);}\
|
||||
}/* _SetEPCountRxReg */
|
||||
|
||||
|
||||
|
||||
#define _SetEPRxDblBuf0Count(bEpNum,wCount) {\
|
||||
uint32_t *pdwReg = _pEPTxCount(bEpNum); \
|
||||
_SetEPCountRxReg(pdwReg, wCount);\
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Macro Name : SetEPTxCount / SetEPRxCount.
|
||||
* Description : sets counter for the tx/rx buffer.
|
||||
* Input : bEpNum: endpoint number.
|
||||
* wCount: Counter value.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _SetEPTxCount(bEpNum,wCount) (*_pEPTxCount(bEpNum) = wCount)
|
||||
#define _SetEPRxCount(bEpNum,wCount) {\
|
||||
uint32_t *pdwReg = _pEPRxCount(bEpNum); \
|
||||
_SetEPCountRxReg(pdwReg, wCount);\
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Macro Name : GetEPTxCount / GetEPRxCount.
|
||||
* Description : gets counter of the tx buffer.
|
||||
* Input : bEpNum: endpoint number.
|
||||
* Output : None.
|
||||
* Return : Counter value.
|
||||
*******************************************************************************/
|
||||
#define _GetEPTxCount(bEpNum)((uint16_t)(*_pEPTxCount(bEpNum)) & 0x3ff)
|
||||
#define _GetEPRxCount(bEpNum)((uint16_t)(*_pEPRxCount(bEpNum)) & 0x3ff)
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : SetEPDblBuf0Addr / SetEPDblBuf1Addr.
|
||||
* Description : Sets buffer 0/1 address in a double buffer endpoint.
|
||||
* Input : bEpNum: endpoint number.
|
||||
* : wBuf0Addr: buffer 0 address.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _SetEPDblBuf0Addr(bEpNum,wBuf0Addr) {_SetEPTxAddr(bEpNum, wBuf0Addr);}
|
||||
#define _SetEPDblBuf1Addr(bEpNum,wBuf1Addr) {_SetEPRxAddr(bEpNum, wBuf1Addr);}
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : SetEPDblBuffAddr.
|
||||
* Description : Sets addresses in a double buffer endpoint.
|
||||
* Input : bEpNum: endpoint number.
|
||||
* : wBuf0Addr: buffer 0 address.
|
||||
* : wBuf1Addr = buffer 1 address.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _SetEPDblBuffAddr(bEpNum,wBuf0Addr,wBuf1Addr) { \
|
||||
_SetEPDblBuf0Addr(bEpNum, wBuf0Addr);\
|
||||
_SetEPDblBuf1Addr(bEpNum, wBuf1Addr);\
|
||||
} /* _SetEPDblBuffAddr */
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : GetEPDblBuf0Addr / GetEPDblBuf1Addr.
|
||||
* Description : Gets buffer 0/1 address of a double buffer endpoint.
|
||||
* Input : bEpNum: endpoint number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _GetEPDblBuf0Addr(bEpNum) (_GetEPTxAddr(bEpNum))
|
||||
#define _GetEPDblBuf1Addr(bEpNum) (_GetEPRxAddr(bEpNum))
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : SetEPDblBuffCount / SetEPDblBuf0Count / SetEPDblBuf1Count.
|
||||
* Description : Gets buffer 0/1 address of a double buffer endpoint.
|
||||
* Input : bEpNum: endpoint number.
|
||||
* : bDir: endpoint dir EP_DBUF_OUT = OUT
|
||||
* EP_DBUF_IN = IN
|
||||
* : wCount: Counter value
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _SetEPDblBuf0Count(bEpNum, bDir, wCount) { \
|
||||
if(bDir == EP_DBUF_OUT)\
|
||||
/* OUT endpoint */ \
|
||||
{_SetEPRxDblBuf0Count(bEpNum,wCount);} \
|
||||
else if(bDir == EP_DBUF_IN)\
|
||||
/* IN endpoint */ \
|
||||
*_pEPTxCount(bEpNum) = (uint32_t)wCount; \
|
||||
} /* SetEPDblBuf0Count*/
|
||||
|
||||
#define _SetEPDblBuf1Count(bEpNum, bDir, wCount) { \
|
||||
if(bDir == EP_DBUF_OUT)\
|
||||
/* OUT endpoint */ \
|
||||
{_SetEPRxCount(bEpNum,wCount);}\
|
||||
else if(bDir == EP_DBUF_IN)\
|
||||
/* IN endpoint */\
|
||||
*_pEPRxCount(bEpNum) = (uint32_t)wCount; \
|
||||
} /* SetEPDblBuf1Count */
|
||||
|
||||
#define _SetEPDblBuffCount(bEpNum, bDir, wCount) {\
|
||||
_SetEPDblBuf0Count(bEpNum, bDir, wCount); \
|
||||
_SetEPDblBuf1Count(bEpNum, bDir, wCount); \
|
||||
} /* _SetEPDblBuffCount */
|
||||
|
||||
/*******************************************************************************
|
||||
* Macro Name : GetEPDblBuf0Count / GetEPDblBuf1Count.
|
||||
* Description : Gets buffer 0/1 rx/tx counter for double buffering.
|
||||
* Input : bEpNum: endpoint number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
#define _GetEPDblBuf0Count(bEpNum) (_GetEPTxCount(bEpNum))
|
||||
#define _GetEPDblBuf1Count(bEpNum) (_GetEPRxCount(bEpNum))
|
||||
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
extern __IO uint16_t wIstr; /* ISTR register last read value */
|
||||
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void SetCNTR(uint16_t /*wRegValue*/);
|
||||
void SetISTR(uint16_t /*wRegValue*/);
|
||||
void SetDADDR(uint16_t /*wRegValue*/);
|
||||
void SetBTABLE(uint16_t /*wRegValue*/);
|
||||
void SetBTABLE(uint16_t /*wRegValue*/);
|
||||
uint16_t GetCNTR(void);
|
||||
uint16_t GetISTR(void);
|
||||
uint16_t GetFNR(void);
|
||||
uint16_t GetDADDR(void);
|
||||
uint16_t GetBTABLE(void);
|
||||
void SetENDPOINT(uint8_t /*bEpNum*/, uint16_t /*wRegValue*/);
|
||||
uint16_t GetENDPOINT(uint8_t /*bEpNum*/);
|
||||
void SetEPType(uint8_t /*bEpNum*/, uint16_t /*wType*/);
|
||||
uint16_t GetEPType(uint8_t /*bEpNum*/);
|
||||
void SetEPTxStatus(uint8_t /*bEpNum*/, uint16_t /*wState*/);
|
||||
void SetEPRxStatus(uint8_t /*bEpNum*/, uint16_t /*wState*/);
|
||||
void SetDouBleBuffEPStall(uint8_t /*bEpNum*/, uint8_t bDir);
|
||||
uint16_t GetEPTxStatus(uint8_t /*bEpNum*/);
|
||||
uint16_t GetEPRxStatus(uint8_t /*bEpNum*/);
|
||||
void SetEPTxValid(uint8_t /*bEpNum*/);
|
||||
void SetEPRxValid(uint8_t /*bEpNum*/);
|
||||
uint16_t GetTxStallStatus(uint8_t /*bEpNum*/);
|
||||
uint16_t GetRxStallStatus(uint8_t /*bEpNum*/);
|
||||
void SetEP_KIND(uint8_t /*bEpNum*/);
|
||||
void ClearEP_KIND(uint8_t /*bEpNum*/);
|
||||
void Set_Status_Out(uint8_t /*bEpNum*/);
|
||||
void Clear_Status_Out(uint8_t /*bEpNum*/);
|
||||
void SetEPDoubleBuff(uint8_t /*bEpNum*/);
|
||||
void ClearEPDoubleBuff(uint8_t /*bEpNum*/);
|
||||
void ClearEP_CTR_RX(uint8_t /*bEpNum*/);
|
||||
void ClearEP_CTR_TX(uint8_t /*bEpNum*/);
|
||||
void ToggleDTOG_RX(uint8_t /*bEpNum*/);
|
||||
void ToggleDTOG_TX(uint8_t /*bEpNum*/);
|
||||
void ClearDTOG_RX(uint8_t /*bEpNum*/);
|
||||
void ClearDTOG_TX(uint8_t /*bEpNum*/);
|
||||
void SetEPAddress(uint8_t /*bEpNum*/, uint8_t /*bAddr*/);
|
||||
uint8_t GetEPAddress(uint8_t /*bEpNum*/);
|
||||
void SetEPTxAddr(uint8_t /*bEpNum*/, uint16_t /*wAddr*/);
|
||||
void SetEPRxAddr(uint8_t /*bEpNum*/, uint16_t /*wAddr*/);
|
||||
uint16_t GetEPTxAddr(uint8_t /*bEpNum*/);
|
||||
uint16_t GetEPRxAddr(uint8_t /*bEpNum*/);
|
||||
void SetEPCountRxReg(uint32_t * /*pdwReg*/, uint16_t /*wCount*/);
|
||||
void SetEPTxCount(uint8_t /*bEpNum*/, uint16_t /*wCount*/);
|
||||
void SetEPRxCount(uint8_t /*bEpNum*/, uint16_t /*wCount*/);
|
||||
uint16_t GetEPTxCount(uint8_t /*bEpNum*/);
|
||||
uint16_t GetEPRxCount(uint8_t /*bEpNum*/);
|
||||
void SetEPDblBuf0Addr(uint8_t /*bEpNum*/, uint16_t /*wBuf0Addr*/);
|
||||
void SetEPDblBuf1Addr(uint8_t /*bEpNum*/, uint16_t /*wBuf1Addr*/);
|
||||
void SetEPDblBuffAddr(uint8_t /*bEpNum*/, uint16_t /*wBuf0Addr*/, uint16_t /*wBuf1Addr*/);
|
||||
uint16_t GetEPDblBuf0Addr(uint8_t /*bEpNum*/);
|
||||
uint16_t GetEPDblBuf1Addr(uint8_t /*bEpNum*/);
|
||||
void SetEPDblBuffCount(uint8_t /*bEpNum*/, uint8_t /*bDir*/, uint16_t /*wCount*/);
|
||||
void SetEPDblBuf0Count(uint8_t /*bEpNum*/, uint8_t /*bDir*/, uint16_t /*wCount*/);
|
||||
void SetEPDblBuf1Count(uint8_t /*bEpNum*/, uint8_t /*bDir*/, uint16_t /*wCount*/);
|
||||
uint16_t GetEPDblBuf0Count(uint8_t /*bEpNum*/);
|
||||
uint16_t GetEPDblBuf1Count(uint8_t /*bEpNum*/);
|
||||
EP_DBUF_DIR GetEPDblBufDir(uint8_t /*bEpNum*/);
|
||||
void FreeUserBuffer(uint8_t bEpNum/*bEpNum*/, uint8_t bDir);
|
||||
uint16_t ToWord(uint8_t, uint8_t);
|
||||
uint16_t ByteSwap(uint16_t);
|
||||
|
||||
#endif /* __USB_REGS_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,103 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_sil.c
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 28-August-2012
|
||||
* @brief Simplified Interface Layer for Global Initialization and Endpoint
|
||||
* Rea/Write operations.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_lib.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Extern variables ----------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : USB_SIL_Init
|
||||
* Description : Initialize the USB Device IP and the Endpoint 0.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : Status.
|
||||
*******************************************************************************/
|
||||
uint32_t USB_SIL_Init(void)
|
||||
{
|
||||
/* USB interrupts initialization */
|
||||
/* clear pending interrupts */
|
||||
_SetISTR(0);
|
||||
wInterrupt_Mask = IMR_MSK;
|
||||
/* set interrupts mask */
|
||||
_SetCNTR(wInterrupt_Mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : USB_SIL_Write
|
||||
* Description : Write a buffer of data to a selected endpoint.
|
||||
* Input : - bEpAddr: The address of the non control endpoint.
|
||||
* - pBufferPointer: The pointer to the buffer of data to be written
|
||||
* to the endpoint.
|
||||
* - wBufferSize: Number of data to be written (in bytes).
|
||||
* Output : None.
|
||||
* Return : Status.
|
||||
*******************************************************************************/
|
||||
uint32_t USB_SIL_Write(uint8_t bEpAddr, uint8_t* pBufferPointer, uint32_t wBufferSize)
|
||||
{
|
||||
/* Use the memory interface function to write to the selected endpoint */
|
||||
UserToPMABufferCopy(pBufferPointer, GetEPTxAddr(bEpAddr & 0x7F), wBufferSize);
|
||||
|
||||
/* Update the data length in the control register */
|
||||
SetEPTxCount((bEpAddr & 0x7F), wBufferSize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : USB_SIL_Read
|
||||
* Description : Write a buffer of data to a selected endpoint.
|
||||
* Input : - bEpAddr: The address of the non control endpoint.
|
||||
* - pBufferPointer: The pointer to which will be saved the
|
||||
* received data buffer.
|
||||
* Output : None.
|
||||
* Return : Number of received data (in Bytes).
|
||||
*******************************************************************************/
|
||||
uint32_t USB_SIL_Read(uint8_t bEpAddr, uint8_t* pBufferPointer)
|
||||
{
|
||||
uint32_t DataLength = 0;
|
||||
|
||||
/* Get the number of received data on the selected Endpoint */
|
||||
DataLength = GetEPRxCount(bEpAddr & 0x7F);
|
||||
|
||||
/* Use the memory interface function to write to the selected endpoint */
|
||||
PMAToUserBufferCopy(pBufferPointer, GetEPRxAddr(bEpAddr & 0x7F), DataLength);
|
||||
|
||||
/* Return the number of received data */
|
||||
return DataLength;
|
||||
}
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_sil.h
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 28-August-2012
|
||||
* @brief Simplified Interface Layer function prototypes.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USB_SIL_H
|
||||
#define __USB_SIL_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
uint32_t USB_SIL_Init(void);
|
||||
uint32_t USB_SIL_Write(uint8_t bEpAddr, uint8_t* pBufferPointer, uint32_t wBufferSize);
|
||||
uint32_t USB_SIL_Read(uint8_t bEpAddr, uint8_t* pBufferPointer);
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
|
||||
#endif /* __USB_SIL_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_type.h
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 28-August-2012
|
||||
* @brief Type definitions used by the USB Library
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USB_TYPE_H
|
||||
#define __USB_TYPE_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_conf.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FALSE = 0, TRUE = !FALSE
|
||||
}
|
||||
bool;
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
/* External variables --------------------------------------------------------*/
|
||||
|
||||
#endif /* __USB_TYPE_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,489 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file hw_config.c
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 21-January-2013
|
||||
* @brief Hardware Configuration & Setup
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
#include <stm32l1xx.h>
|
||||
#include "core/usb_lib.h"
|
||||
#include "usb_prop.h"
|
||||
#include "usb_desc.h"
|
||||
#include "glue.h"
|
||||
#include "usb_pwr.h"
|
||||
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
ErrorStatus HSEStartUpStatus;
|
||||
static USART_InitTypeDef USART_InitStructure;
|
||||
|
||||
uint8_t USART_Rx_Buffer[USART_RX_DATA_SIZE];
|
||||
uint32_t USART_Rx_ptr_in = 0;
|
||||
uint32_t USART_Rx_ptr_out = 0;
|
||||
uint32_t USART_Rx_length = 0;
|
||||
|
||||
uint8_t USB_Tx_State = 0;
|
||||
static void IntToUnicode (uint32_t value , uint8_t *pbuf , uint8_t len);
|
||||
/* Extern variables ----------------------------------------------------------*/
|
||||
|
||||
extern LINE_CODING linecoding;
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/*******************************************************************************
|
||||
* Function Name : Set_System
|
||||
* Description : Configures Main system clocks & power
|
||||
* Input : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void USB_Init_System(void)
|
||||
{
|
||||
// GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
/*!< At this stage the microcontroller clock setting is already configured,
|
||||
this is done through SystemInit() function which is called from startup
|
||||
file (startup_stm32f10x_xx.s) before to branch to application main.
|
||||
To reconfigure the default setting of SystemInit() function, refer to
|
||||
system_stm32f10x.c file
|
||||
*/
|
||||
|
||||
/* lets us configure the USB pullup */
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
|
||||
|
||||
/*Set PA11,12 as IN - USB_DM,DP*/
|
||||
// note: doing this actually seems to BREAK USB, keep it as default
|
||||
/*
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||
*/
|
||||
|
||||
/*SET PA11,12 for USB: USB_DM,DP*/
|
||||
// also unnecessary in practice
|
||||
/*
|
||||
GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_USB);
|
||||
GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_USB);
|
||||
*/
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Set_USBClock
|
||||
* Description : Configures USB Clock input (48MHz)
|
||||
* Input : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void USB_ClockEna(void)
|
||||
{
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Enter_LowPowerMode
|
||||
* Description : Power-off system clocks and power while entering suspend mode
|
||||
* Input : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void Enter_LowPowerMode(void)
|
||||
{
|
||||
/* Set the device state to suspend */
|
||||
bDeviceState = SUSPENDED;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Leave_LowPowerMode
|
||||
* Description : Restores system clocks and power while exiting suspend mode
|
||||
* Input : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void Leave_LowPowerMode(void)
|
||||
{
|
||||
DEVICE_INFO *pInfo = &Device_Info;
|
||||
|
||||
/* Set the device state to the correct state */
|
||||
if (pInfo->Current_Configuration != 0)
|
||||
{
|
||||
/* Device configured */
|
||||
bDeviceState = CONFIGURED;
|
||||
}
|
||||
else
|
||||
{
|
||||
bDeviceState = ATTACHED;
|
||||
}
|
||||
/*Enable SystemCoreClock*/
|
||||
SystemInit();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : USB_Interrupts_Config
|
||||
* Description : Configures the USB interrupts
|
||||
* Input : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void USB_Interrupts_Config(void)
|
||||
{
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
EXTI_InitTypeDef EXTI_InitStructure;
|
||||
|
||||
/* 2 bit for pre-emption priority, 2 bits for subpriority */
|
||||
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
|
||||
|
||||
/* set up USB low priority interrupt */
|
||||
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
/* Enable the USB Wake-up interrupt */
|
||||
NVIC_InitStructure.NVIC_IRQChannel = USB_FS_WKUP_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
/* Enable USART Interrupt */
|
||||
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
/* Configure the EXTI line 18 connected internally to the USB IP */
|
||||
EXTI_ClearITPendingBit(EXTI_Line18);
|
||||
EXTI_InitStructure.EXTI_Line = EXTI_Line18;
|
||||
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
|
||||
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
|
||||
EXTI_Init(&EXTI_InitStructure);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : USB_Cable_Config
|
||||
* Description : Software Connection/Disconnection of USB Cable
|
||||
* Input : None.
|
||||
* Return : Status
|
||||
*******************************************************************************/
|
||||
void USB_Cable_Config(FunctionalState NewState)
|
||||
{
|
||||
if (NewState == DISABLE) {
|
||||
SYSCFG_USBPuCmd(DISABLE);
|
||||
} else {
|
||||
SYSCFG_USBPuCmd(ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : USART_Config_Default.
|
||||
* Description : configure the EVAL_COM1 with default values.
|
||||
* Input : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void USART_Config_Default(void)
|
||||
{
|
||||
GPIO_InitTypeDef gpio;
|
||||
|
||||
/* EVAL_COM1 default configuration */
|
||||
/* EVAL_COM1 configured as follow:
|
||||
- BaudRate = 115200 baud
|
||||
- Word Length = 8 Bits
|
||||
- One Stop Bit
|
||||
- Parity None
|
||||
- Hardware flow control disabled
|
||||
- Receive and transmit enabled
|
||||
*/
|
||||
USART_InitStructure.USART_BaudRate = 115200;
|
||||
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
||||
USART_InitStructure.USART_StopBits = USART_StopBits_1;
|
||||
USART_InitStructure.USART_Parity = USART_Parity_No;
|
||||
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
||||
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
|
||||
|
||||
/* Turn on USART clock */
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
|
||||
|
||||
/* Set up the USART pins */
|
||||
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
|
||||
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
|
||||
|
||||
/* Configure USART GPIO */
|
||||
gpio.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
|
||||
gpio.GPIO_Mode = GPIO_Mode_AF;
|
||||
gpio.GPIO_OType = GPIO_OType_PP;
|
||||
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
gpio.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_Init(GPIOA, &gpio);
|
||||
|
||||
/* Configure and enable the USART */
|
||||
USART_Init(USART1, &USART_InitStructure);
|
||||
USART_Cmd(USART1, ENABLE);
|
||||
|
||||
/* Enable the USART Receive interrupt */
|
||||
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : USART_Config.
|
||||
* Description : Configure the EVAL_COM1 according to the line coding structure.
|
||||
* Input : None.
|
||||
* Return : Configuration status
|
||||
TRUE : configuration done with success
|
||||
FALSE : configuration aborted.
|
||||
*******************************************************************************/
|
||||
bool USART_Config(void)
|
||||
{
|
||||
|
||||
/* set the Stop bit*/
|
||||
switch (linecoding.format)
|
||||
{
|
||||
case 0:
|
||||
USART_InitStructure.USART_StopBits = USART_StopBits_1;
|
||||
break;
|
||||
case 1:
|
||||
USART_InitStructure.USART_StopBits = USART_StopBits_1_5;
|
||||
break;
|
||||
case 2:
|
||||
USART_InitStructure.USART_StopBits = USART_StopBits_2;
|
||||
break;
|
||||
default :
|
||||
{
|
||||
USART_Config_Default();
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* set the parity bit*/
|
||||
switch (linecoding.paritytype)
|
||||
{
|
||||
case 0:
|
||||
USART_InitStructure.USART_Parity = USART_Parity_No;
|
||||
break;
|
||||
case 1:
|
||||
USART_InitStructure.USART_Parity = USART_Parity_Even;
|
||||
break;
|
||||
case 2:
|
||||
USART_InitStructure.USART_Parity = USART_Parity_Odd;
|
||||
break;
|
||||
default :
|
||||
{
|
||||
USART_Config_Default();
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/*set the data type : only 8bits and 9bits is supported */
|
||||
switch (linecoding.datatype)
|
||||
{
|
||||
case 0x07:
|
||||
/* With this configuration a parity (Even or Odd) should be set */
|
||||
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
||||
break;
|
||||
case 0x08:
|
||||
if (USART_InitStructure.USART_Parity == USART_Parity_No)
|
||||
{
|
||||
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
||||
}
|
||||
else
|
||||
{
|
||||
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
|
||||
}
|
||||
|
||||
break;
|
||||
default :
|
||||
{
|
||||
USART_Config_Default();
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
USART_InitStructure.USART_BaudRate = linecoding.bitrate;
|
||||
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
||||
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
|
||||
|
||||
/* Configure and enable the USART */
|
||||
USART_Init(USART1, &USART_InitStructure);
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : USB_To_USART_Send_Data.
|
||||
* Description : send the received data from USB to the UART 0.
|
||||
* Input : data_buffer: data address.
|
||||
Nb_bytes: number of bytes to send.
|
||||
* Return : none.
|
||||
*******************************************************************************/
|
||||
void USB_To_USART_Send_Data(uint8_t* data_buffer, uint8_t Nb_bytes)
|
||||
{
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < Nb_bytes; i++)
|
||||
{
|
||||
USART_SendData(USART1, *(data_buffer + i));
|
||||
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Handle_USBAsynchXfer.
|
||||
* Description : send data to USB.
|
||||
* Input : None.
|
||||
* Return : none.
|
||||
*******************************************************************************/
|
||||
void Handle_USBAsynchXfer (void)
|
||||
{
|
||||
|
||||
uint16_t USB_Tx_ptr;
|
||||
uint16_t USB_Tx_length;
|
||||
|
||||
if(USB_Tx_State != 1)
|
||||
{
|
||||
if (USART_Rx_ptr_out == USART_RX_DATA_SIZE)
|
||||
{
|
||||
USART_Rx_ptr_out = 0;
|
||||
}
|
||||
|
||||
if(USART_Rx_ptr_out == USART_Rx_ptr_in)
|
||||
{
|
||||
USB_Tx_State = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(USART_Rx_ptr_out > USART_Rx_ptr_in) /* rollback */
|
||||
{
|
||||
USART_Rx_length = USART_RX_DATA_SIZE - USART_Rx_ptr_out;
|
||||
}
|
||||
else
|
||||
{
|
||||
USART_Rx_length = USART_Rx_ptr_in - USART_Rx_ptr_out;
|
||||
}
|
||||
|
||||
if (USART_Rx_length > VIRTUAL_COM_PORT_DATA_SIZE)
|
||||
{
|
||||
USB_Tx_ptr = USART_Rx_ptr_out;
|
||||
USB_Tx_length = VIRTUAL_COM_PORT_DATA_SIZE;
|
||||
|
||||
USART_Rx_ptr_out += VIRTUAL_COM_PORT_DATA_SIZE;
|
||||
USART_Rx_length -= VIRTUAL_COM_PORT_DATA_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
USB_Tx_ptr = USART_Rx_ptr_out;
|
||||
USB_Tx_length = USART_Rx_length;
|
||||
|
||||
USART_Rx_ptr_out += USART_Rx_length;
|
||||
USART_Rx_length = 0;
|
||||
}
|
||||
USB_Tx_State = 1;
|
||||
UserToPMABufferCopy(&USART_Rx_Buffer[USB_Tx_ptr], ENDP1_TXADDR, USB_Tx_length);
|
||||
SetEPTxCount(ENDP1, USB_Tx_length);
|
||||
SetEPTxValid(ENDP1);
|
||||
}
|
||||
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : UART_To_USB_Send_Data.
|
||||
* Description : send the received data from UART 0 to USB.
|
||||
* Input : None.
|
||||
* Return : none.
|
||||
*******************************************************************************/
|
||||
void USART_To_USB_Send_Data(void)
|
||||
{
|
||||
|
||||
if (linecoding.datatype == 7)
|
||||
{
|
||||
USART_Rx_Buffer[USART_Rx_ptr_in] = USART_ReceiveData(USART1) & 0x7F;
|
||||
}
|
||||
else if (linecoding.datatype == 8)
|
||||
{
|
||||
USART_Rx_Buffer[USART_Rx_ptr_in] = USART_ReceiveData(USART1);
|
||||
}
|
||||
|
||||
USART_Rx_ptr_in++;
|
||||
|
||||
/* To avoid buffer overflow */
|
||||
if(USART_Rx_ptr_in == USART_RX_DATA_SIZE)
|
||||
{
|
||||
USART_Rx_ptr_in = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Get_SerialNum.
|
||||
* Description : Create the serial number string descriptor.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void Get_SerialNum(void)
|
||||
{
|
||||
uint32_t Device_Serial0, Device_Serial1, Device_Serial2;
|
||||
|
||||
Device_Serial0 = *(uint32_t*)ID1;
|
||||
Device_Serial1 = *(uint32_t*)ID2;
|
||||
Device_Serial2 = *(uint32_t*)ID3;
|
||||
|
||||
Device_Serial0 += Device_Serial2;
|
||||
|
||||
if (Device_Serial0 != 0)
|
||||
{
|
||||
IntToUnicode (Device_Serial0, &Virtual_Com_Port_StringSerial[2] , 8);
|
||||
IntToUnicode (Device_Serial1, &Virtual_Com_Port_StringSerial[18], 4);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : HexToChar.
|
||||
* Description : Convert Hex 32Bits value into char.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
static void IntToUnicode (uint32_t value , uint8_t *pbuf , uint8_t len)
|
||||
{
|
||||
uint8_t idx = 0;
|
||||
|
||||
for( idx = 0 ; idx < len ; idx ++)
|
||||
{
|
||||
if( ((value >> 28)) < 0xA )
|
||||
{
|
||||
pbuf[ 2* idx] = (value >> 28) + '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
pbuf[2* idx] = (value >> 28) + 'A' - 10;
|
||||
}
|
||||
|
||||
value = value << 4;
|
||||
|
||||
pbuf[ 2* idx + 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file hw_config.h
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 21-January-2013
|
||||
* @brief Hardware Configuration & Setup
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __HW_CONFIG_H
|
||||
#define __HW_CONFIG_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "core/usb_type.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported define -----------------------------------------------------------*/
|
||||
#define MASS_MEMORY_START 0x04002000
|
||||
#define BULK_MAX_PACKET_SIZE 0x00000040
|
||||
|
||||
#define USART_RX_DATA_SIZE 1024
|
||||
|
||||
#define ID1 (0x1FF80050)
|
||||
#define ID2 (0x1FF80054)
|
||||
#define ID3 (0x1FF80064)
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void USB_Init_System(void);
|
||||
void USB_ClockEna(void);
|
||||
|
||||
void Enter_LowPowerMode(void);
|
||||
void Leave_LowPowerMode(void);
|
||||
void USB_Interrupts_Config(void);
|
||||
void USB_Cable_Config (FunctionalState NewState);
|
||||
void USART_Config_Default(void);
|
||||
bool USART_Config(void);
|
||||
void USB_To_USART_Send_Data(uint8_t* data_buffer, uint8_t Nb_bytes);
|
||||
void USART_To_USB_Send_Data(void);
|
||||
void Handle_USBAsynchXfer (void);
|
||||
void Get_SerialNum(void);
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
|
||||
#endif /*__HW_CONFIG_H*/
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,50 @@
|
|||
#include <stm32l1xx.h>
|
||||
#include "glue.h"
|
||||
#include "usb_istr.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : USB_IRQHandler
|
||||
* Description : This function handles USB Low Priority interrupts
|
||||
* requests.
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void USB_LP_IRQHandler(void)
|
||||
{
|
||||
USB_Istr();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : USART1_IRQHandler
|
||||
* Description : This function handles USART1 global interrupt request.
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void USART1_IRQHandler(void)
|
||||
{
|
||||
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
|
||||
{
|
||||
/* Send the received data to the PC Host*/
|
||||
USART_To_USB_Send_Data();
|
||||
}
|
||||
|
||||
/* If overrun condition occurs, clear the ORE flag and recover communication */
|
||||
if (USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET)
|
||||
{
|
||||
(void)USART_ReceiveData(USART1);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : USB_FS_WKUP_IRQHandler
|
||||
* Description : This function handles USB WakeUp interrupt request.
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void USB_FS_WKUP_IRQHandler(void)
|
||||
{
|
||||
EXTI_ClearITPendingBit(EXTI_Line18);
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_desc.c
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 21-January-2013
|
||||
* @brief Descriptors for Virtual Com Port Demo
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "core/usb_lib.h"
|
||||
#include "usb_desc.h"
|
||||
|
||||
/* USB Standard Device Descriptor */
|
||||
const uint8_t Virtual_Com_Port_DeviceDescriptor[] =
|
||||
{
|
||||
0x12, /* bLength */
|
||||
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||
0x00,
|
||||
0x02, /* bcdUSB = 2.00 */
|
||||
0x02, /* bDeviceClass: CDC */
|
||||
0x00, /* bDeviceSubClass */
|
||||
0x00, /* bDeviceProtocol */
|
||||
0x40, /* bMaxPacketSize0 */
|
||||
0xD5,
|
||||
0xBA, /* idVendor = 0xBAD5 */
|
||||
0x81,
|
||||
0xAD, /* idProduct = 0xAD81 */
|
||||
0x00,
|
||||
0x02, /* bcdDevice = 2.00 */
|
||||
1, /* Index of string descriptor describing vendor */
|
||||
2, /* Index of string descriptor describing product */
|
||||
3, /* Index of string descriptor describing the device's serial number */
|
||||
0x01 /* bNumConfigurations */
|
||||
};
|
||||
|
||||
const uint8_t Virtual_Com_Port_ConfigDescriptor[] =
|
||||
{
|
||||
/*Configuration Descriptor*/
|
||||
0x09, /* bLength: Configuration Descriptor size */
|
||||
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
|
||||
VIRTUAL_COM_PORT_SIZ_CONFIG_DESC, /* wTotalLength:no of returned bytes */
|
||||
0x00,
|
||||
0x02, /* bNumInterfaces: 2 interface */
|
||||
0x01, /* bConfigurationValue: Configuration value */
|
||||
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
|
||||
0xC0, /* bmAttributes: self powered */
|
||||
0x32, /* MaxPower 0 mA */
|
||||
/*Interface Descriptor*/
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
|
||||
/* Interface descriptor type */
|
||||
0x00, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints: One endpoints used */
|
||||
0x02, /* bInterfaceClass: Communication Interface Class */
|
||||
0x02, /* bInterfaceSubClass: Abstract Control Model */
|
||||
0x01, /* bInterfaceProtocol: Common AT commands */
|
||||
0x00, /* iInterface: */
|
||||
/*Header Functional Descriptor*/
|
||||
0x05, /* bLength: Endpoint Descriptor size */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x00, /* bDescriptorSubtype: Header Func Desc */
|
||||
0x10, /* bcdCDC: spec release number */
|
||||
0x01,
|
||||
/*Call Management Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x01, /* bDescriptorSubtype: Call Management Func Desc */
|
||||
0x00, /* bmCapabilities: D0+D1 */
|
||||
0x01, /* bDataInterface: 1 */
|
||||
/*ACM Functional Descriptor*/
|
||||
0x04, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
|
||||
0x02, /* bmCapabilities */
|
||||
/*Union Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x06, /* bDescriptorSubtype: Union func desc */
|
||||
0x00, /* bMasterInterface: Communication class interface */
|
||||
0x01, /* bSlaveInterface0: Data Class Interface */
|
||||
/*Endpoint 2 Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
0x82, /* bEndpointAddress: (IN2) */
|
||||
0x03, /* bmAttributes: Interrupt */
|
||||
VIRTUAL_COM_PORT_INT_SIZE, /* wMaxPacketSize: */
|
||||
0x00,
|
||||
0xFF, /* bInterval: */
|
||||
/*Data class interface descriptor*/
|
||||
0x09, /* bLength: Endpoint Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
|
||||
0x01, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x02, /* bNumEndpoints: Two endpoints used */
|
||||
0x0A, /* bInterfaceClass: CDC */
|
||||
0x00, /* bInterfaceSubClass: */
|
||||
0x00, /* bInterfaceProtocol: */
|
||||
0x00, /* iInterface: */
|
||||
/*Endpoint 3 Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
0x03, /* bEndpointAddress: (OUT3) */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
VIRTUAL_COM_PORT_DATA_SIZE, /* wMaxPacketSize: */
|
||||
0x00,
|
||||
0x00, /* bInterval: ignore for Bulk transfer */
|
||||
/*Endpoint 1 Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
0x81, /* bEndpointAddress: (IN1) */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
VIRTUAL_COM_PORT_DATA_SIZE, /* wMaxPacketSize: */
|
||||
0x00,
|
||||
0x00 /* bInterval */
|
||||
};
|
||||
|
||||
/* USB String Descriptors */
|
||||
const uint8_t Virtual_Com_Port_StringLangID[VIRTUAL_COM_PORT_SIZ_STRING_LANGID] =
|
||||
{
|
||||
VIRTUAL_COM_PORT_SIZ_STRING_LANGID,
|
||||
USB_STRING_DESCRIPTOR_TYPE,
|
||||
0x09,
|
||||
0x04 /* LangID = 0x0409: U.S. English */
|
||||
};
|
||||
|
||||
const uint8_t Virtual_Com_Port_StringVendor[VIRTUAL_COM_PORT_SIZ_STRING_VENDOR] =
|
||||
{
|
||||
VIRTUAL_COM_PORT_SIZ_STRING_VENDOR, /* Size of Vendor string */
|
||||
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType*/
|
||||
/* Manufacturer: "STMicroelectronics" */
|
||||
't', 0, 'r', 0, 'u', 0, 'e', 0, 'C', 0, 'o', 0, 'n', 0, 't', 0,
|
||||
'r', 0, 'o', 0, 'l', 0,
|
||||
};
|
||||
|
||||
const uint8_t Virtual_Com_Port_StringProduct[VIRTUAL_COM_PORT_SIZ_STRING_PRODUCT] =
|
||||
{
|
||||
VIRTUAL_COM_PORT_SIZ_STRING_PRODUCT, /* bLength */
|
||||
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||
/* Product name: "STM32 Virtual COM Port" */
|
||||
'W', 0, 'P', 0, ' ', 0, 'D', 0, 'C', 0, '2', 0, '2', 0, ' ', 0,
|
||||
'V', 0, 'i', 0, 'r', 0, 't', 0, 'u', 0, 'a', 0, 'l', 0, ' ', 0,
|
||||
'S', 0, 'e', 0, 'r', 0, 'i', 0, 'a', 0, 'l', 0, ' ', 0,
|
||||
'P', 0, 'o', 0, 'r', 0, 't', 0,
|
||||
};
|
||||
|
||||
uint8_t Virtual_Com_Port_StringSerial[VIRTUAL_COM_PORT_SIZ_STRING_SERIAL] =
|
||||
{
|
||||
VIRTUAL_COM_PORT_SIZ_STRING_SERIAL, /* bLength */
|
||||
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||
'0', 0, '0', 0, '0', 0, '1', 0,
|
||||
};
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_desc.h
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 21-January-2013
|
||||
* @brief Descriptor Header for Virtual COM Port Device
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USB_DESC_H
|
||||
#define __USB_DESC_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported define -----------------------------------------------------------*/
|
||||
#define USB_DEVICE_DESCRIPTOR_TYPE 0x01
|
||||
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 0x02
|
||||
#define USB_STRING_DESCRIPTOR_TYPE 0x03
|
||||
#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04
|
||||
#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05
|
||||
|
||||
#define VIRTUAL_COM_PORT_DATA_SIZE 64
|
||||
#define VIRTUAL_COM_PORT_INT_SIZE 8
|
||||
|
||||
#define VIRTUAL_COM_PORT_SIZ_DEVICE_DESC 18
|
||||
#define VIRTUAL_COM_PORT_SIZ_CONFIG_DESC 67
|
||||
#define VIRTUAL_COM_PORT_SIZ_STRING_LANGID 4
|
||||
#define VIRTUAL_COM_PORT_SIZ_STRING_VENDOR 24
|
||||
#define VIRTUAL_COM_PORT_SIZ_STRING_PRODUCT 56
|
||||
#define VIRTUAL_COM_PORT_SIZ_STRING_SERIAL 26
|
||||
|
||||
#define STANDARD_ENDPOINT_DESC_SIZE 0x09
|
||||
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
extern const uint8_t Virtual_Com_Port_DeviceDescriptor[VIRTUAL_COM_PORT_SIZ_DEVICE_DESC];
|
||||
extern const uint8_t Virtual_Com_Port_ConfigDescriptor[VIRTUAL_COM_PORT_SIZ_CONFIG_DESC];
|
||||
|
||||
extern const uint8_t Virtual_Com_Port_StringLangID[VIRTUAL_COM_PORT_SIZ_STRING_LANGID];
|
||||
extern const uint8_t Virtual_Com_Port_StringVendor[VIRTUAL_COM_PORT_SIZ_STRING_VENDOR];
|
||||
extern const uint8_t Virtual_Com_Port_StringProduct[VIRTUAL_COM_PORT_SIZ_STRING_PRODUCT];
|
||||
extern uint8_t Virtual_Com_Port_StringSerial[VIRTUAL_COM_PORT_SIZ_STRING_SERIAL];
|
||||
|
||||
#endif /* __USB_DESC_H */
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,144 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_endp.c
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 21-January-2013
|
||||
* @brief Endpoint routines
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "core/usb_lib.h"
|
||||
#include "usb_desc.h"
|
||||
#include "core/usb_mem.h"
|
||||
#include "usb_istr.h"
|
||||
#include "usb_pwr.h"
|
||||
#include "glue.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
/* Interval between sending IN packets in frame number (1 frame = 1ms) */
|
||||
#define VCOMPORT_IN_FRAME_INTERVAL 5
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
uint8_t USB_Rx_Buffer[VIRTUAL_COM_PORT_DATA_SIZE];
|
||||
extern uint8_t USART_Rx_Buffer[];
|
||||
extern uint32_t USART_Rx_ptr_out;
|
||||
extern uint32_t USART_Rx_length;
|
||||
extern uint8_t USB_Tx_State;
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : EP1_IN_Callback
|
||||
* Description :
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void EP1_IN_Callback (void)
|
||||
{
|
||||
uint16_t USB_Tx_ptr;
|
||||
uint16_t USB_Tx_length;
|
||||
|
||||
if (USB_Tx_State == 1)
|
||||
{
|
||||
if (USART_Rx_length == 0)
|
||||
{
|
||||
USB_Tx_State = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (USART_Rx_length > VIRTUAL_COM_PORT_DATA_SIZE){
|
||||
USB_Tx_ptr = USART_Rx_ptr_out;
|
||||
USB_Tx_length = VIRTUAL_COM_PORT_DATA_SIZE;
|
||||
|
||||
USART_Rx_ptr_out += VIRTUAL_COM_PORT_DATA_SIZE;
|
||||
USART_Rx_length -= VIRTUAL_COM_PORT_DATA_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
USB_Tx_ptr = USART_Rx_ptr_out;
|
||||
USB_Tx_length = USART_Rx_length;
|
||||
|
||||
USART_Rx_ptr_out += USART_Rx_length;
|
||||
USART_Rx_length = 0;
|
||||
}
|
||||
UserToPMABufferCopy(&USART_Rx_Buffer[USB_Tx_ptr], ENDP1_TXADDR, USB_Tx_length);
|
||||
SetEPTxCount(ENDP1, USB_Tx_length);
|
||||
SetEPTxValid(ENDP1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : EP3_OUT_Callback
|
||||
* Description :
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void EP3_OUT_Callback(void)
|
||||
{
|
||||
uint16_t USB_Rx_Cnt;
|
||||
|
||||
/* Get the received data buffer and update the counter */
|
||||
USB_Rx_Cnt = USB_SIL_Read(EP3_OUT, USB_Rx_Buffer);
|
||||
|
||||
/* USB data will be immediately processed, this allow next USB traffic being
|
||||
NAKed till the end of the USART Xfer */
|
||||
|
||||
USB_To_USART_Send_Data(USB_Rx_Buffer, USB_Rx_Cnt);
|
||||
|
||||
/* Enable the receive of data on EP3 */
|
||||
SetEPRxValid(ENDP3);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SOF_Callback / INTR_SOFINTR_Callback
|
||||
* Description :
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SOF_Callback(void)
|
||||
{
|
||||
static uint32_t FrameCount = 0;
|
||||
|
||||
if(bDeviceState == CONFIGURED)
|
||||
{
|
||||
if (FrameCount++ == VCOMPORT_IN_FRAME_INTERVAL)
|
||||
{
|
||||
/* Reset the frame counter */
|
||||
FrameCount = 0;
|
||||
|
||||
/* Check the data to be sent through IN pipe */
|
||||
Handle_USBAsynchXfer();
|
||||
}
|
||||
}
|
||||
}
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_istr.c
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 21-January-2013
|
||||
* @brief ISTR events interrupt service routines
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "core/usb_lib.h"
|
||||
#include "usb_prop.h"
|
||||
#include "usb_pwr.h"
|
||||
#include "usb_istr.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
__IO uint16_t wIstr; /* ISTR register last read value */
|
||||
__IO uint8_t bIntPackSOF = 0; /* SOFs received between 2 consecutive packets */
|
||||
__IO uint32_t esof_counter =0; /* expected SOF counter */
|
||||
__IO uint32_t wCNTR=0;
|
||||
|
||||
/* Extern variables ----------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/* function pointers to non-control endpoints service routines */
|
||||
void (*pEpInt_IN[7])(void) =
|
||||
{
|
||||
EP1_IN_Callback,
|
||||
EP2_IN_Callback,
|
||||
EP3_IN_Callback,
|
||||
EP4_IN_Callback,
|
||||
EP5_IN_Callback,
|
||||
EP6_IN_Callback,
|
||||
EP7_IN_Callback,
|
||||
};
|
||||
|
||||
void (*pEpInt_OUT[7])(void) =
|
||||
{
|
||||
EP1_OUT_Callback,
|
||||
EP2_OUT_Callback,
|
||||
EP3_OUT_Callback,
|
||||
EP4_OUT_Callback,
|
||||
EP5_OUT_Callback,
|
||||
EP6_OUT_Callback,
|
||||
EP7_OUT_Callback,
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : USB_Istr
|
||||
* Description : ISTR events interrupt service routine
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void USB_Istr(void)
|
||||
{
|
||||
#if (IMR_MSK & ISTR_ESOF)
|
||||
uint32_t i=0;
|
||||
__IO uint32_t EP[8];
|
||||
#endif
|
||||
|
||||
wIstr = _GetISTR();
|
||||
|
||||
#if (IMR_MSK & ISTR_SOF)
|
||||
if (wIstr & ISTR_SOF & wInterrupt_Mask)
|
||||
{
|
||||
_SetISTR((uint16_t)CLR_SOF);
|
||||
bIntPackSOF++;
|
||||
|
||||
#ifdef SOF_CALLBACK
|
||||
SOF_Callback();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
|
||||
|
||||
#if (IMR_MSK & ISTR_CTR)
|
||||
if (wIstr & ISTR_CTR & wInterrupt_Mask)
|
||||
{
|
||||
/* servicing of the endpoint correct transfer interrupt */
|
||||
/* clear of the CTR flag into the sub */
|
||||
CTR_LP();
|
||||
#ifdef CTR_CALLBACK
|
||||
CTR_Callback();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
|
||||
#if (IMR_MSK & ISTR_RESET)
|
||||
if (wIstr & ISTR_RESET & wInterrupt_Mask)
|
||||
{
|
||||
_SetISTR((uint16_t)CLR_RESET);
|
||||
Device_Property.Reset();
|
||||
#ifdef RESET_CALLBACK
|
||||
RESET_Callback();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
|
||||
#if (IMR_MSK & ISTR_DOVR)
|
||||
if (wIstr & ISTR_DOVR & wInterrupt_Mask)
|
||||
{
|
||||
_SetISTR((uint16_t)CLR_DOVR);
|
||||
#ifdef DOVR_CALLBACK
|
||||
DOVR_Callback();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
|
||||
#if (IMR_MSK & ISTR_ERR)
|
||||
if (wIstr & ISTR_ERR & wInterrupt_Mask)
|
||||
{
|
||||
_SetISTR((uint16_t)CLR_ERR);
|
||||
#ifdef ERR_CALLBACK
|
||||
ERR_Callback();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
|
||||
#if (IMR_MSK & ISTR_WKUP)
|
||||
if (wIstr & ISTR_WKUP & wInterrupt_Mask)
|
||||
{
|
||||
_SetISTR((uint16_t)CLR_WKUP);
|
||||
Resume(RESUME_EXTERNAL);
|
||||
#ifdef WKUP_CALLBACK
|
||||
WKUP_Callback();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
|
||||
#if (IMR_MSK & ISTR_SUSP)
|
||||
if (wIstr & ISTR_SUSP & wInterrupt_Mask)
|
||||
{
|
||||
|
||||
/* check if SUSPEND is possible */
|
||||
if (fSuspendEnabled)
|
||||
{
|
||||
Suspend();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if not possible then resume after xx ms */
|
||||
Resume(RESUME_LATER);
|
||||
}
|
||||
/* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
|
||||
_SetISTR((uint16_t)CLR_SUSP);
|
||||
#ifdef SUSP_CALLBACK
|
||||
SUSP_Callback();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
|
||||
|
||||
#if (IMR_MSK & ISTR_ESOF)
|
||||
if (wIstr & ISTR_ESOF & wInterrupt_Mask)
|
||||
{
|
||||
/* clear ESOF flag in ISTR */
|
||||
_SetISTR((uint16_t)CLR_ESOF);
|
||||
|
||||
if ((_GetFNR()&FNR_RXDP)!=0)
|
||||
{
|
||||
/* increment ESOF counter */
|
||||
esof_counter ++;
|
||||
|
||||
/* test if we enter in ESOF more than 3 times with FSUSP =0 and RXDP =1=>> possible missing SUSP flag*/
|
||||
if ((esof_counter >3)&&((_GetCNTR()&CNTR_FSUSP)==0))
|
||||
{
|
||||
/* this a sequence to apply a force RESET*/
|
||||
|
||||
/*Store CNTR value */
|
||||
wCNTR = _GetCNTR();
|
||||
|
||||
/*Store endpoints registers status */
|
||||
for (i=0;i<8;i++) EP[i] = _GetENDPOINT(i);
|
||||
|
||||
/*apply FRES */
|
||||
wCNTR|=CNTR_FRES;
|
||||
_SetCNTR(wCNTR);
|
||||
|
||||
/*clear FRES*/
|
||||
wCNTR&=~CNTR_FRES;
|
||||
_SetCNTR(wCNTR);
|
||||
|
||||
/*poll for RESET flag in ISTR*/
|
||||
while((_GetISTR()&ISTR_RESET) == 0);
|
||||
|
||||
/* clear RESET flag in ISTR */
|
||||
_SetISTR((uint16_t)CLR_RESET);
|
||||
|
||||
/*restore Enpoints*/
|
||||
for (i=0;i<8;i++)
|
||||
_SetENDPOINT(i, EP[i]);
|
||||
|
||||
esof_counter = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
esof_counter = 0;
|
||||
}
|
||||
|
||||
/* resume handling timing is made with ESOFs */
|
||||
Resume(RESUME_ESOF); /* request without change of the machine state */
|
||||
|
||||
#ifdef ESOF_CALLBACK
|
||||
ESOF_Callback();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
} /* USB_Istr */
|
||||
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_istr.h
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 21-January-2013
|
||||
* @brief This file includes the peripherals header files in the user application.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USB_ISTR_H
|
||||
#define __USB_ISTR_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_conf.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
void USB_Istr(void);
|
||||
|
||||
/* function prototypes Automatically built defining related macros */
|
||||
|
||||
void EP1_IN_Callback(void);
|
||||
void EP2_IN_Callback(void);
|
||||
void EP3_IN_Callback(void);
|
||||
void EP4_IN_Callback(void);
|
||||
void EP5_IN_Callback(void);
|
||||
void EP6_IN_Callback(void);
|
||||
void EP7_IN_Callback(void);
|
||||
|
||||
void EP1_OUT_Callback(void);
|
||||
void EP2_OUT_Callback(void);
|
||||
void EP3_OUT_Callback(void);
|
||||
void EP4_OUT_Callback(void);
|
||||
void EP5_OUT_Callback(void);
|
||||
void EP6_OUT_Callback(void);
|
||||
void EP7_OUT_Callback(void);
|
||||
|
||||
#ifdef CTR_CALLBACK
|
||||
void CTR_Callback(void);
|
||||
#endif
|
||||
|
||||
#ifdef DOVR_CALLBACK
|
||||
void DOVR_Callback(void);
|
||||
#endif
|
||||
|
||||
#ifdef ERR_CALLBACK
|
||||
void ERR_Callback(void);
|
||||
#endif
|
||||
|
||||
#ifdef WKUP_CALLBACK
|
||||
void WKUP_Callback(void);
|
||||
#endif
|
||||
|
||||
#ifdef SUSP_CALLBACK
|
||||
void SUSP_Callback(void);
|
||||
#endif
|
||||
|
||||
#ifdef RESET_CALLBACK
|
||||
void RESET_Callback(void);
|
||||
#endif
|
||||
|
||||
#ifdef SOF_CALLBACK
|
||||
void SOF_Callback(void);
|
||||
#endif
|
||||
|
||||
#ifdef ESOF_CALLBACK
|
||||
void ESOF_Callback(void);
|
||||
#endif
|
||||
#endif /*__USB_ISTR_H*/
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,418 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_prop.c
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 21-January-2013
|
||||
* @brief All processing related to Virtual Com Port Demo
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "core/usb_lib.h"
|
||||
#include "usb_conf.h"
|
||||
#include "usb_prop.h"
|
||||
#include "usb_desc.h"
|
||||
#include "usb_pwr.h"
|
||||
#include "glue.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
uint8_t Request = 0;
|
||||
|
||||
LINE_CODING linecoding =
|
||||
{
|
||||
115200, /* baud rate*/
|
||||
0x00, /* stop bits-1*/
|
||||
0x00, /* parity - none*/
|
||||
0x08 /* no. of bits 8*/
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Structures initializations */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
DEVICE Device_Table =
|
||||
{
|
||||
EP_NUM,
|
||||
1
|
||||
};
|
||||
|
||||
DEVICE_PROP Device_Property =
|
||||
{
|
||||
Virtual_Com_Port_init,
|
||||
Virtual_Com_Port_Reset,
|
||||
Virtual_Com_Port_Status_In,
|
||||
Virtual_Com_Port_Status_Out,
|
||||
Virtual_Com_Port_Data_Setup,
|
||||
Virtual_Com_Port_NoData_Setup,
|
||||
Virtual_Com_Port_Get_Interface_Setting,
|
||||
Virtual_Com_Port_GetDeviceDescriptor,
|
||||
Virtual_Com_Port_GetConfigDescriptor,
|
||||
Virtual_Com_Port_GetStringDescriptor,
|
||||
0,
|
||||
0x40 /*MAX PACKET SIZE*/
|
||||
};
|
||||
|
||||
USER_STANDARD_REQUESTS User_Standard_Requests =
|
||||
{
|
||||
Virtual_Com_Port_GetConfiguration,
|
||||
Virtual_Com_Port_SetConfiguration,
|
||||
Virtual_Com_Port_GetInterface,
|
||||
Virtual_Com_Port_SetInterface,
|
||||
Virtual_Com_Port_GetStatus,
|
||||
Virtual_Com_Port_ClearFeature,
|
||||
Virtual_Com_Port_SetEndPointFeature,
|
||||
Virtual_Com_Port_SetDeviceFeature,
|
||||
Virtual_Com_Port_SetDeviceAddress
|
||||
};
|
||||
|
||||
ONE_DESCRIPTOR Device_Descriptor =
|
||||
{
|
||||
(uint8_t*)Virtual_Com_Port_DeviceDescriptor,
|
||||
VIRTUAL_COM_PORT_SIZ_DEVICE_DESC
|
||||
};
|
||||
|
||||
ONE_DESCRIPTOR Config_Descriptor =
|
||||
{
|
||||
(uint8_t*)Virtual_Com_Port_ConfigDescriptor,
|
||||
VIRTUAL_COM_PORT_SIZ_CONFIG_DESC
|
||||
};
|
||||
|
||||
ONE_DESCRIPTOR String_Descriptor[4] =
|
||||
{
|
||||
{(uint8_t*)Virtual_Com_Port_StringLangID, VIRTUAL_COM_PORT_SIZ_STRING_LANGID},
|
||||
{(uint8_t*)Virtual_Com_Port_StringVendor, VIRTUAL_COM_PORT_SIZ_STRING_VENDOR},
|
||||
{(uint8_t*)Virtual_Com_Port_StringProduct, VIRTUAL_COM_PORT_SIZ_STRING_PRODUCT},
|
||||
{(uint8_t*)Virtual_Com_Port_StringSerial, VIRTUAL_COM_PORT_SIZ_STRING_SERIAL}
|
||||
};
|
||||
|
||||
/* Extern variables ----------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Extern function prototypes ------------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/*******************************************************************************
|
||||
* Function Name : Virtual_Com_Port_init.
|
||||
* Description : Virtual COM Port Mouse init routine.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void Virtual_Com_Port_init(void)
|
||||
{
|
||||
|
||||
/* Update the serial number string descriptor with the data from the unique
|
||||
ID*/
|
||||
Get_SerialNum();
|
||||
|
||||
pInformation->Current_Configuration = 0;
|
||||
|
||||
/* Connect the device */
|
||||
PowerOn();
|
||||
|
||||
/* Perform basic device initialization operations */
|
||||
USB_SIL_Init();
|
||||
|
||||
/* configure the USART to the default settings */
|
||||
USART_Config_Default();
|
||||
|
||||
bDeviceState = UNCONNECTED;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Virtual_Com_Port_Reset
|
||||
* Description : Virtual_Com_Port reset routine
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void Virtual_Com_Port_Reset(void)
|
||||
{
|
||||
/* Set Virtual_Com_Port DEVICE as not configured */
|
||||
pInformation->Current_Configuration = 0;
|
||||
|
||||
/* Current Feature initialization */
|
||||
pInformation->Current_Feature = Virtual_Com_Port_ConfigDescriptor[7];
|
||||
|
||||
/* Set Virtual_Com_Port DEVICE with the default Interface*/
|
||||
pInformation->Current_Interface = 0;
|
||||
|
||||
SetBTABLE(BTABLE_ADDRESS);
|
||||
|
||||
/* Initialize Endpoint 0 */
|
||||
SetEPType(ENDP0, EP_CONTROL);
|
||||
SetEPTxStatus(ENDP0, EP_TX_STALL);
|
||||
SetEPRxAddr(ENDP0, ENDP0_RXADDR);
|
||||
SetEPTxAddr(ENDP0, ENDP0_TXADDR);
|
||||
Clear_Status_Out(ENDP0);
|
||||
SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
|
||||
SetEPRxValid(ENDP0);
|
||||
|
||||
/* Initialize Endpoint 1 */
|
||||
SetEPType(ENDP1, EP_BULK);
|
||||
SetEPTxAddr(ENDP1, ENDP1_TXADDR);
|
||||
SetEPTxStatus(ENDP1, EP_TX_NAK);
|
||||
SetEPRxStatus(ENDP1, EP_RX_DIS);
|
||||
|
||||
/* Initialize Endpoint 2 */
|
||||
SetEPType(ENDP2, EP_INTERRUPT);
|
||||
SetEPTxAddr(ENDP2, ENDP2_TXADDR);
|
||||
SetEPRxStatus(ENDP2, EP_RX_DIS);
|
||||
SetEPTxStatus(ENDP2, EP_TX_NAK);
|
||||
|
||||
/* Initialize Endpoint 3 */
|
||||
SetEPType(ENDP3, EP_BULK);
|
||||
SetEPRxAddr(ENDP3, ENDP3_RXADDR);
|
||||
SetEPRxCount(ENDP3, VIRTUAL_COM_PORT_DATA_SIZE);
|
||||
SetEPRxStatus(ENDP3, EP_RX_VALID);
|
||||
SetEPTxStatus(ENDP3, EP_TX_DIS);
|
||||
|
||||
/* Set this device to response on default address */
|
||||
SetDeviceAddress(0);
|
||||
|
||||
bDeviceState = ATTACHED;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Virtual_Com_Port_SetConfiguration.
|
||||
* Description : Update the device state to configured.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void Virtual_Com_Port_SetConfiguration(void)
|
||||
{
|
||||
DEVICE_INFO *pInfo = &Device_Info;
|
||||
|
||||
if (pInfo->Current_Configuration != 0)
|
||||
{
|
||||
/* Device configured */
|
||||
bDeviceState = CONFIGURED;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Virtual_Com_Port_SetConfiguration.
|
||||
* Description : Update the device state to addressed.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void Virtual_Com_Port_SetDeviceAddress (void)
|
||||
{
|
||||
bDeviceState = ADDRESSED;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Virtual_Com_Port_Status_In.
|
||||
* Description : Virtual COM Port Status In Routine.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void Virtual_Com_Port_Status_In(void)
|
||||
{
|
||||
if (Request == SET_LINE_CODING)
|
||||
{
|
||||
USART_Config();
|
||||
Request = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Virtual_Com_Port_Status_Out
|
||||
* Description : Virtual COM Port Status OUT Routine.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void Virtual_Com_Port_Status_Out(void)
|
||||
{}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Virtual_Com_Port_Data_Setup
|
||||
* Description : handle the data class specific requests
|
||||
* Input : Request Nb.
|
||||
* Output : None.
|
||||
* Return : USB_UNSUPPORT or USB_SUCCESS.
|
||||
*******************************************************************************/
|
||||
RESULT Virtual_Com_Port_Data_Setup(uint8_t RequestNo)
|
||||
{
|
||||
uint8_t *(*CopyRoutine)(uint16_t);
|
||||
|
||||
CopyRoutine = NULL;
|
||||
|
||||
if (RequestNo == GET_LINE_CODING)
|
||||
{
|
||||
if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
|
||||
{
|
||||
CopyRoutine = Virtual_Com_Port_GetLineCoding;
|
||||
}
|
||||
}
|
||||
else if (RequestNo == SET_LINE_CODING)
|
||||
{
|
||||
if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
|
||||
{
|
||||
CopyRoutine = Virtual_Com_Port_SetLineCoding;
|
||||
}
|
||||
Request = SET_LINE_CODING;
|
||||
}
|
||||
|
||||
if (CopyRoutine == NULL)
|
||||
{
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
pInformation->Ctrl_Info.CopyData = CopyRoutine;
|
||||
pInformation->Ctrl_Info.Usb_wOffset = 0;
|
||||
(*CopyRoutine)(0);
|
||||
return USB_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Virtual_Com_Port_NoData_Setup.
|
||||
* Description : handle the no data class specific requests.
|
||||
* Input : Request Nb.
|
||||
* Output : None.
|
||||
* Return : USB_UNSUPPORT or USB_SUCCESS.
|
||||
*******************************************************************************/
|
||||
RESULT Virtual_Com_Port_NoData_Setup(uint8_t RequestNo)
|
||||
{
|
||||
|
||||
if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
|
||||
{
|
||||
if (RequestNo == SET_COMM_FEATURE)
|
||||
{
|
||||
return USB_SUCCESS;
|
||||
}
|
||||
else if (RequestNo == SET_CONTROL_LINE_STATE)
|
||||
{
|
||||
return USB_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Virtual_Com_Port_GetDeviceDescriptor.
|
||||
* Description : Gets the device descriptor.
|
||||
* Input : Length.
|
||||
* Output : None.
|
||||
* Return : The address of the device descriptor.
|
||||
*******************************************************************************/
|
||||
uint8_t *Virtual_Com_Port_GetDeviceDescriptor(uint16_t Length)
|
||||
{
|
||||
return Standard_GetDescriptorData(Length, &Device_Descriptor);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Virtual_Com_Port_GetConfigDescriptor.
|
||||
* Description : get the configuration descriptor.
|
||||
* Input : Length.
|
||||
* Output : None.
|
||||
* Return : The address of the configuration descriptor.
|
||||
*******************************************************************************/
|
||||
uint8_t *Virtual_Com_Port_GetConfigDescriptor(uint16_t Length)
|
||||
{
|
||||
return Standard_GetDescriptorData(Length, &Config_Descriptor);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Virtual_Com_Port_GetStringDescriptor
|
||||
* Description : Gets the string descriptors according to the needed index
|
||||
* Input : Length.
|
||||
* Output : None.
|
||||
* Return : The address of the string descriptors.
|
||||
*******************************************************************************/
|
||||
uint8_t *Virtual_Com_Port_GetStringDescriptor(uint16_t Length)
|
||||
{
|
||||
uint8_t wValue0 = pInformation->USBwValue0;
|
||||
if (wValue0 > 4)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Standard_GetDescriptorData(Length, &String_Descriptor[wValue0]);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Virtual_Com_Port_Get_Interface_Setting.
|
||||
* Description : test the interface and the alternate setting according to the
|
||||
* supported one.
|
||||
* Input1 : uint8_t: Interface : interface number.
|
||||
* Input2 : uint8_t: AlternateSetting : Alternate Setting number.
|
||||
* Output : None.
|
||||
* Return : The address of the string descriptors.
|
||||
*******************************************************************************/
|
||||
RESULT Virtual_Com_Port_Get_Interface_Setting(uint8_t Interface, uint8_t AlternateSetting)
|
||||
{
|
||||
if (AlternateSetting > 0)
|
||||
{
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
else if (Interface > 1)
|
||||
{
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
return USB_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Virtual_Com_Port_GetLineCoding.
|
||||
* Description : send the linecoding structure to the PC host.
|
||||
* Input : Length.
|
||||
* Output : None.
|
||||
* Return : Linecoding structure base address.
|
||||
*******************************************************************************/
|
||||
uint8_t *Virtual_Com_Port_GetLineCoding(uint16_t Length)
|
||||
{
|
||||
if (Length == 0)
|
||||
{
|
||||
pInformation->Ctrl_Info.Usb_wLength = sizeof(linecoding);
|
||||
return NULL;
|
||||
}
|
||||
return(uint8_t *)&linecoding;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Virtual_Com_Port_SetLineCoding.
|
||||
* Description : Set the linecoding structure fields.
|
||||
* Input : Length.
|
||||
* Output : None.
|
||||
* Return : Linecoding structure base address.
|
||||
*******************************************************************************/
|
||||
uint8_t *Virtual_Com_Port_SetLineCoding(uint16_t Length)
|
||||
{
|
||||
if (Length == 0)
|
||||
{
|
||||
pInformation->Ctrl_Info.Usb_wLength = sizeof(linecoding);
|
||||
return NULL;
|
||||
}
|
||||
return(uint8_t *)&linecoding;
|
||||
}
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_prop.h
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 21-January-2013
|
||||
* @brief All processing related to Virtual COM Port Demo (Endpoint 0)
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __usb_prop_H
|
||||
#define __usb_prop_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t bitrate;
|
||||
uint8_t format;
|
||||
uint8_t paritytype;
|
||||
uint8_t datatype;
|
||||
}LINE_CODING;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported define -----------------------------------------------------------*/
|
||||
|
||||
#define Virtual_Com_Port_GetConfiguration NOP_Process
|
||||
//#define Virtual_Com_Port_SetConfiguration NOP_Process
|
||||
#define Virtual_Com_Port_GetInterface NOP_Process
|
||||
#define Virtual_Com_Port_SetInterface NOP_Process
|
||||
#define Virtual_Com_Port_GetStatus NOP_Process
|
||||
#define Virtual_Com_Port_ClearFeature NOP_Process
|
||||
#define Virtual_Com_Port_SetEndPointFeature NOP_Process
|
||||
#define Virtual_Com_Port_SetDeviceFeature NOP_Process
|
||||
//#define Virtual_Com_Port_SetDeviceAddress NOP_Process
|
||||
|
||||
#define SEND_ENCAPSULATED_COMMAND 0x00
|
||||
#define GET_ENCAPSULATED_RESPONSE 0x01
|
||||
#define SET_COMM_FEATURE 0x02
|
||||
#define GET_COMM_FEATURE 0x03
|
||||
#define CLEAR_COMM_FEATURE 0x04
|
||||
#define SET_LINE_CODING 0x20
|
||||
#define GET_LINE_CODING 0x21
|
||||
#define SET_CONTROL_LINE_STATE 0x22
|
||||
#define SEND_BREAK 0x23
|
||||
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void Virtual_Com_Port_init(void);
|
||||
void Virtual_Com_Port_Reset(void);
|
||||
void Virtual_Com_Port_SetConfiguration(void);
|
||||
void Virtual_Com_Port_SetDeviceAddress (void);
|
||||
void Virtual_Com_Port_Status_In (void);
|
||||
void Virtual_Com_Port_Status_Out (void);
|
||||
RESULT Virtual_Com_Port_Data_Setup(uint8_t);
|
||||
RESULT Virtual_Com_Port_NoData_Setup(uint8_t);
|
||||
RESULT Virtual_Com_Port_Get_Interface_Setting(uint8_t Interface, uint8_t AlternateSetting);
|
||||
uint8_t *Virtual_Com_Port_GetDeviceDescriptor(uint16_t );
|
||||
uint8_t *Virtual_Com_Port_GetConfigDescriptor(uint16_t);
|
||||
uint8_t *Virtual_Com_Port_GetStringDescriptor(uint16_t);
|
||||
|
||||
uint8_t *Virtual_Com_Port_GetLineCoding(uint16_t Length);
|
||||
uint8_t *Virtual_Com_Port_SetLineCoding(uint16_t Length);
|
||||
|
||||
#endif /* __usb_prop_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
|
@ -0,0 +1,318 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_pwr.c
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 21-January-2013
|
||||
* @brief Connection/disconnection & power management
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "core/usb_lib.h"
|
||||
#include "usb_conf.h"
|
||||
#include "usb_pwr.h"
|
||||
#include "glue.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
__IO uint32_t bDeviceState = UNCONNECTED; /* USB device status */
|
||||
__IO bool fSuspendEnabled = FALSE; /* true when suspend is possible */
|
||||
__IO uint32_t EP[8];
|
||||
|
||||
struct
|
||||
{
|
||||
__IO RESUME_STATE eState;
|
||||
__IO uint8_t bESOFcnt;
|
||||
}
|
||||
ResumeS;
|
||||
|
||||
__IO uint32_t remotewakeupon=0;
|
||||
|
||||
/* Extern variables ----------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Extern function prototypes ------------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : PowerOn
|
||||
* Description :
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : USB_SUCCESS.
|
||||
*******************************************************************************/
|
||||
RESULT PowerOn(void)
|
||||
{
|
||||
uint16_t wRegVal;
|
||||
|
||||
/*** cable plugged-in ? ***/
|
||||
USB_Cable_Config(ENABLE);
|
||||
|
||||
/*** CNTR_PWDN = 0 ***/
|
||||
wRegVal = CNTR_FRES;
|
||||
_SetCNTR(wRegVal);
|
||||
|
||||
/*** CNTR_FRES = 0 ***/
|
||||
wInterrupt_Mask = 0;
|
||||
_SetCNTR(wInterrupt_Mask);
|
||||
/*** Clear pending interrupts ***/
|
||||
_SetISTR(0);
|
||||
/*** Set interrupt mask ***/
|
||||
wInterrupt_Mask = CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM;
|
||||
_SetCNTR(wInterrupt_Mask);
|
||||
|
||||
return USB_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : PowerOff
|
||||
* Description : handles switch-off conditions
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : USB_SUCCESS.
|
||||
*******************************************************************************/
|
||||
RESULT PowerOff()
|
||||
{
|
||||
/* disable all interrupts and force USB reset */
|
||||
_SetCNTR(CNTR_FRES);
|
||||
/* clear interrupt status register */
|
||||
_SetISTR(0);
|
||||
/* Disable the Pull-Up*/
|
||||
USB_Cable_Config(DISABLE);
|
||||
/* switch-off device */
|
||||
_SetCNTR(CNTR_FRES + CNTR_PDWN);
|
||||
/* sw variables reset */
|
||||
/* ... */
|
||||
|
||||
return USB_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Suspend
|
||||
* Description : sets suspend mode operating conditions
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : USB_SUCCESS.
|
||||
*******************************************************************************/
|
||||
void Suspend(void)
|
||||
{
|
||||
uint32_t i =0;
|
||||
uint16_t wCNTR;
|
||||
uint32_t tmpreg = 0;
|
||||
__IO uint32_t savePWR_CR=0;
|
||||
/* suspend preparation */
|
||||
/* ... */
|
||||
|
||||
/*Store CNTR value */
|
||||
wCNTR = _GetCNTR();
|
||||
|
||||
/* This a sequence to apply a force RESET to handle a robustness case */
|
||||
|
||||
/*Store endpoints registers status */
|
||||
for (i=0;i<8;i++) EP[i] = _GetENDPOINT(i);
|
||||
|
||||
/* unmask RESET flag */
|
||||
wCNTR|=CNTR_RESETM;
|
||||
_SetCNTR(wCNTR);
|
||||
|
||||
/*apply FRES */
|
||||
wCNTR|=CNTR_FRES;
|
||||
_SetCNTR(wCNTR);
|
||||
|
||||
/*clear FRES*/
|
||||
wCNTR&=~CNTR_FRES;
|
||||
_SetCNTR(wCNTR);
|
||||
|
||||
/*poll for RESET flag in ISTR*/
|
||||
while((_GetISTR()&ISTR_RESET) == 0);
|
||||
|
||||
/* clear RESET flag in ISTR */
|
||||
_SetISTR((uint16_t)CLR_RESET);
|
||||
|
||||
/*restore Enpoints*/
|
||||
for (i=0;i<8;i++)
|
||||
_SetENDPOINT(i, EP[i]);
|
||||
|
||||
/* Now it is safe to enter macrocell in suspend mode */
|
||||
wCNTR |= CNTR_FSUSP;
|
||||
_SetCNTR(wCNTR);
|
||||
|
||||
/* force low-power mode in the macrocell */
|
||||
wCNTR = _GetCNTR();
|
||||
wCNTR |= CNTR_LPMODE;
|
||||
_SetCNTR(wCNTR);
|
||||
|
||||
/*prepare entry in low power mode (STOP mode)*/
|
||||
/* Select the regulator state in STOP mode*/
|
||||
savePWR_CR = PWR->CR;
|
||||
tmpreg = PWR->CR;
|
||||
/* Clear PDDS and LPDS bits */
|
||||
tmpreg &= ((uint32_t)0xFFFFFFFC);
|
||||
/* Set LPDS bit according to PWR_Regulator value */
|
||||
tmpreg |= PWR_Regulator_LowPower;
|
||||
/* Store the new value */
|
||||
PWR->CR = tmpreg;
|
||||
/* Set SLEEPDEEP bit of Cortex System Control Register */
|
||||
#if defined (STM32F30X) || defined (STM32F37X)
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
#else
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP;
|
||||
#endif
|
||||
|
||||
/* enter system in STOP mode, only when wakeup flag in not set */
|
||||
if((_GetISTR()&ISTR_WKUP)==0)
|
||||
{
|
||||
__WFI();
|
||||
/* Reset SLEEPDEEP bit of Cortex System Control Register */
|
||||
#if defined (STM32F30X) || defined (STM32F37X)
|
||||
SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
|
||||
#else
|
||||
SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear Wakeup flag */
|
||||
_SetISTR(CLR_WKUP);
|
||||
/* clear FSUSP to abort entry in suspend mode */
|
||||
wCNTR = _GetCNTR();
|
||||
wCNTR&=~CNTR_FSUSP;
|
||||
_SetCNTR(wCNTR);
|
||||
|
||||
/*restore sleep mode configuration */
|
||||
/* restore Power regulator config in sleep mode*/
|
||||
PWR->CR = savePWR_CR;
|
||||
|
||||
/* Reset SLEEPDEEP bit of Cortex System Control Register */
|
||||
#if defined (STM32F30X) || defined (STM32F37X)
|
||||
SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
|
||||
#else
|
||||
SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Resume_Init
|
||||
* Description : Handles wake-up restoring normal operations
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : USB_SUCCESS.
|
||||
*******************************************************************************/
|
||||
void Resume_Init(void)
|
||||
{
|
||||
uint16_t wCNTR;
|
||||
|
||||
/* ------------------ ONLY WITH BUS-POWERED DEVICES ---------------------- */
|
||||
/* restart the clocks */
|
||||
/* ... */
|
||||
|
||||
/* CNTR_LPMODE = 0 */
|
||||
wCNTR = _GetCNTR();
|
||||
wCNTR &= (~CNTR_LPMODE);
|
||||
_SetCNTR(wCNTR);
|
||||
|
||||
/* restore full power */
|
||||
/* ... on connected devices */
|
||||
Leave_LowPowerMode();
|
||||
|
||||
/* reset FSUSP bit */
|
||||
_SetCNTR(IMR_MSK);
|
||||
|
||||
/* reverse suspend preparation */
|
||||
/* ... */
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : Resume
|
||||
* Description : This is the state machine handling resume operations and
|
||||
* timing sequence. The control is based on the Resume structure
|
||||
* variables and on the ESOF interrupt calling this subroutine
|
||||
* without changing machine state.
|
||||
* Input : a state machine value (RESUME_STATE)
|
||||
* RESUME_ESOF doesn't change ResumeS.eState allowing
|
||||
* decrementing of the ESOF counter in different states.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void Resume(RESUME_STATE eResumeSetVal)
|
||||
{
|
||||
uint16_t wCNTR;
|
||||
|
||||
if (eResumeSetVal != RESUME_ESOF)
|
||||
ResumeS.eState = eResumeSetVal;
|
||||
switch (ResumeS.eState)
|
||||
{
|
||||
case RESUME_EXTERNAL:
|
||||
if (remotewakeupon ==0)
|
||||
{
|
||||
Resume_Init();
|
||||
ResumeS.eState = RESUME_OFF;
|
||||
}
|
||||
else /* RESUME detected during the RemoteWAkeup signalling => keep RemoteWakeup handling*/
|
||||
{
|
||||
ResumeS.eState = RESUME_ON;
|
||||
}
|
||||
break;
|
||||
case RESUME_INTERNAL:
|
||||
Resume_Init();
|
||||
ResumeS.eState = RESUME_START;
|
||||
remotewakeupon = 1;
|
||||
break;
|
||||
case RESUME_LATER:
|
||||
ResumeS.bESOFcnt = 2;
|
||||
ResumeS.eState = RESUME_WAIT;
|
||||
break;
|
||||
case RESUME_WAIT:
|
||||
ResumeS.bESOFcnt--;
|
||||
if (ResumeS.bESOFcnt == 0)
|
||||
ResumeS.eState = RESUME_START;
|
||||
break;
|
||||
case RESUME_START:
|
||||
wCNTR = _GetCNTR();
|
||||
wCNTR |= CNTR_RESUME;
|
||||
_SetCNTR(wCNTR);
|
||||
ResumeS.eState = RESUME_ON;
|
||||
ResumeS.bESOFcnt = 10;
|
||||
break;
|
||||
case RESUME_ON:
|
||||
ResumeS.bESOFcnt--;
|
||||
if (ResumeS.bESOFcnt == 0)
|
||||
{
|
||||
wCNTR = _GetCNTR();
|
||||
wCNTR &= (~CNTR_RESUME);
|
||||
_SetCNTR(wCNTR);
|
||||
ResumeS.eState = RESUME_OFF;
|
||||
remotewakeupon = 0;
|
||||
}
|
||||
break;
|
||||
case RESUME_OFF:
|
||||
case RESUME_ESOF:
|
||||
default:
|
||||
ResumeS.eState = RESUME_OFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file usb_pwr.h
|
||||
* @author MCD Application Team
|
||||
* @version V4.0.0
|
||||
* @date 21-January-2013
|
||||
* @brief Connection/disconnection & power management header
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USB_PWR_H
|
||||
#define __USB_PWR_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
typedef enum _RESUME_STATE
|
||||
{
|
||||
RESUME_EXTERNAL,
|
||||
RESUME_INTERNAL,
|
||||
RESUME_LATER,
|
||||
RESUME_WAIT,
|
||||
RESUME_START,
|
||||
RESUME_ON,
|
||||
RESUME_OFF,
|
||||
RESUME_ESOF
|
||||
} RESUME_STATE;
|
||||
|
||||
typedef enum _DEVICE_STATE
|
||||
{
|
||||
UNCONNECTED,
|
||||
ATTACHED,
|
||||
POWERED,
|
||||
SUSPENDED,
|
||||
ADDRESSED,
|
||||
CONFIGURED
|
||||
} DEVICE_STATE;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void Suspend(void);
|
||||
void Resume_Init(void);
|
||||
void Resume(RESUME_STATE eResumeSetVal);
|
||||
RESULT PowerOn(void);
|
||||
RESULT PowerOff(void);
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
extern __IO uint32_t bDeviceState; /* USB device status */
|
||||
extern __IO bool fSuspendEnabled; /* true when suspend is possible */
|
||||
|
||||
#endif /*__USB_PWR_H*/
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue