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:
true 2023-02-11 06:31:54 -08:00
parent 1182c9b578
commit 03376cc654
101 changed files with 15902 additions and 0 deletions

5
fw_dc22_stm32l100/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch

View File

@ -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"
]
}

View File

@ -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

View File

@ -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

View File

@ -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>&copy; 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****/

View 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 */

View File

@ -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>&copy; 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****/

View 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

View File

@ -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);
}
}

View File

@ -0,0 +1,4 @@
/* improved reference xxtea implementation */
void btea(uint32_t *v, int n, uint32_t const key[4]);

View File

@ -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

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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};

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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];

View File

@ -0,0 +1,7 @@
/**
* radio/address.h: address buffers and lookups
* 2015 by true
*
* $Id$
*
**/

View File

@ -0,0 +1,15 @@
/**
* radio/irq.c: nrf irq handler
* 2015 by true
* ----
*
* $Id$
*
**/
#include <pirate.h>
#include "nrf.h"

View File

@ -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();
}

View File

@ -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

View File

@ -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

View File

@ -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));
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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}
};

View File

@ -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

View File

@ -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()
{
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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

View File

@ -0,0 +1,8 @@
/**
* pirate gpio interface
* 2014 true
*
* ----
*
* $Id: gpio.c 327 2015-02-18 04:43:42Z true $
**/

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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
//---------------------------------------------------
}
*/

View File

@ -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*/

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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
};

View File

@ -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--;
}

View File

@ -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--;
}

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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
};

View File

@ -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--;
}

View File

@ -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);
}

View File

@ -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};

View File

@ -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

View File

@ -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]}
};

View File

@ -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

View File

@ -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};

View File

@ -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

View File

@ -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]},
};

View File

@ -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

View File

@ -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]}
};

View File

@ -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

View File

@ -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]}
};

View File

@ -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

View File

@ -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;

View File

@ -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]}
};

View File

@ -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

View File

@ -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()
{
}

View File

@ -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)
{
}*/
/**
* @}
*/
/**
* @}
*/

View File

@ -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

View File

@ -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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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);
}

View File

@ -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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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****/

View 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>&copy; 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