├── layout ├── TapuinoMini1.03 │ ├── gerbers │ │ ├── none │ │ ├── TapuinoMini.dri │ │ ├── TapuinoMini.gpi │ │ └── TapuinoMini.TXT │ └── README.md ├── Vero-top.png ├── tapuino.fzz ├── tapuino-r2.fzz ├── tapuino_bb.png ├── Vero-bottom.png ├── tapuino_bb-r2.png ├── Vero-button-top.png ├── tapuino-main-r2.png ├── Vero-button-bottom.png ├── Vero-button-top-r2.png ├── tapuino-mux-board-r1.png ├── tapuino-mux-board-r2.png ├── Vero-button-bottom-r2.png ├── eagle │ ├── parts │ │ ├── commodore.lbr │ │ └── NanoV3.lbr │ ├── v1.4 │ │ ├── Tapuino holes_0000.jpg │ │ ├── Tapuino assembly PCB v1.4.pdf │ │ ├── buttons template.brd │ │ └── 1602 QAPASS LCD Template -0.5.brd │ ├── LICENCE │ └── TapuinoMini │ │ ├── 1.01 │ │ ├── TapuinoMiniDouble_top.png │ │ └── TapuinoMiniDouble_bottom.png │ │ └── 1.02 │ │ ├── TapuinoMiniDouble_top.png │ │ └── TapuinoMiniDouble_bottom.png ├── tapuino-main-bottom-r2.png └── tapuino-mux-board-r2-bottom.png ├── .gitattributes ├── CAD ├── pics │ ├── top.jpg │ ├── board.jpg │ ├── box1.jpg │ ├── box2.jpg │ ├── box3.jpg │ ├── box-cad-1.png │ ├── box-cad-2.png │ ├── c64connector-open.jpg │ └── c64connector-closed.jpg ├── Display lid.stl ├── Main body.stl ├── Top section.stl ├── Key 1 - Left.stl ├── Key 2 - Right.stl ├── Reset button.stl ├── Key 3 - Select.stl ├── Key 4 - Cancel.stl ├── C=64 Datassette connector - lid.stl ├── C=64 Datassette connector - base.stl └── README.md ├── buffer.c ├── tapuino.ino ├── version.h ├── buffer.h ├── menu.h ├── .gitignore ├── fileutils.h ├── serial.h ├── lcd_interface.h ├── comms.h ├── main.c ├── lcdutils.h ├── memstrings-neutral.c ├── ccsbcs_avr.c ├── spi.h ├── tapuino.h ├── integer.h ├── spi.c ├── Makefile ├── LICENCE ├── mmc.h ├── README.md ├── config-user.h.example ├── memstrings.h ├── memstrings-tr.c ├── memstrings-en.c ├── memstrings-es.c ├── memstrings-de.c ├── memstrings-it.c ├── fileutils.c ├── diskio.h ├── serial.c ├── disp_oled_SSD131x.c ├── lcdutils.c ├── comms.c ├── config.h ├── i2c_master.h ├── LightweightRingBuff.h ├── i2c_master.c ├── disp_oled_ssd1306.c ├── font8x8.h ├── Tapuino.cproj ├── disp_LCD_HD44780.c ├── ffconf.h ├── ff.h ├── menu.c └── mmc.c /layout/TapuinoMini1.03/gerbers/none: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | layout/* linguist-vendored 2 | -------------------------------------------------------------------------------- /CAD/pics/top.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/pics/top.jpg -------------------------------------------------------------------------------- /CAD/Display lid.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/Display lid.stl -------------------------------------------------------------------------------- /CAD/Main body.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/Main body.stl -------------------------------------------------------------------------------- /CAD/Top section.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/Top section.stl -------------------------------------------------------------------------------- /CAD/pics/board.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/pics/board.jpg -------------------------------------------------------------------------------- /CAD/pics/box1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/pics/box1.jpg -------------------------------------------------------------------------------- /CAD/pics/box2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/pics/box2.jpg -------------------------------------------------------------------------------- /CAD/pics/box3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/pics/box3.jpg -------------------------------------------------------------------------------- /layout/Vero-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/Vero-top.png -------------------------------------------------------------------------------- /layout/tapuino.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/tapuino.fzz -------------------------------------------------------------------------------- /CAD/Key 1 - Left.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/Key 1 - Left.stl -------------------------------------------------------------------------------- /CAD/Key 2 - Right.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/Key 2 - Right.stl -------------------------------------------------------------------------------- /CAD/Reset button.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/Reset button.stl -------------------------------------------------------------------------------- /layout/tapuino-r2.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/tapuino-r2.fzz -------------------------------------------------------------------------------- /layout/tapuino_bb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/tapuino_bb.png -------------------------------------------------------------------------------- /CAD/Key 3 - Select.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/Key 3 - Select.stl -------------------------------------------------------------------------------- /CAD/Key 4 - Cancel.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/Key 4 - Cancel.stl -------------------------------------------------------------------------------- /CAD/pics/box-cad-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/pics/box-cad-1.png -------------------------------------------------------------------------------- /CAD/pics/box-cad-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/pics/box-cad-2.png -------------------------------------------------------------------------------- /buffer.c: -------------------------------------------------------------------------------- 1 | #include "buffer.h" 2 | 3 | RingBuff_t comms_rx_buffer; 4 | RingBuff_t comms_tx_buffer; 5 | -------------------------------------------------------------------------------- /layout/Vero-bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/Vero-bottom.png -------------------------------------------------------------------------------- /layout/tapuino_bb-r2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/tapuino_bb-r2.png -------------------------------------------------------------------------------- /layout/Vero-button-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/Vero-button-top.png -------------------------------------------------------------------------------- /layout/tapuino-main-r2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/tapuino-main-r2.png -------------------------------------------------------------------------------- /layout/Vero-button-bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/Vero-button-bottom.png -------------------------------------------------------------------------------- /layout/Vero-button-top-r2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/Vero-button-top-r2.png -------------------------------------------------------------------------------- /CAD/pics/c64connector-open.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/pics/c64connector-open.jpg -------------------------------------------------------------------------------- /layout/tapuino-mux-board-r1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/tapuino-mux-board-r1.png -------------------------------------------------------------------------------- /layout/tapuino-mux-board-r2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/tapuino-mux-board-r2.png -------------------------------------------------------------------------------- /CAD/pics/c64connector-closed.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/pics/c64connector-closed.jpg -------------------------------------------------------------------------------- /layout/Vero-button-bottom-r2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/Vero-button-bottom-r2.png -------------------------------------------------------------------------------- /layout/eagle/parts/commodore.lbr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/eagle/parts/commodore.lbr -------------------------------------------------------------------------------- /layout/tapuino-main-bottom-r2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/tapuino-main-bottom-r2.png -------------------------------------------------------------------------------- /CAD/C=64 Datassette connector - lid.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/C=64 Datassette connector - lid.stl -------------------------------------------------------------------------------- /layout/tapuino-mux-board-r2-bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/tapuino-mux-board-r2-bottom.png -------------------------------------------------------------------------------- /CAD/C=64 Datassette connector - base.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/CAD/C=64 Datassette connector - base.stl -------------------------------------------------------------------------------- /layout/eagle/v1.4/Tapuino holes_0000.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/eagle/v1.4/Tapuino holes_0000.jpg -------------------------------------------------------------------------------- /layout/eagle/v1.4/Tapuino assembly PCB v1.4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/eagle/v1.4/Tapuino assembly PCB v1.4.pdf -------------------------------------------------------------------------------- /layout/eagle/LICENCE: -------------------------------------------------------------------------------- 1 | Layout files are licensed under the Creative Commons Attribution-NonCommercial 4.0 International for use other than by the copyright holders. 2 | -------------------------------------------------------------------------------- /layout/eagle/TapuinoMini/1.01/TapuinoMiniDouble_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/eagle/TapuinoMini/1.01/TapuinoMiniDouble_top.png -------------------------------------------------------------------------------- /layout/eagle/TapuinoMini/1.02/TapuinoMiniDouble_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/eagle/TapuinoMini/1.02/TapuinoMiniDouble_top.png -------------------------------------------------------------------------------- /tapuino.ino: -------------------------------------------------------------------------------- 1 | extern "C" 2 | { 3 | #include "tapuino.h" 4 | } 5 | 6 | void setup() 7 | { 8 | tapuino_run(); 9 | } 10 | 11 | void loop() 12 | { 13 | } 14 | -------------------------------------------------------------------------------- /layout/eagle/TapuinoMini/1.01/TapuinoMiniDouble_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/eagle/TapuinoMini/1.01/TapuinoMiniDouble_bottom.png -------------------------------------------------------------------------------- /layout/eagle/TapuinoMini/1.02/TapuinoMiniDouble_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sweetlilmre/tapuino/HEAD/layout/eagle/TapuinoMini/1.02/TapuinoMiniDouble_bottom.png -------------------------------------------------------------------------------- /version.h: -------------------------------------------------------------------------------- 1 | #ifndef VERSION_H 2 | #define VERSION_H 3 | 4 | #define TAPUINO_MAJOR_VERSION 2 5 | #define TAPUINO_MINOR_VERSION 10 6 | #define TAPUINO_BUILD_VERSION 0 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef _BUFFER_H 2 | #define _BUFFER_H 3 | #include "LightweightRingBuff.h" 4 | 5 | extern RingBuff_t comms_rx_buffer; 6 | extern RingBuff_t comms_tx_buffer; 7 | 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /menu.h: -------------------------------------------------------------------------------- 1 | #ifndef MENU_H 2 | #define MENU_H 3 | 4 | void handle_play_mode(FILINFO* pfile_info); 5 | void handle_mode_record(FILINFO* pfile_info); 6 | void handle_mode_options(); 7 | void main_menu(FILINFO* pfile_info); 8 | 9 | #endif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Libraries 8 | *.lib 9 | *.a 10 | 11 | # Shared objects (inc. Windows DLLs) 12 | *.dll 13 | *.so 14 | *.so.* 15 | *.dylib 16 | 17 | # Executables 18 | *.exe 19 | *.out 20 | *.app 21 | *.i*86 22 | *.x86_64 23 | *.hex 24 | 25 | # Target directory 26 | target/ 27 | config-user.h 28 | -------------------------------------------------------------------------------- /fileutils.h: -------------------------------------------------------------------------------- 1 | #ifndef FILEUTILS_H 2 | #define FILEUTILS_H 3 | 4 | #define FAT_BUF_SIZE 256 5 | 6 | extern FATFS g_fs; 7 | extern DIR g_dir; 8 | extern FIL g_fil; 9 | extern uint8_t g_fat_buffer[FAT_BUF_SIZE]; 10 | 11 | int get_num_files(FILINFO* pfile_info); 12 | int get_file_at_index(FILINFO* pfile_info, int index); 13 | FRESULT change_dir(char* dir); 14 | 15 | #endif -------------------------------------------------------------------------------- /serial.h: -------------------------------------------------------------------------------- 1 | #ifndef _SERIAL_H 2 | #define _SERIAL_H 3 | 4 | void serial_init( void ); 5 | int serial_available( void ); 6 | char serial_read( void ); 7 | 8 | void serial_write( char data ); 9 | void serial_print( char* data ); 10 | void serial_printByte( unsigned char data ); 11 | void serial_println( char* data ); 12 | void serial_println_P( char* data ); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /lcd_interface.h: -------------------------------------------------------------------------------- 1 | #ifndef LCD_INTERFACE_H 2 | #define LCD_INTERFACE_H 3 | 4 | #include 5 | 6 | void lcd_init(uint8_t lcd_addr); 7 | void lcd_cursor(); 8 | void lcd_noCursor(); 9 | void lcd_backlight(); 10 | void lcd_noBacklight(); 11 | void lcd_setCursor(uint8_t col, uint8_t row); 12 | void lcd_print(char* msg); 13 | void lcd_write(uint8_t value); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /comms.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMMS_H 2 | #define _COMMS_H 3 | 4 | 5 | #define COMMAND_IDLE 0 6 | #define COMMAND_SELECT 1 7 | #define COMMAND_SELECT_LONG 2 8 | #define COMMAND_ABORT 3 9 | #define COMMAND_ABORT_LONG 4 10 | #define COMMAND_NEXT 5 11 | #define COMMAND_PREVIOUS 6 12 | 13 | void input_callback(); 14 | extern volatile uint8_t g_cur_command; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Tapuino.c 3 | * 4 | * Created: 2014/10/04 04:31:40 PM 5 | * Author: sweetlilmre 6 | */ 7 | 8 | #ifndef ARDUINO 9 | 10 | #include 11 | #include "tapuino.h" 12 | 13 | int main(void) 14 | { 15 | while(1) 16 | { 17 | tapuino_run(); 18 | //TODO:: Please write your application code 19 | } 20 | } 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /layout/TapuinoMini1.03/README.md: -------------------------------------------------------------------------------- 1 | # tapuinomini1.03 2 | 3 | TapuninoMini 1.03 based on the design of OzayTuray - Original design by Peter Edwards ( sweetlilmre ). 4 | 5 | A redesigned version of the Tapuinomini with built in buttons and connector on the PCB. 6 | 7 | A step by step build process can be found on my blog: 8 | http://arananet-net.kinja.com/tapuino-1-03-mejorando-el-tapuino-mini-1788202676 9 | 10 | 2016 -@edu_arana 11 | -------------------------------------------------------------------------------- /lcdutils.h: -------------------------------------------------------------------------------- 1 | #ifndef _LCDUTILS_H 2 | #define _LCDUTILS_H 3 | 4 | void lcd_setup(); 5 | 6 | void filename_ticker(FILINFO* pfile_info, uint32_t cur_tick); 7 | void display_filename(FILINFO* pfile_info); 8 | void lcd_busy_spinner(); 9 | void lcd_spinner(uint32_t wait, int8_t perc); 10 | void lcd_show_dir(); 11 | void lcd_title(char* msg); 12 | void lcd_title_P(const char* msg); 13 | void lcd_status(char* msg); 14 | void lcd_status_P(const char* msg); 15 | 16 | extern char g_char_buffer[]; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /memstrings-neutral.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "memstrings.h" 3 | 4 | const char S_NAME_PATTERN[] PROGMEM = "rec-%.4d.tap"; 5 | const char S_VERSION_PATTERN[] PROGMEM = "V: %d.%d.%d"; 6 | const char S_FILENAME_CHARS[] PROGMEM = " abcdefghijklmnopqrstuvwxyz0123456789_-"; 7 | 8 | const char S_C64[] PROGMEM = "C64"; 9 | const char S_C16[] PROGMEM = "C16"; 10 | const char S_VIC[] PROGMEM = "VIC"; 11 | const char S_PAL[] PROGMEM = "PAL"; 12 | const char S_NTSC[] PROGMEM = "NTSC"; 13 | -------------------------------------------------------------------------------- /CAD/README.md: -------------------------------------------------------------------------------- 1 | Tapuino 3D printable enclosure 2 | ============================== 3 | 4 | This is a 3D printable enclosure designed with Fusion 360. It can be printed using PLA using: 5 | 6 | - 3 walls 7 | - 0.1mm layer height 8 | - Supports for the top section and the C=64 connector lid 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /ccsbcs_avr.c: -------------------------------------------------------------------------------- 1 | #include "ff.h" 2 | #include 3 | 4 | WCHAR ff_convert ( /* Converted character, Returns zero on error */ 5 | WCHAR chr, /* Character code to be converted */ 6 | UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */ 7 | ) 8 | { 9 | return chr; 10 | } 11 | 12 | 13 | WCHAR ff_wtoupper ( /* Upper converted character */ 14 | WCHAR chr /* Input character */ 15 | ) 16 | { 17 | if (chr >= 'a' && chr <= 'z') { 18 | chr = 'A' + (chr - 'a'); 19 | } 20 | return chr; 21 | } 22 | -------------------------------------------------------------------------------- /spi.h: -------------------------------------------------------------------------------- 1 | #ifndef _SPIFUNCS_H__ 2 | #define _SPIFUNCS_H__ 3 | 4 | //SPI configuration (Platform dependent) 5 | #define SPI_DDR DDRB 6 | #define SPI_PORT PORTB 7 | #define SPI_SS 2 8 | #define SPI_MOSI 3 9 | #define SPI_MISO 4 10 | #define SPI_SCK 5 11 | 12 | 13 | 14 | // SPI Controls 15 | #define SPI_SELECT() SPI_PORT &= ~_BV(SPI_SS) // SPI CS = L 16 | #define SPI_DESELECT() SPI_PORT |= _BV(SPI_SS) 17 | #define SPI_IS_SEL() !(SPI_PORT & _BV(SPI_SS)) 18 | 19 | 20 | 21 | void SPI_Init(); 22 | void SPI_Speed_Slow(); 23 | void SPI_Speed_Fast(); 24 | void SPI_Send( BYTE data ); 25 | BYTE SPI_Recv( void ); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /tapuino.h: -------------------------------------------------------------------------------- 1 | #ifndef TAPUINO_H 2 | #define TAPUINO_H 3 | 4 | #include "ff.h" 5 | 6 | void tapuino_run(); 7 | void record_file(char* pfile_name); 8 | int play_file(FILINFO* pfile_info); 9 | uint32_t get_timer_tick(); 10 | void save_eeprom_data(); 11 | 12 | extern volatile uint8_t g_invert_signal; 13 | extern volatile uint16_t g_ticker_rate; 14 | extern volatile uint16_t g_ticker_hold_rate; 15 | extern volatile uint16_t g_key_repeat_next; 16 | extern volatile uint16_t g_rec_finalize_time; 17 | extern volatile uint8_t g_rec_auto_finalize; 18 | extern uint8_t g_machine_type; 19 | extern uint8_t g_video_mode; 20 | extern volatile uint8_t g_is_paused; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /integer.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------*/ 2 | /* Integer type definitions for FatFs module */ 3 | /*-------------------------------------------*/ 4 | 5 | #ifndef _FF_INTEGER 6 | #define _FF_INTEGER 7 | 8 | #ifdef _WIN32 /* FatFs development platform */ 9 | 10 | #include 11 | #include 12 | 13 | #else /* Embedded platform */ 14 | 15 | /* This type MUST be 8 bit */ 16 | typedef unsigned char BYTE; 17 | 18 | /* These types MUST be 16 bit */ 19 | typedef short SHORT; 20 | typedef unsigned short WORD; 21 | typedef unsigned short WCHAR; 22 | 23 | /* These types MUST be 16 bit or 32 bit */ 24 | typedef int INT; 25 | typedef unsigned int UINT; 26 | 27 | /* These types MUST be 32 bit */ 28 | typedef long LONG; 29 | typedef unsigned long DWORD; 30 | 31 | #endif 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /spi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "integer.h" 3 | #include "spi.h" 4 | 5 | 6 | void SPI_Init() 7 | { 8 | SPI_DDR |= _BV(SPI_MOSI) | _BV(SPI_SCK) | _BV(SPI_SS); // setup SPI output ports 9 | SPI_DDR &= ~_BV(SPI_MISO); // setup SPI input ports 10 | 11 | SPI_PORT |= _BV(SPI_MOSI) | _BV(SPI_SCK) | _BV(SPI_SS); // SPI outputs high 12 | SPI_PORT |= _BV(SPI_MISO); // set pull-up resistor on input 13 | SPCR = _BV(SPE) | _BV(MSTR) |_BV(SPR1); 14 | } 15 | 16 | 17 | void SPI_Speed_Slow() 18 | { 19 | SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR1) | _BV(SPR0); 20 | SPSR &= ~_BV(SPI2X); 21 | } 22 | 23 | void SPI_Speed_Fast() 24 | { 25 | SPCR = _BV(SPE) | _BV(MSTR); 26 | SPSR |= _BV(SPI2X); 27 | } 28 | 29 | void SPI_Send( BYTE data ) 30 | { 31 | SPDR = ( data ); 32 | while( !( SPSR & ( 1< http://jump.to/fleury 25 | * LCD code: conversion of the Arduino code apparently by DFRobot? (converted to C by me) 26 | 27 | 28 | ## 3D printable enclosure 29 | by @fabriziofiorucci 30 | 31 | A [3D printable enclosure](CAD) designed with Fusion 360 is available for download as .stl files 32 | 33 | 34 | -------------------------------------------------------------------------------- /config-user.h.example: -------------------------------------------------------------------------------- 1 | /********************************************************************************/ 2 | // User selectable configuration settings 3 | // 4 | /********************************************************************************/ 5 | 6 | /********************************************************************************/ 7 | // LCD Definitions 8 | /********************************************************************************/ 9 | 10 | // uncomment one of these sets for your specific LCD 11 | 12 | // #define LCD_USE_1602_LCD_MODULE 13 | // #define LCD_I2C_ADDR 0x27 // I2C address for the LCD 14 | 15 | // #define LCD_USE_SSD1306_OLED_MODULE 16 | // #define LCD_I2C_ADDR 0x3C // I2C address for the OLED 17 | // #define LCD_SSD1306_BIG_FONTS // define this for ... bigger fonts... 18 | // choose one of these depending on your display 19 | // #define LCD_SSD1306_128x64 20 | // #define LCD_SSD1306_128x32 21 | 22 | 23 | // #define LCD_USE_SSD131X_OLED_MODULE 24 | // #define LCD_I2C_ADDR 0x3C // I2C address for the OLED 25 | 26 | /********************************************************************************/ 27 | // Language Definitions 28 | /********************************************************************************/ 29 | 30 | // uncomment one of these for your language 31 | 32 | // #define TAPUINO_LANGUAGE_EN 33 | // #define TAPUINO_LANGUAGE_IT 34 | // #define TAPUINO_LANGUAGE_TR 35 | // #define TAPUINO_LANGUAGE_ES 36 | // #define TAPUINO_LANGUAGE_DE 37 | -------------------------------------------------------------------------------- /layout/TapuinoMini1.03/gerbers/TapuinoMini.gpi: -------------------------------------------------------------------------------- 1 | Generated by EAGLE CAM Processor 7.6.0 2 | 3 | Photoplotter Info File: C:/Users/usuario/Desktop/Proyectos/tapuinomini_edu/TapuinoMini.gpi 4 | 5 | Date : 29/10/2016 10:41 6 | Plotfile : C:/Users/usuario/Desktop/Proyectos/tapuinomini_edu/TapuinoMini.GTL 7 | Apertures : generated: 8 | Device : Gerber RS-274-X photoplotter, coordinate format 2.5 inch 9 | 10 | Parameter settings: 11 | 12 | Emulate Apertures : no 13 | Tolerance Draw + : 0.00 % 14 | Tolerance Draw - : 0.00 % 15 | Tolerance Flash + : 0.00 % 16 | Tolerance Flash - : 0.00 % 17 | Rotate : no 18 | Mirror : no 19 | Optimize : yes 20 | Auto fit : yes 21 | OffsetX : 0inch 22 | OffsetY : 0inch 23 | 24 | Plotfile Info: 25 | 26 | Coordinate Format : 2.5 27 | Coordinate Units : Inch 28 | Data Mode : Absolute 29 | Zero Suppression : None 30 | End Of Block : * 31 | 32 | Apertures used: 33 | 34 | Code Shape Size used 35 | 36 | D10 rectangle 0.1000inch x 0.2000inch 11 37 | D11 draw 0.0000inch 13 38 | D12 square 0.0560inch 4 39 | D13 octagon 0.0700inch 38 40 | D14 square 0.0640inch 1 41 | D15 octagon 0.0640inch 5 42 | D16 octagon 0.0560inch 16 43 | D17 octagon 0.0600inch 8 44 | D18 round 0.0885inch 8 45 | D19 draw 0.0120inch 28 46 | D20 draw 0.0050inch 2 47 | D21 draw 0.0160inch 44 48 | D22 square 0.0356inch 11 49 | 50 | -------------------------------------------------------------------------------- /memstrings.h: -------------------------------------------------------------------------------- 1 | #ifndef _MEMSTRINGS_H 2 | #define _MEMSTRINGS_H 3 | 4 | #include 5 | 6 | extern const char S_DEFAULT_RECORD_DIR[]; 7 | extern const char S_NAME_PATTERN[]; 8 | extern const char S_RECORDING[]; 9 | extern const char S_SELECT_RECORD_MODE[]; 10 | extern const char S_REC_MODE_MANUAL[]; 11 | extern const char S_REC_MODE_AUTO[]; 12 | extern const char S_ENTER_FILENAME[]; 13 | extern const char S_FILENAME_CHARS[]; 14 | 15 | extern const char S_STARTINGINIT[]; 16 | extern const char S_INITI2COK[]; 17 | extern const char S_INIT[]; 18 | extern const char S_INIT_FAILED[]; 19 | extern const char S_INIT_OK[]; 20 | extern const char S_NO_FILES_FOUND[]; 21 | extern const char S_SELECT_FILE[]; 22 | extern const char S_SELECT_MODE[]; 23 | extern const char S_MODE_PLAY[]; 24 | extern const char S_MODE_RECORD[]; 25 | extern const char S_READY_RECORD[]; 26 | extern const char S_PRESS_START[]; 27 | 28 | extern const char S_MODE_OPTIONS[]; 29 | extern const char S_OPTION_SIGNAL[]; 30 | extern const char S_OPTION_KEY_REPEAT[]; 31 | extern const char S_OPTION_TICKER_SPEED[]; 32 | extern const char S_OPTION_TICKER_HOLD[]; 33 | extern const char S_OPTION_REC_FINALIZE[]; 34 | extern const char S_OPTION_REC_AUTO_FINALIZE[]; 35 | 36 | 37 | extern const char S_MKDIR_FAILED[]; 38 | extern const char S_CHDIR_FAILED[]; 39 | extern const char S_READ_FAILED[]; 40 | extern const char S_OPEN_FAILED[]; 41 | extern const char S_INVALID_TAP[]; 42 | extern const char S_INVALID_SIZE[]; 43 | extern const char S_LOADING[]; 44 | extern const char S_OPERATION_COMPLETE[]; 45 | extern const char S_OPERATION_ABORTED[]; 46 | 47 | 48 | extern const char S_OPTION_MACHINE_TYPE[]; 49 | extern const char S_C64[]; 50 | extern const char S_C16[]; 51 | extern const char S_VIC[]; 52 | 53 | extern const char S_OPTION_VIDEO_MODE[]; 54 | extern const char S_PAL[]; 55 | extern const char S_NTSC[]; 56 | 57 | extern const char S_VERSION_PATTERN[]; 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /memstrings-tr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "config.h" 3 | #include "memstrings.h" 4 | 5 | #ifdef TAPUINO_LANGUAGE_TR 6 | 7 | const char S_DEFAULT_RECORD_DIR[] PROGMEM = "/kaydedilen"; 8 | const char S_RECORDING[] PROGMEM = "Kaydediyor"; 9 | const char S_SELECT_RECORD_MODE[] PROGMEM = "Isim modu:"; 10 | const char S_REC_MODE_MANUAL[] PROGMEM = "Manuel"; 11 | const char S_REC_MODE_AUTO[] PROGMEM = "Otomatik"; 12 | const char S_ENTER_FILENAME[] PROGMEM = "Isim girin"; 13 | 14 | const char S_INIT[] PROGMEM = "Basliyor..."; 15 | const char S_INIT_FAILED[] PROGMEM = "Baslama hatasi!"; 16 | const char S_INIT_OK[] PROGMEM = "Baslama TAMAM."; 17 | 18 | const char S_NO_FILES_FOUND[] PROGMEM = "Hic dosya yok!"; 19 | const char S_SELECT_FILE[] PROGMEM = "Dosya sec:"; 20 | const char S_SELECT_MODE[] PROGMEM = "Mod sec:"; 21 | const char S_MODE_PLAY[] PROGMEM = "Oynat"; 22 | const char S_MODE_RECORD[] PROGMEM = "Kaydet"; 23 | const char S_READY_RECORD[] PROGMEM = "Hazir..."; 24 | const char S_PRESS_START[] PROGMEM = "BASLA tusuna bas"; 25 | 26 | const char S_MODE_OPTIONS[] PROGMEM = "Secenekler"; 27 | const char S_OPTION_SIGNAL[] PROGMEM = "Ters cevir"; 28 | const char S_OPTION_KEY_REPEAT[] PROGMEM = "Tus hizi"; 29 | const char S_OPTION_TICKER_SPEED[] PROGMEM = "Kayma hizi"; 30 | const char S_OPTION_TICKER_HOLD[] PROGMEM = "Kayma bekleme"; 31 | const char S_OPTION_REC_FINALIZE[] PROGMEM = "Kaydi sonlandir"; 32 | 33 | const char S_MKDIR_FAILED[] PROGMEM = "MKDIR hatasi!"; 34 | const char S_CHDIR_FAILED[] PROGMEM = "CHDIR hatasi!"; 35 | const char S_READ_FAILED[] PROGMEM = "OKUMA hatasi!"; 36 | const char S_OPEN_FAILED[] PROGMEM = "ACMA hatasi!"; 37 | const char S_INVALID_TAP[] PROGMEM = "Gecersiz TAP!"; 38 | const char S_INVALID_SIZE[] PROGMEM = "Gecersiz boyut!"; 39 | 40 | const char S_LOADING[] PROGMEM = "Yukleniyor:"; 41 | const char S_OPERATION_COMPLETE[] PROGMEM = "Tamamlandi!"; 42 | const char S_OPERATION_ABORTED[] PROGMEM = "Vazgecildi!"; 43 | 44 | const char S_OPTION_MACHINE_TYPE[] PROGMEM = "Makine"; 45 | const char S_OPTION_VIDEO_MODE[] PROGMEM = "Video"; 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /layout/TapuinoMini1.03/gerbers/TapuinoMini.TXT: -------------------------------------------------------------------------------- 1 | % 2 | M48 3 | M72 4 | T01C0.02362 5 | T02C0.02800 6 | T03C0.03200 7 | T04C0.03500 8 | T05C0.04000 9 | T06C0.05900 10 | T07C0.11024 11 | % 12 | T01 13 | X120000Y97500 14 | X120000Y115000 15 | X105000Y90000 16 | X105000Y115000 17 | X47500Y102500 18 | X60000Y115000 19 | X75000Y115000 20 | X90000Y82500 21 | X90000Y115000 22 | X135000Y92500 23 | X135000Y115000 24 | T02 25 | X40000Y57500 26 | X40000Y27500 27 | X133750Y57500 28 | X139750Y52500 29 | X133750Y47500 30 | X135500Y27500 31 | X129500Y32500 32 | X135500Y37500 33 | X90000Y50000 34 | X120000Y50000 35 | X90000Y42500 36 | X120000Y42500 37 | X120000Y57500 38 | X90000Y57500 39 | X120000Y35000 40 | X90000Y35000 41 | T03 42 | X52500Y27500 43 | X62500Y27500 44 | X62500Y57500 45 | X52500Y57500 46 | X72500Y27500 47 | X72500Y57500 48 | T04 49 | X110000Y2500 50 | X120000Y2500 51 | X130000Y2500 52 | X140000Y2500 53 | X7500Y67500 54 | X7500Y57500 55 | X7500Y47500 56 | X7500Y37500 57 | X7500Y27500 58 | X7500Y17500 59 | X130000Y72500 60 | X120000Y72500 61 | X110000Y72500 62 | X100000Y72500 63 | X90000Y72500 64 | X80000Y72500 65 | X70000Y72500 66 | X60000Y72500 67 | X50000Y72500 68 | X40000Y72500 69 | X30000Y72500 70 | X20000Y72500 71 | X20000Y12500 72 | X30000Y12500 73 | X40000Y12500 74 | X50000Y12500 75 | X60000Y12500 76 | X70000Y12500 77 | X80000Y12500 78 | X90000Y12500 79 | X100000Y12500 80 | X110000Y12500 81 | X120000Y12500 82 | X130000Y12500 83 | X20000Y32500 84 | X20000Y22500 85 | X95000Y22500 86 | X85000Y22500 87 | X157500Y92500 88 | X147500Y92500 89 | X185000Y92500 90 | X175000Y92500 91 | T05 92 | X13600Y-29900 93 | X31400Y-29900 94 | X63600Y-29900 95 | X81400Y-29900 96 | X163600Y-29900 97 | X181400Y-29900 98 | X113600Y-29900 99 | X131400Y-29900 100 | T06 101 | X8700Y-20100 102 | X36300Y-20100 103 | X58700Y-20100 104 | X86300Y-20100 105 | X158700Y-20100 106 | X186300Y-20100 107 | X108700Y-20100 108 | X136300Y-20100 109 | T07 110 | X12500Y112500 111 | X185000Y112500 112 | X187500Y-2500 113 | X10000Y0 114 | M30 115 | -------------------------------------------------------------------------------- /memstrings-en.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "config.h" 3 | #include "memstrings.h" 4 | 5 | #ifdef TAPUINO_LANGUAGE_EN 6 | 7 | const char S_DEFAULT_RECORD_DIR[] PROGMEM = "/recorded"; 8 | const char S_RECORDING[] PROGMEM = "Recording"; 9 | const char S_SELECT_RECORD_MODE[] PROGMEM = "Name mode:"; 10 | const char S_REC_MODE_MANUAL[] PROGMEM = "Manual"; 11 | const char S_REC_MODE_AUTO[] PROGMEM = "Auto"; 12 | const char S_ENTER_FILENAME[] PROGMEM = "Enter name"; 13 | 14 | const char S_INIT[] PROGMEM = "Init..."; 15 | const char S_INIT_FAILED[] PROGMEM = "Init failed!"; 16 | const char S_INIT_OK[] PROGMEM = "Init OK."; 17 | 18 | const char S_NO_FILES_FOUND[] PROGMEM = "No files found!"; 19 | const char S_SELECT_FILE[] PROGMEM = "Select file:"; 20 | const char S_SELECT_MODE[] PROGMEM = "Select mode:"; 21 | const char S_MODE_PLAY[] PROGMEM = "Play"; 22 | const char S_MODE_RECORD[] PROGMEM = "Record"; 23 | const char S_READY_RECORD[] PROGMEM = "Ready..."; 24 | const char S_PRESS_START[] PROGMEM = "Press START"; 25 | 26 | const char S_MODE_OPTIONS[] PROGMEM = "Options"; 27 | const char S_OPTION_SIGNAL[] PROGMEM = "Invert"; 28 | const char S_OPTION_KEY_REPEAT[] PROGMEM = "Key speed"; 29 | const char S_OPTION_TICKER_SPEED[] PROGMEM = "Ticker speed"; 30 | const char S_OPTION_TICKER_HOLD[] PROGMEM = "Ticker hold"; 31 | const char S_OPTION_REC_FINALIZE[] PROGMEM = "Record finalize"; 32 | const char S_OPTION_REC_AUTO_FINALIZE[] PROGMEM = "Auto finalize"; 33 | 34 | const char S_MKDIR_FAILED[] PROGMEM = "MKDIR fail!"; 35 | const char S_CHDIR_FAILED[] PROGMEM = "CHDIR fail!"; 36 | const char S_READ_FAILED[] PROGMEM = "READ fail!"; 37 | const char S_OPEN_FAILED[] PROGMEM = "OPEN fail!"; 38 | const char S_INVALID_TAP[] PROGMEM = "Invalid TAP!"; 39 | const char S_INVALID_SIZE[] PROGMEM = "Invalid size!"; 40 | 41 | const char S_LOADING[] PROGMEM = "Loading:"; 42 | const char S_OPERATION_COMPLETE[] PROGMEM = "Complete!"; 43 | const char S_OPERATION_ABORTED[] PROGMEM = "Aborted!"; 44 | 45 | const char S_OPTION_MACHINE_TYPE[] PROGMEM = "Machine"; 46 | const char S_OPTION_VIDEO_MODE[] PROGMEM = "Video"; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /memstrings-es.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "config.h" 3 | #include "memstrings.h" 4 | 5 | #ifdef TAPUINO_LANGUAGE_ES 6 | 7 | const char S_DEFAULT_RECORD_DIR[] PROGMEM = "/grabado"; 8 | const char S_RECORDING[] PROGMEM = "Grabando"; 9 | const char S_SELECT_RECORD_MODE[] PROGMEM = "Modo:"; 10 | const char S_REC_MODE_MANUAL[] PROGMEM = "Manual"; 11 | const char S_REC_MODE_AUTO[] PROGMEM = "Auto"; 12 | const char S_ENTER_FILENAME[] PROGMEM = "Teclear nombre"; 13 | 14 | const char S_INIT[] PROGMEM = "Inicializando..."; 15 | const char S_INIT_FAILED[] PROGMEM = "No Inicializado!"; 16 | const char S_INIT_OK[] PROGMEM = "Inicializado!"; 17 | 18 | const char S_NO_FILES_FOUND[] PROGMEM = "No hay ficheros!"; 19 | const char S_SELECT_FILE[] PROGMEM = "Escoger fichero:"; 20 | const char S_SELECT_MODE[] PROGMEM = "Modo:"; 21 | const char S_MODE_PLAY[] PROGMEM = "Reproducir"; 22 | const char S_MODE_RECORD[] PROGMEM = "Grabar"; 23 | const char S_READY_RECORD[] PROGMEM = "Preparado!..."; 24 | const char S_PRESS_START[] PROGMEM = "Pulsar START"; 25 | 26 | const char S_MODE_OPTIONS[] PROGMEM = "Opciones"; 27 | const char S_OPTION_SIGNAL[] PROGMEM = "Invertir"; 28 | const char S_OPTION_KEY_REPEAT[] PROGMEM = "Vel. Tecla"; 29 | const char S_OPTION_TICKER_SPEED[] PROGMEM = "Vel. Ticker"; 30 | const char S_OPTION_TICKER_HOLD[] PROGMEM = "Sos. Ticker"; 31 | const char S_OPTION_REC_FINALIZE[] PROGMEM = "Fin Grabacion"; 32 | const char S_OPTION_REC_AUTO_FINALIZE[] PROGMEM = "Auto-Finalizar"; 33 | 34 | const char S_MKDIR_FAILED[] PROGMEM = "Fallo en MKDIR!"; 35 | const char S_CHDIR_FAILED[] PROGMEM = "Fallo en CHDIR!"; 36 | const char S_READ_FAILED[] PROGMEM = "Fallo en READ!"; 37 | const char S_OPEN_FAILED[] PROGMEM = "Fallo en OPEN!"; 38 | const char S_INVALID_TAP[] PROGMEM = "TAP invalido!"; 39 | const char S_INVALID_SIZE[] PROGMEM = "Tamaño Invalido!"; 40 | 41 | const char S_LOADING[] PROGMEM = "Cargando:"; 42 | const char S_OPERATION_COMPLETE[] PROGMEM = "Completado!"; 43 | const char S_OPERATION_ABORTED[] PROGMEM = "Cancelado!"; 44 | 45 | const char S_OPTION_MACHINE_TYPE[] PROGMEM = "Tipo de maquina"; 46 | const char S_OPTION_VIDEO_MODE[] PROGMEM = "Video"; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /memstrings-de.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "config.h" 3 | #include "memstrings.h" 4 | 5 | #ifdef TAPUINO_LANGUAGE_DE 6 | 7 | const char S_DEFAULT_RECORD_DIR[] PROGMEM = "/aufnahmen"; 8 | const char S_RECORDING[] PROGMEM = "Aufnahme"; 9 | const char S_SELECT_RECORD_MODE[] PROGMEM = "Aufnahmemodus:"; 10 | const char S_REC_MODE_MANUAL[] PROGMEM = "Manuell"; 11 | const char S_REC_MODE_AUTO[] PROGMEM = "Automatisch"; 12 | const char S_ENTER_FILENAME[] PROGMEM = "Dateiname:"; 13 | 14 | const char S_INIT[] PROGMEM = "Starten..."; 15 | const char S_INIT_FAILED[] PROGMEM = "Fehler"; 16 | const char S_INIT_OK[] PROGMEM = "Start OK"; 17 | 18 | const char S_NO_FILES_FOUND[] PROGMEM = "Keine Dateien"; 19 | const char S_SELECT_FILE[] PROGMEM = "Datei waehlen:"; 20 | const char S_SELECT_MODE[] PROGMEM = "Modus waehlen:"; 21 | const char S_MODE_PLAY[] PROGMEM = "Laden"; 22 | const char S_MODE_RECORD[] PROGMEM = "Aufnehmen"; 23 | const char S_READY_RECORD[] PROGMEM = "Bereit..."; 24 | const char S_PRESS_START[] PROGMEM = "Druecke START"; 25 | 26 | const char S_MODE_OPTIONS[] PROGMEM = "Optionen"; 27 | const char S_OPTION_SIGNAL[] PROGMEM = "Invertieren"; 28 | const char S_OPTION_KEY_REPEAT[] PROGMEM = "Tastenwiederhlng"; 29 | const char S_OPTION_TICKER_SPEED[] PROGMEM = "Ticker-Geschw."; 30 | const char S_OPTION_TICKER_HOLD[] PROGMEM = "Ticker-Pause"; 31 | const char S_OPTION_REC_FINALIZE[] PROGMEM = "Finalisieren"; 32 | const char S_OPTION_REC_AUTO_FINALIZE[] PROGMEM = "Automatisch fin."; 33 | 34 | const char S_MKDIR_FAILED[] PROGMEM = "MKDIR Fehler"; 35 | const char S_CHDIR_FAILED[] PROGMEM = "CHDIR Fehler"; 36 | const char S_READ_FAILED[] PROGMEM = "READ Fehler"; 37 | const char S_OPEN_FAILED[] PROGMEM = "OPEN Fehler"; 38 | const char S_INVALID_TAP[] PROGMEM = "Ungueltiges TAP"; 39 | const char S_INVALID_SIZE[] PROGMEM = "Falsche Groesse"; 40 | 41 | const char S_LOADING[] PROGMEM = "Laden..."; 42 | const char S_OPERATION_COMPLETE[] PROGMEM = "Vollstaendig"; 43 | const char S_OPERATION_ABORTED[] PROGMEM = "Abbruch..."; 44 | 45 | const char S_OPTION_MACHINE_TYPE[] PROGMEM = "Computer-Typ"; 46 | const char S_OPTION_VIDEO_MODE[] PROGMEM = "Video-Standard"; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /memstrings-it.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "config.h" 3 | #include "memstrings.h" 4 | 5 | #ifdef TAPUINO_LANGUAGE_IT 6 | 7 | const char S_DEFAULT_RECORD_DIR[] PROGMEM = "/salvataggi"; 8 | const char S_RECORDING[] PROGMEM = "Recording"; 9 | const char S_SELECT_RECORD_MODE[] PROGMEM = "Nome file:"; 10 | const char S_REC_MODE_MANUAL[] PROGMEM = "Manuale"; 11 | const char S_REC_MODE_AUTO[] PROGMEM = "Automatico"; 12 | const char S_ENTER_FILENAME[] PROGMEM = "Inserisci nome"; 13 | 14 | const char S_INIT[] PROGMEM = "Avvio in corso.."; 15 | const char S_INIT_FAILED[] PROGMEM = "Avvio fallito!"; 16 | const char S_INIT_OK[] PROGMEM = "Avvio OK!"; 17 | 18 | const char S_NO_FILES_FOUND[] PROGMEM = "Nessun file!"; 19 | const char S_SELECT_FILE[] PROGMEM = "Scegli file:"; 20 | const char S_SELECT_MODE[] PROGMEM = "Scegli modo:"; 21 | const char S_MODE_PLAY[] PROGMEM = "Play"; 22 | const char S_MODE_RECORD[] PROGMEM = "Record"; 23 | const char S_READY_RECORD[] PROGMEM = "Pronto..."; 24 | const char S_PRESS_START[] PROGMEM = "Premi START"; 25 | 26 | const char S_MODE_OPTIONS[] PROGMEM = "Opzioni"; 27 | const char S_OPTION_SIGNAL[] PROGMEM = "Inverti"; 28 | const char S_OPTION_KEY_REPEAT[] PROGMEM = "Velocita' scorr."; 29 | const char S_OPTION_TICKER_SPEED[] PROGMEM = "Velocita' scroll"; 30 | const char S_OPTION_TICKER_HOLD[] PROGMEM = "Pausa scroll"; 31 | const char S_OPTION_REC_FINALIZE[] PROGMEM = "Pausa a fine REC"; 32 | const char S_OPTION_REC_AUTO_FINALIZE[] PROGMEM = "Auto finalizza"; 33 | 34 | const char S_MKDIR_FAILED[] PROGMEM = "Errore MKDIR!"; 35 | const char S_CHDIR_FAILED[] PROGMEM = "Errore CHDIR!"; 36 | const char S_READ_FAILED[] PROGMEM = "READ fallito!"; 37 | const char S_OPEN_FAILED[] PROGMEM = "OPEN fallito!"; 38 | const char S_INVALID_TAP[] PROGMEM = "TAP Invalido!"; 39 | const char S_INVALID_SIZE[] PROGMEM = "Dimens. invalida"; 40 | 41 | const char S_LOADING[] PROGMEM = "Loading:"; 42 | const char S_OPERATION_COMPLETE[] PROGMEM = "Completato!"; 43 | const char S_OPERATION_ABORTED[] PROGMEM = "Annullato!"; 44 | 45 | const char S_OPTION_MACHINE_TYPE[] PROGMEM = "Macchina"; 46 | const char S_OPTION_VIDEO_MODE[] PROGMEM = "Video"; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /fileutils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "ff.h" 4 | #include "config.h" 5 | #include "fileutils.h" 6 | 7 | #define DEFAULT_DIR "/" 8 | #define INVALID_FILE_ATTR (AM_VOL) 9 | 10 | 11 | FATFS g_fs; 12 | DIR g_dir; 13 | FIL g_fil; 14 | uint8_t g_fat_buffer[FAT_BUF_SIZE]; 15 | 16 | /*---------------------------------------------------------*/ 17 | /* User Provided RTC Function called by FatFs module */ 18 | 19 | DWORD get_fattime (void) { 20 | /* Returns current time packed into a DWORD variable */ 21 | return ((DWORD)(2014 - 1980) << 25) /* Year 2014 */ 22 | | ((DWORD)6 << 21) /* Month 6 */ 23 | | ((DWORD)1 << 16) /* Mday 1 */ 24 | | ((DWORD)0 << 11) /* Hour 0 */ 25 | | ((DWORD)0 << 5) /* Min 0 */ 26 | | ((DWORD)0 >> 1); /* Sec 0 */ 27 | } 28 | 29 | int is_valid_file(FILINFO* pfile_info) { 30 | char* file_name; 31 | int len; 32 | file_name = pfile_info->lfname[0] ? pfile_info->lfname : pfile_info->fname; 33 | len = strlen(file_name); 34 | 35 | if ((pfile_info->fattrib & INVALID_FILE_ATTR)) { 36 | return 0; 37 | } 38 | 39 | if ((pfile_info->fattrib & AM_DIR)) { 40 | return (file_name[0] != '.'); 41 | } 42 | 43 | if (len < 5) { 44 | return 0; 45 | } 46 | 47 | return 1; 48 | } 49 | 50 | int get_num_files(FILINFO* pfile_info) { 51 | int num_files = 0; 52 | if (!pfile_info) { 53 | return 0; 54 | } 55 | // rewind directory to first file 56 | if (f_readdir(&g_dir, 0) != FR_OK) { 57 | return 0; 58 | } 59 | 60 | while(1) { 61 | pfile_info->fname[0] = 0; 62 | if ((f_readdir(&g_dir, pfile_info) != FR_OK) || !pfile_info->fname[0]) { 63 | break; 64 | } 65 | 66 | if (!is_valid_file(pfile_info)) { 67 | continue; 68 | } 69 | 70 | num_files++; 71 | } 72 | return num_files; 73 | } 74 | 75 | int get_file_at_index(FILINFO* pfile_info, int index) { 76 | int cur_file_index = 0; 77 | 78 | if (!pfile_info) { 79 | return 0; 80 | } 81 | 82 | // rewind directory to first file 83 | if (f_readdir(&g_dir, 0) != FR_OK) { 84 | return 0; 85 | } 86 | 87 | while(1) { 88 | pfile_info->fname[0] = 0; 89 | if ((f_readdir(&g_dir, pfile_info) != FR_OK) || !pfile_info->fname[0]) { 90 | break; 91 | } 92 | 93 | if (!is_valid_file(pfile_info)) { 94 | continue; 95 | } 96 | 97 | if (cur_file_index == index) { 98 | return 1; 99 | } 100 | cur_file_index++; 101 | } 102 | return 0; 103 | } 104 | 105 | 106 | FRESULT change_dir(char* dir) { 107 | FRESULT fr = FR_OK; 108 | if ((fr = f_chdir(dir)) == FR_OK) { 109 | return f_opendir( &g_dir, "." ); 110 | } 111 | return fr; 112 | } 113 | -------------------------------------------------------------------------------- /diskio.h: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------/ 2 | / Low level disk interface modlue include file (C)ChaN, 2013 / 3 | /-----------------------------------------------------------------------*/ 4 | 5 | #ifndef _DISKIO_DEFINED 6 | #define _DISKIO_DEFINED 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | #define _USE_WRITE 1 /* 1: Enable disk_write function */ 13 | #define _USE_IOCTL 1 /* 1: Enable disk_ioctl fucntion */ 14 | 15 | #include "integer.h" 16 | 17 | 18 | /* Status of Disk Functions */ 19 | typedef BYTE DSTATUS; 20 | 21 | /* Results of Disk Functions */ 22 | typedef enum { 23 | RES_OK = 0, /* 0: Successful */ 24 | RES_ERROR, /* 1: R/W Error */ 25 | RES_WRPRT, /* 2: Write Protected */ 26 | RES_NOTRDY, /* 3: Not Ready */ 27 | RES_PARERR /* 4: Invalid Parameter */ 28 | } DRESULT; 29 | 30 | 31 | /*---------------------------------------*/ 32 | /* Prototypes for disk control functions */ 33 | 34 | 35 | DSTATUS disk_initialize (BYTE pdrv); 36 | DSTATUS disk_status (BYTE pdrv); 37 | DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); 38 | DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); 39 | DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); 40 | 41 | 42 | /* Disk Status Bits (DSTATUS) */ 43 | 44 | #define STA_NOINIT 0x01 /* Drive not initialized */ 45 | #define STA_NODISK 0x02 /* No medium in the drive */ 46 | #define STA_PROTECT 0x04 /* Write protected */ 47 | 48 | 49 | /* Command code for disk_ioctrl fucntion */ 50 | 51 | /* Generic command (used by FatFs) */ 52 | #define CTRL_SYNC 0 /* Flush disk cache (for write functions) */ 53 | #define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */ 54 | #define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */ 55 | #define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */ 56 | #define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */ 57 | 58 | /* Generic command (not used by FatFs) */ 59 | #define CTRL_POWER 5 /* Get/Set power status */ 60 | #define CTRL_LOCK 6 /* Lock/Unlock media removal */ 61 | #define CTRL_EJECT 7 /* Eject media */ 62 | #define CTRL_FORMAT 8 /* Create physical format on the media */ 63 | 64 | /* MMC/SDC specific ioctl command */ 65 | #define MMC_GET_TYPE 10 /* Get card type */ 66 | #define MMC_GET_CSD 11 /* Get CSD */ 67 | #define MMC_GET_CID 12 /* Get CID */ 68 | #define MMC_GET_OCR 13 /* Get OCR */ 69 | #define MMC_GET_SDSTAT 14 /* Get SD status */ 70 | 71 | /* ATA/CF specific ioctl command */ 72 | #define ATA_GET_REV 20 /* Get F/W revision */ 73 | #define ATA_GET_MODEL 21 /* Get model name */ 74 | #define ATA_GET_SN 22 /* Get serial number */ 75 | 76 | #ifdef __cplusplus 77 | } 78 | #endif 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /serial.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "config.h" 6 | #include "buffer.h" 7 | 8 | #ifdef ENABLE_SERIAL 9 | 10 | #define USART_BAUDRATE 57600 11 | #define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1) 12 | 13 | 14 | void serial_init( void ) 15 | { 16 | RingBuffer_InitBuffer( &comms_rx_buffer ); 17 | RingBuffer_InitBuffer( &comms_tx_buffer ); 18 | 19 | DDRD |= _BV( 1 ); 20 | UCSR0B |= _BV( RXEN0 ) | _BV( TXEN0 ); // Turn on the transmission and reception circuitry 21 | UCSR0C |= _BV( UCSZ00 ) | _BV( UCSZ01 ); // Use 8-bit character sizes 22 | UBRR0H = (unsigned char) (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register 23 | UBRR0L = (unsigned char) BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register 24 | 25 | UCSR0B |= _BV( RXCIE0 ); // Enable the USART Recieve Complete interrupt 26 | 27 | sei(); // Enable the Global Interrupt Enable flag so that interrupts can be processed 28 | } 29 | 30 | int serial_available( void ) 31 | { 32 | return( comms_rx_buffer.Count ); 33 | } 34 | 35 | void serial_write( char data ) 36 | { 37 | // wait for interrupt to clean 38 | while( RingBuffer_IsFull( &comms_tx_buffer ) ); 39 | RingBuffer_Insert( &comms_tx_buffer, data ); 40 | UCSR0B |= _BV( UDRIE0 ); 41 | } 42 | 43 | void serial_print( char* data ) 44 | { 45 | uint8_t v; 46 | while ((v = *data++)) { 47 | serial_write(v); 48 | } 49 | } 50 | 51 | void serial_print_P( const char* data ) 52 | { 53 | uint8_t v; 54 | while ((v = pgm_read_byte(data++))) { 55 | serial_write(v); 56 | } 57 | } 58 | 59 | static const char* hex = "0123456789ABCDEF"; 60 | void serial_printByte( unsigned char data ) 61 | { 62 | serial_write( hex[ ( data >> 4 ) & 0x0F ] ); 63 | serial_write( hex[ ( data & 0x0F ) ] ); 64 | } 65 | 66 | void serial_println( char* data ) 67 | { 68 | serial_print( data ); 69 | serial_write( '\n' ); 70 | } 71 | 72 | void serial_println_P( const char* data ) 73 | { 74 | serial_print_P( data ); 75 | serial_write( '\n' ); 76 | } 77 | 78 | char serial_read( void ) 79 | { 80 | RingBuff_Data_t data = RingBuffer_Remove( &comms_rx_buffer ); 81 | return( data ); 82 | } 83 | 84 | SIGNAL(USART_RX_vect) 85 | { 86 | char rx = UDR0; 87 | if( !RingBuffer_IsFull( &comms_rx_buffer ) ) 88 | { 89 | RingBuffer_Insert( &comms_rx_buffer, rx ); 90 | } 91 | } 92 | 93 | ISR(USART_UDRE_vect) 94 | { 95 | if( RingBuffer_IsEmpty( &comms_tx_buffer ) ) 96 | { 97 | UCSR0B &= ~_BV( UDRIE0 ); 98 | } 99 | else 100 | { 101 | UDR0 = RingBuffer_Remove( &comms_tx_buffer ); 102 | } 103 | } 104 | 105 | #endif //ENABLE_SERIAL 106 | 107 | -------------------------------------------------------------------------------- /disp_oled_SSD131x.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | #ifdef LCD_USE_SSD131X_OLED_MODULE 3 | 4 | #include 5 | #include "i2c_master.h" 6 | 7 | #define MODE_OLED_COMMAND 0x80 8 | #define MODE_OLED_DATA 0x40 9 | 10 | uint8_t _addr; 11 | 12 | void sendData(unsigned char data); 13 | void sendCommand(unsigned char command); 14 | void send_string(const char *String); 15 | 16 | 17 | void lcd_init(uint8_t lcd_addr) { 18 | _addr = lcd_addr; 19 | i2c_init(); 20 | 21 | // *** I2C initial *** // 22 | _delay_ms(100); 23 | sendCommand(0x2A); // **** Set "RE"=1 00101010B 24 | sendCommand(0x71); 25 | sendCommand(0x5C); 26 | sendCommand(0x28); 27 | 28 | sendCommand(0x08); // **** Set Sleep Mode On 29 | sendCommand(0x2A); // **** Set "RE"=1 00101010B 30 | sendCommand(0x79); // **** Set "SD"=1 01111001B 31 | 32 | sendCommand(0xD5); 33 | sendCommand(0x70); 34 | sendCommand(0x78); // **** Set "SD"=0 35 | 36 | sendCommand(0x08); // **** Set 5-dot, 3 or 4 line(0x09), 1 or 2 line(0x08) 37 | 38 | sendCommand(0x06); // **** Set Com31-->Com0 Seg0-->Seg99 39 | 40 | // **** Set OLED Characterization *** // 41 | sendCommand(0x2A); // **** Set "RE"=1 42 | sendCommand(0x79); // **** Set "SD"=1 43 | 44 | // **** CGROM/CGRAM Management *** // 45 | sendCommand(0x72); // **** Set ROM 46 | sendCommand(0x00); // **** Set ROM A and 8 CGRAM 47 | 48 | 49 | sendCommand(0xDA); // **** Set Seg Pins HW Config 50 | sendCommand(0x10); 51 | 52 | sendCommand(0x81); // **** Set Contrast 53 | sendCommand(0xFF); 54 | 55 | sendCommand(0xDB); // **** Set VCOM deselect level 56 | sendCommand(0x30); // **** VCC x 0.83 57 | 58 | sendCommand(0xDC); // **** Set gpio - turn EN for 15V generator on. 59 | sendCommand(0x03); 60 | 61 | sendCommand(0x78); // **** Exiting Set OLED Characterization 62 | sendCommand(0x28); 63 | sendCommand(0x2A); 64 | //sendCommand(0x05); // **** Set Entry Mode 65 | sendCommand(0x06); // **** Set Entry Mode 66 | sendCommand(0x08); 67 | sendCommand(0x28); // **** Set "IS"=0 , "RE" =0 //28 68 | sendCommand(0x01); 69 | sendCommand(0x80); // **** Set DDRAM Address to 0x80 (line 1 start) 70 | 71 | _delay_ms(100); 72 | sendCommand(0x0C); // **** Turn on Display 73 | } 74 | 75 | void sendData(uint8_t data) 76 | { 77 | i2c_start((_addr << 1) | I2C_WRITE); 78 | i2c_write(MODE_OLED_DATA); // **** Set OLED Command mode 79 | i2c_write(data); 80 | i2c_stop(); 81 | } 82 | 83 | void sendCommand(uint8_t command) 84 | { 85 | i2c_start((_addr << 1) | I2C_WRITE); 86 | i2c_write(MODE_OLED_COMMAND); // **** Set OLED Command mode 87 | i2c_write(command); 88 | i2c_stop(); 89 | _delay_ms(10); 90 | } 91 | 92 | 93 | void lcd_cursor() { 94 | sendCommand(0x0E); // **** Turn on Display, cursor 95 | } 96 | 97 | void lcd_noCursor(){ 98 | sendCommand(0x0C); // **** Turn on Display 99 | } 100 | 101 | void lcd_backlight(){ 102 | } 103 | 104 | void lcd_noBacklight(){ 105 | } 106 | 107 | void lcd_createChar(uint8_t location, uint8_t charmap[]){ 108 | } 109 | 110 | void lcd_setCursor(uint8_t col, uint8_t row){ 111 | int row_offsets[] = { 0x00, 0x40 }; 112 | sendCommand(0x80 | (col + row_offsets[row])); 113 | } 114 | 115 | void lcd_write(uint8_t value){ 116 | sendData(value); 117 | } 118 | 119 | void lcd_print(char* msg) { 120 | uint8_t v; 121 | while((v = *msg++)) { 122 | sendData(v); 123 | } 124 | //sendCommand(0xC0); // **** New Line 125 | } 126 | 127 | #endif -------------------------------------------------------------------------------- /lcdutils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "tapuino.h" 7 | #include "ff.h" 8 | #include "config.h" 9 | #include "lcd_interface.h" 10 | #include "lcdutils.h" 11 | #include "memstrings.h" 12 | 13 | // right arrow character 14 | #define DIRECTORY_INDICATOR 0b01111110 15 | 16 | char g_char_buffer[MAX_LCD_LINE_LEN + 1] = {0}; 17 | static uint8_t g_ticker_enabled = 0; 18 | static uint8_t g_ticker_index = 0; 19 | static uint32_t g_last_tick = 0; 20 | static uint32_t g_last_hold = 0; 21 | static char* g_ticker_string = NULL; 22 | 23 | void filename_ticker(FILINFO* pfile_info, uint32_t cur_tick) { 24 | if (g_ticker_enabled) { 25 | if (!g_last_tick) g_last_tick = cur_tick; 26 | 27 | // how often do we tick? 28 | if (cur_tick - g_last_tick < (uint32_t) g_ticker_rate) { 29 | return; 30 | } 31 | g_last_tick = cur_tick; 32 | 33 | if (!g_last_hold) g_last_hold = cur_tick; 34 | // how long do we hold? 35 | if (cur_tick - g_last_hold < (uint32_t) g_ticker_hold_rate) { 36 | return; 37 | } 38 | 39 | // is the filename within screen bounds? 40 | if ((strlen(g_ticker_string) - g_ticker_index) < MAX_LCD_LINE_LEN) { 41 | // how long do we hold at the end? 42 | if (cur_tick - g_last_hold < (uint32_t) (g_ticker_hold_rate << 1)) { 43 | return; 44 | } 45 | g_ticker_index = 0; 46 | g_last_tick = g_last_hold = 0; 47 | } else { 48 | //reset to avoid overflow 49 | g_last_hold = cur_tick - g_ticker_hold_rate - 1; 50 | g_ticker_index++; 51 | } 52 | 53 | lcd_status(&g_ticker_string[g_ticker_index]); 54 | if (pfile_info->fattrib & AM_DIR) { 55 | lcd_show_dir(); 56 | } 57 | } 58 | } 59 | 60 | void display_filename(FILINFO* pfile_info) { 61 | g_ticker_string = pfile_info->lfname[0] ? pfile_info->lfname : pfile_info->fname; 62 | lcd_status(g_ticker_string); 63 | if (pfile_info->fattrib & AM_DIR) { 64 | lcd_show_dir(); 65 | } 66 | g_ticker_enabled = strlen(g_ticker_string) > (MAX_LCD_LINE_LEN - 1); 67 | g_ticker_index = 0; 68 | g_last_tick = 0; 69 | g_last_hold = 0; 70 | } 71 | 72 | void lcd_spinner_internal(uint32_t cur_tick, uint8_t perc, uint16_t rate) { 73 | static uint8_t indicators[] = {'|', '/', '-', '\\'}; 74 | static uint8_t pos = 0; 75 | if (cur_tick - g_last_tick < rate) { 76 | return; 77 | } 78 | 79 | g_last_tick = cur_tick; 80 | lcd_setCursor(MAX_LCD_LINE_LEN - 7, 0); 81 | memset(g_char_buffer, 32, 7); 82 | if (perc < 101) { 83 | uint8_t off = perc < 10 ? 2 : perc < 100 ? 1 : 0; 84 | itoa(perc, g_char_buffer + off, 10); 85 | g_char_buffer[3] = '%'; 86 | } 87 | g_char_buffer[5] = g_is_paused ? 'P' : MOTOR_IS_OFF() ? 'm' : 'M'; 88 | g_char_buffer[6] = indicators[pos++]; 89 | g_char_buffer[7] = 0; 90 | lcd_print(g_char_buffer); 91 | 92 | if (pos > 3) { 93 | pos = 0; 94 | } 95 | } 96 | 97 | void lcd_spinner(uint32_t cur_tick, int8_t perc) { 98 | lcd_spinner_internal(cur_tick, perc, g_ticker_rate); 99 | } 100 | 101 | void lcd_busy_spinner() { 102 | uint8_t i; 103 | for (i = 0; i < 100; i++) { 104 | lcd_spinner_internal(i, 101, 0); 105 | _delay_ms(20); 106 | } 107 | } 108 | 109 | void lcd_show_dir() { 110 | lcd_setCursor(MAX_LCD_LINE_LEN - 1, 1); 111 | lcd_write(DIRECTORY_INDICATOR); 112 | } 113 | 114 | void lcd_line(char* msg, int line, uint8_t usepgm) { 115 | int len; 116 | memset(g_char_buffer, 32, MAX_LCD_LINE_LEN); 117 | g_char_buffer[MAX_LCD_LINE_LEN] = 0; 118 | 119 | lcd_setCursor(0, line); 120 | if (usepgm) { 121 | len = strlen_P(msg); 122 | memcpy_P(g_char_buffer, msg, len > MAX_LCD_LINE_LEN ? MAX_LCD_LINE_LEN : len); 123 | } else { 124 | len = strlen(msg); 125 | memcpy(g_char_buffer, msg, len > MAX_LCD_LINE_LEN ? MAX_LCD_LINE_LEN : len); 126 | } 127 | lcd_print(g_char_buffer); 128 | } 129 | 130 | void lcd_title(char* msg) { 131 | lcd_line(msg, 0, 0); 132 | } 133 | 134 | void lcd_title_P(const char* msg) { 135 | lcd_line((char*)msg, 0, 1); 136 | } 137 | 138 | void lcd_status(char* msg) { 139 | lcd_line(msg, 1, 0); 140 | } 141 | 142 | void lcd_status_P(const char* msg) { 143 | lcd_line((char*)msg, 1, 1); 144 | } 145 | 146 | void lcd_setup() { 147 | lcd_init(LCD_I2C_ADDR); 148 | lcd_backlight(); 149 | } 150 | -------------------------------------------------------------------------------- /comms.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "tapuino.h" 4 | #include "config.h" 5 | #include "comms.h" 6 | 7 | volatile uint8_t g_cur_command = COMMAND_IDLE; 8 | 9 | // repeat needed on all keys for short/long on select/abort and repeat on prev/next 10 | #define REPEAT_MASK (_BV(KEY_SELECT_PIN) | _BV(KEY_ABORT_PIN) | _BV(KEY_PREV_PIN) | _BV(KEY_NEXT_PIN)) 11 | volatile unsigned char key_press = 0; 12 | volatile unsigned char key_state = 0; 13 | volatile unsigned char key_rpt = 0; 14 | 15 | /*-------------------------------------------------------------------------- 16 | FUNC: 8/1/11 - Used to read debounced button presses 17 | PARAMS: A keymask corresponding to the pin for the button you with to poll 18 | RETURNS: A keymask where any high bits represent a button press 19 | --------------------------------------------------------------------------*/ 20 | unsigned char get_key_press( unsigned char key_mask ) { 21 | // cli(); // read and clear atomic ! 22 | key_mask &= key_press; // read key(s) 23 | key_press ^= key_mask; // clear key(s) 24 | // sei(); 25 | return key_mask; 26 | } 27 | 28 | /*-------------------------------------------------------------------------- 29 | FUNC: 8/1/11 - Used to check for debounced buttons that are held down 30 | PARAMS: A keymask corresponding to the pin for the button you with to poll 31 | RETURNS: A keymask where any high bits is a button held long enough for 32 | its input to be repeated 33 | --------------------------------------------------------------------------*/ 34 | unsigned char get_key_rpt( unsigned char key_mask ) { 35 | // cli(); // read and clear atomic ! 36 | key_mask &= key_rpt; // read key(s) 37 | key_rpt ^= key_mask; // clear key(s) 38 | // sei(); 39 | return key_mask; 40 | } 41 | 42 | /*-------------------------------------------------------------------------- 43 | FUNC: 8/1/11 - Used to read debounced button released after a short press 44 | PARAMS: A keymask corresponding to the pin for the button you with to poll 45 | RETURNS: A keymask where any high bits represent a quick press and release 46 | --------------------------------------------------------------------------*/ 47 | unsigned char get_key_short( unsigned char key_mask ) 48 | { 49 | //cli(); // read key state and key press atomic ! 50 | return get_key_press( ~key_state & key_mask ); 51 | } 52 | 53 | /*-------------------------------------------------------------------------- 54 | FUNC: 8/1/11 - Used to read debounced button held for REPEAT_START amount 55 | of time. 56 | PARAMS: A keymask corresponding to the pin for the button you with to poll 57 | RETURNS: A keymask where any high bits represent a long button press 58 | --------------------------------------------------------------------------*/ 59 | unsigned char get_key_long( unsigned char key_mask ) 60 | { 61 | return get_key_press( get_key_rpt( key_mask )); 62 | } 63 | 64 | void player_handleInputKeys() { 65 | if (get_key_short(_BV(KEY_SELECT_PIN))) { 66 | g_cur_command = COMMAND_SELECT; 67 | } 68 | 69 | if (get_key_short(_BV(KEY_ABORT_PIN))) { 70 | g_cur_command = COMMAND_ABORT; 71 | } 72 | 73 | if (get_key_long(_BV(KEY_SELECT_PIN))) { 74 | g_cur_command = COMMAND_SELECT_LONG; 75 | } 76 | 77 | if (get_key_long(_BV(KEY_ABORT_PIN))) { 78 | g_cur_command = COMMAND_ABORT_LONG; 79 | } 80 | 81 | if (get_key_press(_BV(KEY_PREV_PIN)) || get_key_rpt(_BV(KEY_PREV_PIN))) { 82 | g_cur_command = COMMAND_PREVIOUS; 83 | } 84 | 85 | if (get_key_press(_BV(KEY_NEXT_PIN)) || get_key_rpt(_BV(KEY_NEXT_PIN))) { 86 | g_cur_command = COMMAND_NEXT; 87 | } 88 | } 89 | 90 | void input_callback() 91 | { 92 | static unsigned char ct0, ct1, rpt; 93 | unsigned char i; 94 | 95 | // key changed ? 96 | #ifdef KEYS_INPUT_PULLUP 97 | i = key_state ^ ~KEYS_READ_PINS; // HW V2.0 for internal pullup the reading is inverted 98 | #else 99 | i = key_state ^ KEYS_READ_PINS; // HW V1.0 normal read 100 | #endif 101 | 102 | ct0 = ~( ct0 & i ); // reset or count ct0 103 | ct1 = ct0 ^ (ct1 & i); // reset or count ct1 104 | i &= ct0 & ct1; // count until roll over ? 105 | key_state ^= i; // then toggle debounced state 106 | key_press |= key_state & i; // 0->1: key press detect 107 | 108 | if( (key_state & REPEAT_MASK) == 0 ) // check repeat function 109 | rpt = (KEY_REPEAT_START / 10); // start delay 110 | if( --rpt == 0 ){ 111 | rpt = g_key_repeat_next; // repeat delay 112 | key_rpt |= key_state & REPEAT_MASK; 113 | } 114 | player_handleInputKeys(); 115 | } 116 | 117 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _CONFIG_H 3 | #define _CONFIG_H 4 | 5 | #include "config-user.h" 6 | 7 | // thanks stack overflow: http://stackoverflow.com/questions/4301471/c-macro-to-test-if-more-than-one-defined 8 | #if defined(LCD_USE_SSD1306_OLED_MODULE) + defined(LCD_USE_1602_LCD_MODULE) + defined(LCD_USE_SSD131X_OLED_MODULE) != 1 9 | #error Ether no or multiple LCD types defined! Have you created your config-user.h file? 10 | #endif 11 | 12 | #if defined(LCD_USE_SSD1306_OLED_MODULE) 13 | #if defined(LCD_SSD1306_128x64) + defined(LCD_SSD1306_128x32) != 1 14 | #error When using the SSD1306 module, define EITHER: LCD_SSD1306_128x64 or LCD_SSD1306_128x32 depending on your module type 15 | #endif 16 | #endif 17 | 18 | #if defined(TAPUINO_LANGUAGE_EN) + defined(TAPUINO_LANGUAGE_ES) + defined(TAPUINO_LANGUAGE_IT) + defined(TAPUINO_LANGUAGE_TR) + defined(TAPUINO_LANGUAGE_DE) != 1 19 | #error Either no or multiple languages defined! Have you created your config-user.h file? 20 | #endif 21 | 22 | 23 | #define LCD_BIT_RS 0 // Register select 24 | #define LCD_BIT_RW 1 // Read / Write 25 | #define LCD_BIT_EN 2 // Enable 26 | #define LCD_BIT_BACKLIGHT 3 // Backlight 27 | #define LCD_BIT_DATA0 4 // 4 bit data, bit 0 28 | #define LCD_BIT_DATA1 5 // 4 bit data, bit 1 29 | #define LCD_BIT_DATA2 6 // 4 bit data, bit 2 30 | #define LCD_BIT_DATA3 7 // 4 bit data, bit 3 31 | // LCD dimensions config 32 | #define LCD_NUM_LINES 2 // number of display lines on the LCD 33 | #define MAX_LCD_LINE_LEN 16 // max number of characters on a line 34 | 35 | // Timing constant defaults, these will only apply until eeprom values are saved 36 | #define TICKER_RATE 250 // milliseconds, granularity 10ms 37 | #define TICKER_HOLD 1250 // milliseconds, ticker begin and end hold time, granularity 10ms 38 | #define KEY_REPEAT_START 500 // milliseconds, granularity 10ms 39 | #define KEY_REPEAT_NEXT 300 // milliseconds, granularity 10ms 40 | #define REC_FINALIZE_TIME 2000 // milliseconds, granularity 10ms 41 | 42 | // TWI for pullups 43 | #define TWI_PORT PORTC 44 | #define TWI_PIN_SDA 4 45 | #define TWI_PIN_SCL 5 46 | 47 | // port definitions, change for different wiring 48 | #define TAPE_READ_PORT PORTD 49 | #define TAPE_READ_DDR DDRD 50 | #define TAPE_READ_PIN 3 51 | #define TAPE_READ_PINS PIND 52 | #define TAPE_READ_LOW() TAPE_READ_PORT &= ~_BV(TAPE_READ_PIN) 53 | #define TAPE_READ_HIGH() TAPE_READ_PORT |= _BV(TAPE_READ_PIN) 54 | 55 | #define TAPE_WRITE_PORT PORTB 56 | #define TAPE_WRITE_DDR DDRB 57 | #define TAPE_WRITE_PINS PINB 58 | #define TAPE_WRITE_PIN 0 59 | 60 | /* The Sense pin on the original Datassette is a physical switch that only grounds the line when pressed, it's left 61 | * floating when no keys are pressed. This means that the pin should be driven in an open-collector fashion, otherwise 62 | * it can create problems, in particular on the Plus/4 where the Sense line is shared with data pin 2 of the User Port. 63 | * 64 | * This could be compensated in hardware (put a diode in series, cathode to Arduino side) or in software, by taking 65 | * advantage of the way ATmega pins are configured, which is what we do here: 66 | * - To set sense "high" we set the pin to input mode, pin will go Hi-Z and basically float 67 | * - To set it low, we switch to output mode which will implicitly be low (PORTD defaults to 0 and we never touch it) 68 | */ 69 | #define SENSE_PORT PORTD 70 | #define SENSE_DDR DDRD 71 | #define SENSE_PIN 5 72 | #define SENSE_ON() SENSE_DDR |= _BV(SENSE_PIN) 73 | #define SENSE_OFF() SENSE_DDR &= ~_BV(SENSE_PIN) 74 | 75 | #define MOTOR_PORT PORTD 76 | #define MOTOR_DDR DDRD 77 | #define MOTOR_PIN 4 78 | #define MOTOR_PINS PIND 79 | #define MOTOR_IS_OFF() (MOTOR_PINS & _BV(MOTOR_PIN)) 80 | 81 | #define CONTROL_PORT PORTD 82 | #define CONTROL_DDR DDRD 83 | #define CONTROL_PIN0 6 84 | #define CONTROL_PIN1 7 85 | #define CONTROL_SET_BUS0() CONTROL_PORT &= ~(_BV(CONTROL_PIN0) | _BV(CONTROL_PIN1)) 86 | #define CONTROL_SET_BUS1() { CONTROL_PORT &= ~_BV(CONTROL_PIN1); CONTROL_PORT |= _BV(CONTROL_PIN0); } 87 | 88 | #define REC_LED_PORT PORTD 89 | #define REC_LED_DDR DDRD 90 | #define REC_LED_PIN 2 91 | #define REC_LED_OFF() REC_LED_PORT |= _BV(REC_LED_PIN) 92 | #define REC_LED_ON() REC_LED_PORT &= ~_BV(REC_LED_PIN) 93 | 94 | // comment this line if you are using HW1.0 95 | #define KEYS_INPUT_PULLUP 96 | #define KEYS_READ_PORT PORTC 97 | #define KEYS_READ_DDR DDRC 98 | #define KEYS_READ_PINS PINC 99 | #define KEY_SELECT_PIN 3 100 | #define KEY_ABORT_PIN 2 101 | #define KEY_PREV_PIN 1 102 | #define KEY_NEXT_PIN 0 103 | 104 | // debugging 105 | //#define ENABLE_SERIAL 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /i2c_master.h: -------------------------------------------------------------------------------- 1 | #ifndef _I2CMASTER_H 2 | #define _I2CMASTER_H 1 3 | /************************************************************************* 4 | * Title: C include file for the I2C master interface 5 | * (i2cmaster.S or twimaster.c) 6 | * Author: Peter Fleury http://jump.to/fleury 7 | * File: $Id: i2cmaster.h,v 1.10 2005/03/06 22:39:57 Peter Exp $ 8 | * Software: AVR-GCC 3.4.3 / avr-libc 1.2.3 9 | * Target: any AVR device 10 | * Usage: see Doxygen manual 11 | **************************************************************************/ 12 | 13 | #ifdef DOXYGEN 14 | /** 15 | @defgroup pfleury_ic2master I2C Master library 16 | @code #include @endcode 17 | 18 | @brief I2C (TWI) Master Software Library 19 | 20 | Basic routines for communicating with I2C slave devices. This single master 21 | implementation is limited to one bus master on the I2C bus. 22 | 23 | This I2c library is implemented as a compact assembler software implementation of the I2C protocol 24 | which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c). 25 | Since the API for these two implementations is exactly the same, an application can be linked either against the 26 | software I2C implementation or the hardware I2C implementation. 27 | 28 | Use 4.7k pull-up resistor on the SDA and SCL pin. 29 | 30 | Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module 31 | i2cmaster.S to your target when using the software I2C implementation ! 32 | 33 | Adjust the CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion. 34 | 35 | @note 36 | The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted 37 | to GNU assembler and AVR-GCC C call interface. 38 | Replaced the incorrect quarter period delays found in AVR300 with 39 | half period delays. 40 | 41 | @author Peter Fleury pfleury@gmx.ch http://jump.to/fleury 42 | 43 | @par API Usage Example 44 | The following code shows typical usage of this library, see example test_i2cmaster.c 45 | 46 | @code 47 | 48 | #include 49 | 50 | 51 | #define Dev24C02 0xA2 // device address of EEPROM 24C02, see datasheet 52 | 53 | int main(void) 54 | { 55 | unsigned char ret; 56 | 57 | i2c_init(); // initialize I2C library 58 | 59 | // write 0x75 to EEPROM address 5 (Byte Write) 60 | i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode 61 | i2c_write(0x05); // write address = 5 62 | i2c_write(0x75); // write value 0x75 to EEPROM 63 | i2c_stop(); // set stop conditon = release bus 64 | 65 | 66 | // read previously written value back from EEPROM address 5 67 | i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode 68 | 69 | i2c_write(0x05); // write address = 5 70 | i2c_rep_start(Dev24C02+I2C_READ); // set device address and read mode 71 | 72 | ret = i2c_readNak(); // read one byte from EEPROM 73 | i2c_stop(); 74 | 75 | for(;;); 76 | } 77 | @endcode 78 | 79 | */ 80 | #endif /* DOXYGEN */ 81 | 82 | /**@{*/ 83 | 84 | #if (__GNUC__ * 100 + __GNUC_MINOR__) < 304 85 | #error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !" 86 | #endif 87 | 88 | #include 89 | 90 | /** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */ 91 | #define I2C_READ 1 92 | 93 | /** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */ 94 | #define I2C_WRITE 0 95 | 96 | 97 | /** 98 | @brief initialize the I2C master interace. Need to be called only once 99 | @param void 100 | @return none 101 | */ 102 | extern void i2c_init(void); 103 | 104 | 105 | /** 106 | @brief Terminates the data transfer and releases the I2C bus 107 | @param void 108 | @return none 109 | */ 110 | extern void i2c_stop(void); 111 | 112 | 113 | /** 114 | @brief Issues a start condition and sends address and transfer direction 115 | 116 | @param addr address and transfer direction of I2C device 117 | @retval 0 device accessible 118 | @retval 1 failed to access device 119 | */ 120 | extern unsigned char i2c_start(unsigned char addr); 121 | 122 | 123 | /** 124 | @brief Issues a repeated start condition and sends address and transfer direction 125 | 126 | @param addr address and transfer direction of I2C device 127 | @retval 0 device accessible 128 | @retval 1 failed to access device 129 | */ 130 | extern unsigned char i2c_rep_start(unsigned char addr); 131 | 132 | 133 | /** 134 | @brief Issues a start condition and sends address and transfer direction 135 | 136 | If device is busy, use ack polling to wait until device ready 137 | @param addr address and transfer direction of I2C device 138 | @return none 139 | */ 140 | extern void i2c_start_wait(unsigned char addr); 141 | 142 | 143 | /** 144 | @brief Send one byte to I2C device 145 | @param data byte to be transfered 146 | @retval 0 write successful 147 | @retval 1 write failed 148 | */ 149 | extern unsigned char i2c_write(unsigned char data); 150 | 151 | 152 | /** 153 | @brief read one byte from the I2C device, request more data from device 154 | @return byte read from I2C device 155 | */ 156 | extern unsigned char i2c_readAck(void); 157 | 158 | /** 159 | @brief read one byte from the I2C device, read is followed by a stop condition 160 | @return byte read from I2C device 161 | */ 162 | extern unsigned char i2c_readNak(void); 163 | 164 | /** 165 | @brief read one byte from the I2C device 166 | 167 | Implemented as a macro, which calls either i2c_readAck or i2c_readNak 168 | 169 | @param ack 1 send ack, request more data from device
170 | 0 send nak, read is followed by a stop condition 171 | @return byte read from I2C device 172 | */ 173 | extern unsigned char i2c_read(unsigned char ack); 174 | #define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak(); 175 | 176 | 177 | /**@}*/ 178 | #endif 179 | -------------------------------------------------------------------------------- /LightweightRingBuff.h: -------------------------------------------------------------------------------- 1 | /* 2 | LUFA Library 3 | Copyright (C) Dean Camera, 2010. 4 | 5 | dean [at] fourwalledcubicle [dot] com 6 | www.fourwalledcubicle.com 7 | */ 8 | 9 | /* 10 | Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) 11 | 12 | Permission to use, copy, modify, distribute, and sell this 13 | software and its documentation for any purpose is hereby granted 14 | without fee, provided that the above copyright notice appear in 15 | all copies and that both that the copyright notice and this 16 | permission notice and warranty disclaimer appear in supporting 17 | documentation, and that the name of the author not be used in 18 | advertising or publicity pertaining to distribution of the 19 | software without specific, written prior permission. 20 | 21 | The author disclaim all warranties with regard to this 22 | software, including all implied warranties of merchantability 23 | and fitness. In no event shall the author be liable for any 24 | special, indirect or consequential damages or any damages 25 | whatsoever resulting from loss of use, data or profits, whether 26 | in an action of contract, negligence or other tortious action, 27 | arising out of or in connection with the use or performance of 28 | this software. 29 | */ 30 | 31 | /** \file 32 | * 33 | * Ultra lightweight ring buffer, for fast insertion/deletion. This uses inlined functions 34 | * for maximum speed. All buffers created with this library must be of the same size, however 35 | * multiple independant buffers can be created. 36 | * 37 | * Note that for each buffer, insertion and removal operations may occur at the same time (via 38 | * a multithreaded ISR based system) however the same kind of operation (two or more insertions 39 | * or deletions) must not overlap. If there is possibility of two or more of the same kind of 40 | * operating occuring at the same point in time, atomic (mutex) locking should be used. 41 | */ 42 | 43 | #ifndef _ULW_RING_BUFF_H_ 44 | #define _ULW_RING_BUFF_H_ 45 | 46 | /* Includes: */ 47 | //#include 48 | #define ATOMIC_BLOCK(x) 49 | 50 | #include 51 | #include 52 | 53 | /* Defines: */ 54 | /** Size of each ring buffer, in data elements - must be between 1 and 255. */ 55 | #define BUFFER_SIZE 32 56 | 57 | /** Type of data to store into the buffer. */ 58 | #define RingBuff_Data_t uint8_t 59 | 60 | /** Datatype which may be used to store the count of data stored in a buffer, retrieved 61 | * via a call to \ref RingBuffer_GetCount(). 62 | */ 63 | #if (BUFFER_SIZE <= 0xFF) 64 | #define RingBuff_Count_t uint8_t 65 | #else 66 | #define RingBuff_Count_t uint16_t 67 | #endif 68 | 69 | /* Type Defines: */ 70 | /** Type define for a new ring buffer object. Buffers should be initialized via a call to 71 | * \ref RingBuffer_InitBuffer() before use. 72 | */ 73 | typedef struct 74 | { 75 | RingBuff_Data_t Buffer[BUFFER_SIZE]; /**< Internal ring buffer data, referenced by the buffer pointers. */ 76 | volatile RingBuff_Data_t* In; /**< Current storage location in the circular buffer */ 77 | volatile RingBuff_Data_t* Out; /**< Current retrieval location in the circular buffer */ 78 | volatile RingBuff_Count_t Count; 79 | } RingBuff_t; 80 | 81 | /* Inline Functions: */ 82 | /** Initializes a ring buffer ready for use. Buffers must be initialized via this function 83 | * before any operations are called upon them. Already initialized buffers may be reset 84 | * by re-initializing them using this function. 85 | * 86 | * \param[out] Buffer Pointer to a ring buffer structure to initialize 87 | */ 88 | static inline void RingBuffer_InitBuffer(RingBuff_t* const Buffer) 89 | { 90 | Buffer->In = Buffer->Buffer; 91 | Buffer->Out = Buffer->Buffer; 92 | Buffer->Count = 0; 93 | } 94 | 95 | 96 | /** Atomically determines if the specified ring buffer contains any free space. This should 97 | * be tested before storing data to the buffer, to ensure that no data is lost due to a 98 | * buffer overrun. 99 | * 100 | * \param[in,out] Buffer Pointer to a ring buffer structure to insert into 101 | * 102 | * \return Boolean true if the buffer contains no free space, false otherwise 103 | */ 104 | static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer) 105 | { 106 | return (Buffer->Count == BUFFER_SIZE); 107 | } 108 | 109 | /** Atomically determines if the specified ring buffer contains any data. This should 110 | * be tested before removing data from the buffer, to ensure that the buffer does not 111 | * underflow. 112 | * 113 | * If the data is to be removed in a loop, store the total number of bytes stored in the 114 | * buffer (via a call to the \ref RingBuffer_GetCount() function) in a temporary variable 115 | * to reduce the time spent in atomicity locks. 116 | * 117 | * \param[in,out] Buffer Pointer to a ring buffer structure to insert into 118 | * 119 | * \return Boolean true if the buffer contains no free space, false otherwise 120 | */ 121 | static inline bool RingBuffer_IsEmpty(RingBuff_t* const Buffer) 122 | { 123 | return (Buffer->Count == 0); 124 | } 125 | 126 | /** Inserts an element into the ring buffer. 127 | * 128 | * \note Only one execution thread (main program thread or an ISR) may insert into a single buffer 129 | * otherwise data corruption may occur. Insertion and removal may occur from different execution 130 | * threads. 131 | * 132 | * \param[in,out] Buffer Pointer to a ring buffer structure to insert into 133 | * \param[in] Data Data element to insert into the buffer 134 | */ 135 | static inline void RingBuffer_Insert(RingBuff_t* const Buffer, 136 | const RingBuff_Data_t Data) 137 | { 138 | *Buffer->In = Data; 139 | 140 | if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE]) 141 | Buffer->In = Buffer->Buffer; 142 | 143 | Buffer->Count++; 144 | } 145 | 146 | /** Removes an element from the ring buffer. 147 | * 148 | * \note Only one execution thread (main program thread or an ISR) may remove from a single buffer 149 | * otherwise data corruption may occur. Insertion and removal may occur from different execution 150 | * threads. 151 | * 152 | * \param[in,out] Buffer Pointer to a ring buffer structure to retrieve from 153 | * 154 | * \return Next data element stored in the buffer 155 | */ 156 | static inline RingBuff_Data_t RingBuffer_Remove(RingBuff_t* const Buffer) 157 | { 158 | RingBuff_Data_t Data = *Buffer->Out; 159 | 160 | if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE]) 161 | Buffer->Out = Buffer->Buffer; 162 | 163 | Buffer->Count--; 164 | 165 | return Data; 166 | } 167 | 168 | #endif 169 | -------------------------------------------------------------------------------- /i2c_master.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * Title: I2C master library using hardware TWI interface 3 | * Author: Peter Fleury http://jump.to/fleury 4 | * File: $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $ 5 | * Software: AVR-GCC 3.4.3 / avr-libc 1.2.3 6 | * Target: any AVR device with hardware TWI 7 | * Usage: API compatible with I2C Software Library i2cmaster.h 8 | **************************************************************************/ 9 | #include 10 | #include 11 | 12 | #include "i2c_master.h" 13 | 14 | 15 | /* define CPU frequency in Mhz here if not defined in Makefile */ 16 | #ifndef F_CPU 17 | #define F_CPU 4000000UL 18 | #endif 19 | 20 | /* I2C clock in Hz */ 21 | #define SCL_CLOCK 10000UL 22 | 23 | 24 | /************************************************************************* 25 | Initialization of the I2C bus interface. Need to be called only once 26 | *************************************************************************/ 27 | void i2c_init(void) 28 | { 29 | /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */ 30 | 31 | TWSR = 0; /* no prescaler */ 32 | TWBR = (uint8_t) ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */ 33 | 34 | }/* i2c_init */ 35 | 36 | 37 | /************************************************************************* 38 | Issues a start condition and sends address and transfer direction. 39 | return 0 = device accessible, 1= failed to access device 40 | *************************************************************************/ 41 | unsigned char i2c_start(unsigned char address) 42 | { 43 | uint8_t twst; 44 | 45 | // send START condition 46 | TWCR = (1< 5 | #include 6 | #include 7 | #include "i2c_master.h" 8 | #include "font8x8.h" 9 | 10 | #define NUM_COLS 16 11 | #define NUM_ROWS 2 12 | #define NUM_CHARS NUM_COLS * NUM_ROWS 13 | 14 | static uint8_t _addr; // I2C address 15 | static uint8_t _row, _col; 16 | static uint8_t _buffer[NUM_CHARS]; 17 | static uint8_t _displayCursor; 18 | 19 | void write_raw(uint8_t value, uint8_t cursor); 20 | void ssd1306_fillscreen(uint8_t fill); 21 | void ssd1306_send_command_start(void); 22 | void ssd1306_send_command(uint8_t command); 23 | void ssd1306_send_data_start(void); 24 | 25 | #define SSD1306_DISPLAYOFF 0xAE 26 | #define SSD1306_SETDISPLAYCLOCKDIV 0xD5 27 | #define SSD1306_SETMULTIPLEX 0xA8 28 | #define SSD1306_SETDISPLAYOFFSET 0xD3 29 | #define SSD1306_SETSTARTLINE 0x40 30 | #define SSD1306_CHARGEPUMP 0x8D 31 | #define SSD1306_MEMORYMODE 0x20 32 | #define SSD1306_SEGREMAP 0xA0 33 | #define SSD1306_COMSCANDEC 0xC8 34 | #define SSD1306_SETCOMPINS 0xDA 35 | #define SSD1306_SETCONTRAST 0x81 36 | #define SSD1306_SETPRECHARGE 0xD9 37 | #define SSD1306_SETVCOMDETECT 0xDB 38 | #define SSD1306_DISPLAYALLON_RESUME 0xA4 39 | #define SSD1306_NORMALDISPLAY 0xA6 40 | #define SSD1306_DISPLAYON 0xAF 41 | #define SSD1306_SETSTARTPAGE 0xB0 42 | #define SSD1306_LOWCOLUMNADDR 0x00 43 | #define SSD1306_HIGHCOLUMNADDR 0x10 44 | 45 | // Init Sequence 46 | const uint8_t ssd1306_init_sequence [] PROGMEM = { 47 | SSD1306_DISPLAYOFF, // 0xAE Display OFF (sleep mode) 48 | SSD1306_SETDISPLAYCLOCKDIV, 0x80, // 0xD5 Set display clock divide ratio/oscillator frequency 49 | #if defined LCD_SSD1306_128x64 50 | SSD1306_SETMULTIPLEX, 0x3F, // 0xA8 Set multiplex ratio (1 to 64) 51 | #elif defined LCD_SSD1306_128x32 52 | SSD1306_SETMULTIPLEX, 0x1F, // 0xA8 Set multiplex ratio (1 to 64) 53 | #endif 54 | SSD1306_SETDISPLAYOFFSET, 0x00, // 0xD3 Set display offset. 00 = no offset 55 | SSD1306_SETSTARTLINE | 0x00, // 0x40 Set start line address 56 | SSD1306_CHARGEPUMP, 0x14, // 0x8D Set DC-DC enable: internal VCC 57 | SSD1306_MEMORYMODE, 0x10, // 0x20 Set Memory Addressing Mode 58 | // 00=Horizontal Addressing Mode; 01=Vertical Addressing Mode; 59 | // 10=Page Addressing Mode (RESET); 11=Invalid 60 | SSD1306_SEGREMAP | 0x01, // 0xA0 Set Segment Re-map. A0=address mapped; A1=address 127 mapped. 61 | SSD1306_COMSCANDEC, // 0xC8 Set COM Output Scan Direction - descending 62 | #if defined LCD_SSD1306_128x64 63 | #ifdef LCD_SSD1306_BIG_FONTS 64 | SSD1306_SETCOMPINS, 0x02, // 0xDA Set com pins hardware configuration 65 | #else 66 | SSD1306_SETCOMPINS, 0x12, // 0xDA Set com pins hardware configuration 67 | #endif 68 | #elif defined LCD_SSD1306_128x32 69 | SSD1306_SETCOMPINS, 0x02, // 0xDA Set com pins hardware configuration 70 | #endif 71 | 72 | SSD1306_SETCONTRAST, 0x3F, // 0x81 Set contrast control register 73 | SSD1306_SETPRECHARGE, 0x22, // 0xD9 Set pre-charge period 74 | SSD1306_SETVCOMDETECT, 0x20, // 0xDB Set vcomh 0x20,0.77xVcc 75 | SSD1306_DISPLAYALLON_RESUME, // 0xA4 Output RAM to Display 0xA4=Output follows RAM content; 0xA5,Output ignores RAM content 76 | SSD1306_NORMALDISPLAY, // 0xA6 Set display mode. A6=Normal; A7=Inverse 77 | SSD1306_SETSTARTPAGE | 0x00, // Set Page Start Address for Page Addressing Mode, 0-7 78 | SSD1306_LOWCOLUMNADDR, // ---set low column address 79 | SSD1306_HIGHCOLUMNADDR, // ---set high column address 80 | SSD1306_DISPLAYON // 0xAF Display ON in normal mode 81 | }; 82 | 83 | 84 | void lcd_init(uint8_t lcd_addr) 85 | { 86 | uint8_t i; 87 | _addr = lcd_addr; 88 | _row = 0; 89 | _col = 0; 90 | _displayCursor = 0; 91 | 92 | i2c_init(); 93 | _delay_ms(100); 94 | 95 | for (i = 0; i < sizeof (ssd1306_init_sequence); i++) { 96 | ssd1306_send_command(pgm_read_byte(&ssd1306_init_sequence[i])); 97 | } 98 | ssd1306_fillscreen(0); 99 | memset(_buffer, 32, NUM_CHARS); 100 | } 101 | 102 | void lcd_cursor() { 103 | uint8_t curValue = _buffer[_row * NUM_COLS + _col]; 104 | _displayCursor = 1; 105 | write_raw(curValue, 1); 106 | } 107 | 108 | void lcd_noCursor(){ 109 | uint8_t curValue = _buffer[_row * NUM_COLS + _col]; 110 | _displayCursor = 0; 111 | write_raw(curValue, 0); 112 | } 113 | 114 | void lcd_backlight() { 115 | 116 | } 117 | 118 | void lcd_noBacklight() { 119 | 120 | } 121 | 122 | 123 | void write_raw(uint8_t value, uint8_t cursor) { 124 | uint8_t i, v, col; 125 | uint8_t c = value - 32; 126 | 127 | col = _col << 3; // convert to pixel: character column * 8 128 | ssd1306_send_command_start(); 129 | i2c_write(SSD1306_SETSTARTPAGE + _row); 130 | i2c_write((col & 0x0f) | SSD1306_LOWCOLUMNADDR); 131 | i2c_write(((col & 0xf0) >> 4) | SSD1306_HIGHCOLUMNADDR); 132 | 133 | ssd1306_send_data_start(); 134 | // write 1 column of the character per iteration 135 | for (i = 0; i < 8; i++) 136 | { 137 | v = pgm_read_byte(&font8x8[c * 8 + i]); 138 | // add underline for cursor: last pixel in the column 139 | if (cursor) v |= 0x80; 140 | i2c_write(v); 141 | } 142 | i2c_stop(); 143 | } 144 | 145 | void lcd_setCursor(uint8_t col, uint8_t row) 146 | { 147 | if ((row < NUM_ROWS) && (col < NUM_COLS)) { 148 | if (_displayCursor) { 149 | uint8_t curValue = _buffer[_row * NUM_COLS + _col]; 150 | write_raw(curValue, 0); 151 | } 152 | 153 | _col = col; 154 | _row = row; 155 | 156 | if (_displayCursor) { 157 | uint8_t curValue = _buffer[_row * NUM_COLS + _col]; 158 | write_raw(curValue, 1); 159 | } 160 | } 161 | } 162 | 163 | // ---------------------------------------------------------------------------- 164 | 165 | void lcd_write(uint8_t value) { 166 | write_raw(value, 0); 167 | 168 | _buffer[_row * NUM_COLS + _col] = value; 169 | _col++; 170 | if (_col >= NUM_COLS) { 171 | _col = 0; 172 | _row = (_row + 1) % NUM_ROWS; 173 | } 174 | if (_displayCursor) { 175 | uint8_t curValue = _buffer[_row * NUM_COLS + _col]; 176 | write_raw(curValue, 1); 177 | } 178 | } 179 | 180 | void lcd_print(char *s) { 181 | while (*s) { 182 | lcd_write(*s++); 183 | } 184 | } 185 | 186 | // ---------------------------------------------------------------------------- 187 | void ssd1306_fillscreen(uint8_t fill) { 188 | uint8_t m, n; 189 | for (m = 0; m < 8; m++) 190 | { 191 | ssd1306_send_command_start(); 192 | i2c_write(SSD1306_SETSTARTPAGE + m); // page0 - page7 193 | i2c_write(SSD1306_LOWCOLUMNADDR); // low column start address 194 | i2c_write(SSD1306_HIGHCOLUMNADDR); // high column start address 195 | ssd1306_send_data_start(); 196 | for (n = 0; n < 128; n++) 197 | { 198 | i2c_write(fill); 199 | } 200 | i2c_stop(); 201 | } 202 | } 203 | 204 | void ssd1306_send_command_start(void) { 205 | i2c_start(_addr << 1); 206 | i2c_write(0x00); // command 207 | } 208 | 209 | void ssd1306_send_command(uint8_t command) { 210 | ssd1306_send_command_start(); 211 | i2c_write(command); 212 | i2c_stop(); 213 | } 214 | 215 | void ssd1306_send_data_start(void) { 216 | i2c_start(_addr << 1); 217 | i2c_write(0x40); // data 218 | } 219 | 220 | #endif 221 | -------------------------------------------------------------------------------- /font8x8.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const uint8_t font8x8 [] PROGMEM = { 4 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // [0x20] ' ' 5 | 0x00, 0x00, 0x00, 0xDF, 0xDF, 0x00, 0x00, 0x00, // [0x21] '!' 6 | 0x00, 0x03, 0x07, 0x00, 0x03, 0x07, 0x00, 0x00, // [0x22] '"' 7 | 0x00, 0x14, 0x3E, 0x14, 0x3E, 0x14, 0x00, 0x00, // [0x23] '#' 8 | 0x00, 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00, 0x00, // [0x24] '$' 9 | 0x43, 0x23, 0x10, 0x08, 0x04, 0x62, 0x61, 0x00, // [0x25] '%' 10 | 0x38, 0x7C, 0x44, 0x7F, 0x3F, 0x04, 0x04, 0x00, // [0x26] '&' 11 | 0x00, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, // [0x27] ''' 12 | 0x00, 0x00, 0x7E, 0xFF, 0x81, 0x00, 0x00, 0x00, // [0x28] '(' 13 | 0x00, 0x00, 0x81, 0xFF, 0x7E, 0x00, 0x00, 0x00, // [0x29] ')' 14 | 0x08, 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x08, 0x00, // [0x2A] '*' 15 | 0x00, 0x08, 0x08, 0x3E, 0x3E, 0x08, 0x08, 0x00, // [0x2B] '+' 16 | 0x00, 0x00, 0x80, 0xE0, 0x60, 0x00, 0x00, 0x00, // [0x2C] ',' 17 | 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, // [0x2D] '-' 18 | 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, // [0x2E] '.' 19 | 0x00, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0x00, 0x00, // [0x2F] '/' 20 | 0x3E, 0x7F, 0x51, 0x49, 0x45, 0x7F, 0x3E, 0x00, // [0x30] '0' 21 | 0x00, 0x40, 0x42, 0x7F, 0x7F, 0x40, 0x40, 0x00, // [0x31] '1' 22 | 0x72, 0x7B, 0x49, 0x49, 0x49, 0x4F, 0x46, 0x00, // [0x32] '2' 23 | 0x22, 0x63, 0x41, 0x49, 0x49, 0x7F, 0x36, 0x00, // [0x33] '3' 24 | 0x07, 0x0F, 0x08, 0x08, 0x08, 0x7E, 0x7E, 0x00, // [0x34] '4' 25 | 0x27, 0x6F, 0x49, 0x49, 0x49, 0x79, 0x31, 0x00, // [0x35] '5' 26 | 0x3E, 0x7F, 0x49, 0x49, 0x49, 0x79, 0x30, 0x00, // [0x36] '6' 27 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x7F, 0x7E, 0x00, // [0x37] '7' 28 | 0x36, 0x7F, 0x49, 0x49, 0x49, 0x7F, 0x36, 0x00, // [0x38] '8' 29 | 0x06, 0x0F, 0x09, 0x09, 0x09, 0x7F, 0x7F, 0x00, // [0x39] '9' 30 | 0x00, 0x00, 0x00, 0x63, 0x63, 0x00, 0x00, 0x00, // [0x3A] ':' 31 | 0x00, 0x00, 0x80, 0xE3, 0x63, 0x00, 0x00, 0x00, // [0x3B] ';' 32 | 0x00, 0x08, 0x1C, 0x36, 0x63, 0x41, 0x00, 0x00, // [0x3C] '<' 33 | 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, // [0x3D] '=' 34 | 0x00, 0x41, 0x63, 0x36, 0x1C, 0x08, 0x00, 0x00, // [0x3E] '>' 35 | 0x02, 0x03, 0xD1, 0xD9, 0x09, 0x0F, 0x06, 0x00, // [0x3F] '?' 36 | 0x3E, 0x7F, 0x41, 0x5D, 0x55, 0x5F, 0x0E, 0x00, // [0x40] '@' 37 | 0x7E, 0x7F, 0x09, 0x09, 0x09, 0x7F, 0x7E, 0x00, // [0x41] 'A' 38 | 0x7F, 0x7F, 0x49, 0x49, 0x49, 0x7F, 0x36, 0x00, // [0x42] 'B' 39 | 0x3E, 0x7F, 0x41, 0x41, 0x41, 0x63, 0x22, 0x00, // [0x43] 'C' 40 | 0x7F, 0x7F, 0x41, 0x41, 0x63, 0x3E, 0x1C, 0x00, // [0x44] 'D' 41 | 0x7F, 0x7F, 0x49, 0x49, 0x49, 0x41, 0x41, 0x00, // [0x45] 'E' 42 | 0x7F, 0x7F, 0x09, 0x09, 0x09, 0x01, 0x01, 0x00, // [0x46] 'F' 43 | 0x3E, 0x7F, 0x41, 0x49, 0x49, 0x7B, 0x7A, 0x00, // [0x47] 'G' 44 | 0x7F, 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x7F, 0x00, // [0x48] 'H' 45 | 0x00, 0x41, 0x41, 0x7F, 0x7F, 0x41, 0x41, 0x00, // [0x49] 'I' 46 | 0x20, 0x61, 0x41, 0x7F, 0x3F, 0x01, 0x01, 0x00, // [0x4A] 'J' 47 | 0x7F, 0x7F, 0x08, 0x1C, 0x36, 0x63, 0x41, 0x00, // [0x4B] 'K' 48 | 0x7F, 0x7F, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, // [0x4C] 'L' 49 | 0x7F, 0x7F, 0x06, 0x0C, 0x06, 0x7F, 0x7F, 0x00, // [0x4D] 'M' 50 | 0x7F, 0x7F, 0x06, 0x0C, 0x18, 0x7F, 0x7F, 0x00, // [0x4E] 'N' 51 | 0x3E, 0x7F, 0x41, 0x41, 0x41, 0x7F, 0x3E, 0x00, // [0x4F] 'O' 52 | 0x7F, 0x7F, 0x09, 0x09, 0x09, 0x0F, 0x06, 0x00, // [0x50] 'P' 53 | 0x3E, 0x7F, 0x41, 0x61, 0xC1, 0xFF, 0xBE, 0x00, // [0x51] 'Q' 54 | 0x7F, 0x7F, 0x09, 0x09, 0x09, 0x7F, 0x76, 0x00, // [0x52] 'R' 55 | 0x26, 0x6F, 0x49, 0x49, 0x49, 0x7B, 0x32, 0x00, // [0x53] 'S' 56 | 0x00, 0x01, 0x01, 0x7F, 0x7F, 0x01, 0x01, 0x00, // [0x54] 'T' 57 | 0x3F, 0x7F, 0x40, 0x40, 0x40, 0x7F, 0x7F, 0x00, // [0x55] 'U' 58 | 0x00, 0x07, 0x1F, 0x78, 0x78, 0x1F, 0x07, 0x00, // [0x56] 'V' 59 | 0x7F, 0x7F, 0x30, 0x18, 0x30, 0x7F, 0x7F, 0x00, // [0x57] 'W' 60 | 0x63, 0x77, 0x1C, 0x08, 0x1C, 0x77, 0x63, 0x00, // [0x58] 'X' 61 | 0x27, 0x6F, 0x48, 0x48, 0x48, 0x7F, 0x3F, 0x00, // [0x59] 'Y' 62 | 0x61, 0x71, 0x59, 0x4D, 0x47, 0x43, 0x41, 0x00, // [0x5A] 'Z' 63 | 0x00, 0x00, 0xFF, 0xFF, 0x81, 0x81, 0x00, 0x00, // [0x5B] '[' 64 | 0x00, 0x03, 0x0F, 0x3C, 0xF0, 0xC0, 0x00, 0x00, // [0x5C] '\\' 65 | 0x00, 0x00, 0x81, 0x81, 0xFF, 0xFF, 0x00, 0x00, // [0x5D] ']' 66 | 0x04, 0x06, 0x03, 0x01, 0x03, 0x06, 0x04, 0x00, // [0x5E] '^' 67 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, // [0x5F] '_' 68 | 0x03, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // [0x60] '`' 69 | 0x38, 0x7C, 0x44, 0x44, 0x24, 0x7C, 0x78, 0x00, // [0x61] 'a' 70 | 0x7F, 0x7F, 0x24, 0x44, 0x44, 0x7C, 0x38, 0x00, // [0x62] 'b' 71 | 0x38, 0x7C, 0x44, 0x44, 0x44, 0x44, 0x44, 0x00, // [0x63] 'c' 72 | 0x38, 0x7C, 0x44, 0x44, 0x24, 0x7F, 0x7F, 0x00, // [0x64] 'd' 73 | 0x38, 0x7C, 0x54, 0x54, 0x54, 0x5C, 0x08, 0x00, // [0x65] 'e' 74 | 0x00, 0x04, 0x7E, 0x7F, 0x05, 0x01, 0x00, 0x00, // [0x66] 'f' 75 | 0x18, 0xBC, 0xA4, 0xA4, 0x94, 0xFC, 0x78, 0x00, // [0x67] 'g' 76 | 0x7F, 0x7F, 0x08, 0x04, 0x04, 0x7C, 0x78, 0x00, // [0x68] 'h' 77 | 0x00, 0x00, 0x00, 0x7D, 0x7D, 0x00, 0x00, 0x00, // [0x69] 'i' 78 | 0x00, 0x40, 0x40, 0x40, 0x7D, 0x3D, 0x00, 0x00, // [0x6A] 'j' 79 | 0x7F, 0x7F, 0x08, 0x08, 0x1C, 0x76, 0x62, 0x00, // [0x6B] 'k' 80 | 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x00, 0x00, 0x00, // [0x6C] 'l' 81 | 0x78, 0x7C, 0x18, 0x30, 0x18, 0x7C, 0x78, 0x00, // [0x6D] 'm' 82 | 0x7C, 0x7C, 0x08, 0x04, 0x04, 0x7C, 0x78, 0x00, // [0x6E] 'n' 83 | 0x38, 0x7C, 0x44, 0x44, 0x44, 0x7C, 0x38, 0x00, // [0x6F] 'o' 84 | 0xFC, 0xFC, 0x28, 0x24, 0x24, 0x3C, 0x18, 0x00, // [0x70] 'p' 85 | 0x1C, 0x1E, 0x22, 0x22, 0x12, 0xFE, 0xFE, 0x00, // [0x71] 'q' 86 | 0x7C, 0x7C, 0x08, 0x04, 0x04, 0x0C, 0x08, 0x00, // [0x72] 'r' 87 | 0x48, 0x5C, 0x54, 0x54, 0x54, 0x74, 0x20, 0x00, // [0x73] 's' 88 | 0x3F, 0x7F, 0x44, 0x44, 0x44, 0x60, 0x20, 0x00, // [0x74] 't' 89 | 0x3C, 0x7C, 0x40, 0x40, 0x20, 0x7C, 0x7C, 0x00, // [0x75] 'u' 90 | 0x00, 0x0C, 0x3C, 0x70, 0x70, 0x3C, 0x0C, 0x00, // [0x76] 'v' 91 | 0x3C, 0x7C, 0x30, 0x18, 0x30, 0x7C, 0x3C, 0x00, // [0x77] 'w' 92 | 0x44, 0x6C, 0x38, 0x10, 0x38, 0x6C, 0x44, 0x00, // [0x78] 'x' 93 | 0x0C, 0x5C, 0x50, 0x50, 0x50, 0x7C, 0x3C, 0x00, // [0x79] 'y' 94 | 0x44, 0x64, 0x74, 0x54, 0x5C, 0x4C, 0x44, 0x00, // [0x7A] 'z' 95 | 0x00, 0x08, 0x3E, 0x77, 0x41, 0x00, 0x00, 0x00, // [0x7B] '{' 96 | 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, // [0x7C] '|' 97 | 0x00, 0x41, 0x77, 0x3E, 0x08, 0x00, 0x00, 0x00, // [0x7D] '}' 98 | 0x00, 0x08, 0x08, 0x49, 0x2A, 0x1C, 0x08, 0x00, // [0x7E] '->' 99 | // 0x02, 0x03, 0x01, 0x03, 0x02, 0x03, 0x01, 0x00, // [0x7E] '~' 100 | }; 101 | -------------------------------------------------------------------------------- /Tapuino.cproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2.0 5 | 6.2 6 | com.Atmel.AVRGCC8.C 7 | {4ec26722-9e4b-4e84-94fb-ac9f2dab1ef2} 8 | ATmega328P 9 | none 10 | Executable 11 | C 12 | $(MSBuildProjectName) 13 | .elf 14 | $(MSBuildProjectDirectory)\$(Configuration) 15 | Tapuino 16 | Tapuino 17 | Tapuino 18 | Native 19 | true 20 | false 21 | true 22 | true 23 | 24 | 25 | 26 | 2 27 | 1 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | true 41 | 42 | 43 | 44 | 45 | True 46 | True 47 | True 48 | True 49 | False 50 | True 51 | True 52 | 53 | 54 | NDEBUG 55 | F_CPU=16000000 56 | 57 | 58 | Optimize for size (-Os) 59 | True 60 | True 61 | True 62 | 63 | 64 | libm 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | True 74 | True 75 | True 76 | True 77 | False 78 | True 79 | True 80 | 81 | 82 | DEBUG 83 | F_CPU=16000000 84 | 85 | 86 | Optimize (-O1) 87 | True 88 | True 89 | Default (-g2) 90 | True 91 | 92 | 93 | libm 94 | 95 | 96 | Default (-Wa,-g) 97 | 98 | 99 | 100 | 101 | 102 | compile 103 | 104 | 105 | compile 106 | 107 | 108 | compile 109 | 110 | 111 | compile 112 | 113 | 114 | compile 115 | 116 | 117 | compile 118 | 119 | 120 | compile 121 | 122 | 123 | compile 124 | 125 | 126 | compile 127 | 128 | 129 | compile 130 | 131 | 132 | compile 133 | 134 | 135 | compile 136 | 137 | 138 | compile 139 | 140 | 141 | compile 142 | 143 | 144 | compile 145 | 146 | 147 | compile 148 | 149 | 150 | compile 151 | 152 | 153 | compile 154 | 155 | 156 | compile 157 | 158 | 159 | compile 160 | 161 | 162 | compile 163 | 164 | 165 | compile 166 | 167 | 168 | compile 169 | 170 | 171 | compile 172 | 173 | 174 | compile 175 | 176 | 177 | compile 178 | 179 | 180 | compile 181 | 182 | 183 | compile 184 | 185 | 186 | compile 187 | 188 | 189 | compile 190 | 191 | 192 | compile 193 | 194 | 195 | 196 | -------------------------------------------------------------------------------- /disp_LCD_HD44780.c: -------------------------------------------------------------------------------- 1 | //www.DFRobot.com 2 | //last updated on 21/12/2011 3 | //Tim Starling Fix the reset bug (Thanks Tim) 4 | //wiki doc http://www.dfrobot.com/wiki/index.php?title=I2C/TWI_LCD1602_Module_(SKU:_DFR0063) 5 | //Support Forum: http://www.dfrobot.com/forum/ 6 | //Compatible with the Arduino IDE 1.0 7 | //Library version:1.1 8 | 9 | 10 | #include "config.h" 11 | #ifdef LCD_USE_1602_LCD_MODULE 12 | 13 | #include "lcd_interface.h" 14 | 15 | #include 16 | #include 17 | 18 | #include "i2c_master.h" 19 | 20 | // commands 21 | #define LCD_CLEARDISPLAY 0x01 22 | #define LCD_RETURNHOME 0x02 23 | #define LCD_ENTRYMODESET 0x04 24 | #define LCD_DISPLAYCONTROL 0x08 25 | #define LCD_CURSORSHIFT 0x10 26 | #define LCD_FUNCTIONSET 0x20 27 | #define LCD_SETCGRAMADDR 0x40 28 | #define LCD_SETDDRAMADDR 0x80 29 | 30 | // flags for display entry mode 31 | #define LCD_ENTRYRIGHT 0x00 32 | #define LCD_ENTRYLEFT 0x02 33 | #define LCD_ENTRYSHIFTINCREMENT 0x01 34 | #define LCD_ENTRYSHIFTDECREMENT 0x00 35 | 36 | // flags for display on/off control 37 | #define LCD_DISPLAYON 0x04 38 | #define LCD_DISPLAYOFF 0x00 39 | #define LCD_CURSORON 0x02 40 | #define LCD_CURSOROFF 0x00 41 | #define LCD_BLINKON 0x01 42 | #define LCD_BLINKOFF 0x00 43 | 44 | // flags for display/cursor shift 45 | #define LCD_DISPLAYMOVE 0x08 46 | #define LCD_CURSORMOVE 0x00 47 | #define LCD_MOVERIGHT 0x04 48 | #define LCD_MOVELEFT 0x00 49 | 50 | // flags for backlight control 51 | #define LCD_BACKLIGHT _BV(LCD_BIT_BACKLIGHT) 52 | #define LCD_NOBACKLIGHT 0x00 53 | 54 | // flags for function set 55 | #define LCD_8BITMODE 0x10 56 | #define LCD_4BITMODE 0x00 57 | #define LCD_2LINE 0x08 58 | #define LCD_1LINE 0x00 59 | #define LCD_5x10DOTS 0x04 60 | #define LCD_5x8DOTS 0x00 61 | 62 | uint8_t backslashChar[8] = { 63 | 0b00000, 64 | 0b10000, 65 | 0b01000, 66 | 0b00100, 67 | 0b00010, 68 | 0b00001, 69 | 0b00000, 70 | 0b00000 71 | }; 72 | 73 | 74 | // When the display powers up, it is configured as follows: 75 | // 76 | // 1. Display clear 77 | // 2. Function set: 78 | // DL = 1; 8-bit interface data 79 | // N = 0; 1-line display 80 | // F = 0; 5x8 dot character font 81 | // 3. Display on/off control: 82 | // D = 0; Display off 83 | // C = 0; Cursor off 84 | // B = 0; Blinking off 85 | // 4. Entry mode set: 86 | // I/D = 1; Increment by 1 87 | // S = 0; No shift 88 | // 89 | // Note, however, that resetting the Arduino doesn't reset the LCD, so we 90 | // can't assume that its in that state when a sketch starts (and the 91 | // LiquidCrystal constructor is called). 92 | 93 | uint8_t _addr; 94 | uint8_t _displayfunction; 95 | uint8_t _displaycontrol; 96 | uint8_t _displaymode; 97 | uint8_t _numlines; 98 | uint8_t _cols; 99 | uint8_t _rows; 100 | uint8_t _backlightval; 101 | 102 | void send(uint8_t value, uint8_t mode); 103 | void write4bits(uint8_t value, uint8_t mode); 104 | void expanderWrite(uint8_t _data); 105 | void pulseEnable(uint8_t _data); 106 | void lcd_begin(uint8_t lcd_addr, uint8_t cols, uint8_t lines, uint8_t dotsize); 107 | void lcd_display(); 108 | void lcd_clear(); 109 | void lcd_home(); 110 | void lcd_createChar(uint8_t location, uint8_t charmap[]); 111 | 112 | void lcd_write(uint8_t value) { 113 | // replace backslash with redefined char 114 | if (value == '\\') value = 0x01; 115 | send(value, _BV(LCD_BIT_RS)); 116 | } 117 | 118 | // mid level commands, for sending data/cmds 119 | 120 | void command(uint8_t value) { 121 | send(value, 0); 122 | } 123 | 124 | void lcd_init(uint8_t lcd_addr) { 125 | lcd_begin(lcd_addr, MAX_LCD_LINE_LEN, LCD_NUM_LINES, LCD_5x8DOTS); 126 | // can't define this as the zeroth character as zero is null in strings :)! :) 127 | lcd_createChar(1, backslashChar); 128 | } 129 | 130 | void lcd_begin(uint8_t lcd_addr, uint8_t cols, uint8_t lines, uint8_t dotsize) { 131 | _addr = lcd_addr; 132 | _cols = cols; 133 | _rows = lines; 134 | _backlightval = LCD_NOBACKLIGHT; 135 | i2c_init(); 136 | _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; 137 | 138 | 139 | if (lines > 1) { 140 | _displayfunction |= LCD_2LINE; 141 | } 142 | _numlines = lines; 143 | 144 | // for some 1 line displays you can select a 10 pixel high font 145 | if ((dotsize != 0) && (lines == 1)) { 146 | _displayfunction |= LCD_5x10DOTS; 147 | } 148 | 149 | // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! 150 | // according to datasheet, we need at least 40ms after power rises above 2.7V 151 | // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50 152 | _delay_ms(50); 153 | 154 | // Now we pull both RS and R/W low to begin commands 155 | lcd_noBacklight(); // reset expander and turn backlight off (Bit 8 =1) 156 | _delay_ms(1000); 157 | 158 | //put the LCD into 4 bit mode 159 | // this is according to the hitachi HD44780 datasheet 160 | // figure 24, pg 46 161 | 162 | // we start in 8bit mode, try to set 4 bit mode 163 | write4bits(0x03, 0); 164 | _delay_us(4500); // wait min 4.1ms 165 | 166 | // second try 167 | write4bits(0x03, 0); 168 | _delay_us(4500); // wait min 4.1ms 169 | 170 | // third go! 171 | write4bits(0x03, 0); 172 | _delay_us(150); 173 | 174 | // finally, set to 4-bit interface 175 | write4bits(0x02, 0); 176 | 177 | // set # lines, font size, etc. 178 | command(LCD_FUNCTIONSET | _displayfunction); 179 | 180 | // turn the display on with no cursor or blinking default 181 | _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; 182 | lcd_display(); 183 | 184 | // clear it off 185 | lcd_clear(); 186 | 187 | // Initialize to default text direction (for roman languages) 188 | _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; 189 | 190 | // set the entry mode 191 | command(LCD_ENTRYMODESET | _displaymode); 192 | 193 | lcd_home(); 194 | } 195 | 196 | // high level commands, for the user! 197 | void lcd_clear() { 198 | command(LCD_CLEARDISPLAY);// clear display, set cursor position to zero 199 | _delay_us(2000); // this command takes a long time! 200 | } 201 | 202 | void lcd_home() { 203 | command(LCD_RETURNHOME); // set cursor position to zero 204 | _delay_us(2000); // this command takes a long time! 205 | } 206 | 207 | void lcd_setCursor(uint8_t col, uint8_t row) { 208 | int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; 209 | if ( row > _numlines ) { 210 | row = _numlines - 1; // we count rows starting w/0 211 | } 212 | command(LCD_SETDDRAMADDR | (col + row_offsets[row])); 213 | } 214 | 215 | // Turn the display on/off (quickly) 216 | void lcd_noDisplay() { 217 | _displaycontrol &= ~LCD_DISPLAYON; 218 | command(LCD_DISPLAYCONTROL | _displaycontrol); 219 | } 220 | 221 | void lcd_display() { 222 | _displaycontrol |= LCD_DISPLAYON; 223 | command(LCD_DISPLAYCONTROL | _displaycontrol); 224 | } 225 | 226 | // Turns the underline cursor on/off 227 | void lcd_noCursor() { 228 | _displaycontrol &= ~LCD_CURSORON; 229 | command(LCD_DISPLAYCONTROL | _displaycontrol); 230 | } 231 | void lcd_cursor() { 232 | _displaycontrol |= LCD_CURSORON; 233 | command(LCD_DISPLAYCONTROL | _displaycontrol); 234 | } 235 | 236 | // Allows us to fill the first 8 CGRAM locations 237 | // with custom characters 238 | void lcd_createChar(uint8_t location, uint8_t charmap[]) { 239 | int i; 240 | location &= 0x7; // we only have 8 locations 0-7 241 | command(LCD_SETCGRAMADDR | (location << 3)); 242 | for (i = 0; i < 8; i++) { 243 | lcd_write(charmap[i]); 244 | } 245 | } 246 | 247 | // Turn the (optional) backlight off/on 248 | void lcd_noBacklight(void) { 249 | _backlightval = LCD_NOBACKLIGHT; 250 | expanderWrite(_backlightval); 251 | } 252 | 253 | void lcd_backlight(void) { 254 | _backlightval = LCD_BACKLIGHT; 255 | expanderWrite(_backlightval); 256 | } 257 | 258 | void lcd_print(char* msg) { 259 | uint8_t v; 260 | while((v = *msg++)) { 261 | lcd_write(v); 262 | } 263 | } 264 | 265 | // low level data pushing commands 266 | 267 | // write either command or data 268 | void send(uint8_t value, uint8_t mode) { 269 | uint8_t highnib = value >> 4; 270 | uint8_t lownib = value & 0x0f; 271 | write4bits(highnib, mode); 272 | write4bits(lownib, mode); 273 | } 274 | 275 | void write4bits(uint8_t value, uint8_t mode) { 276 | uint8_t res = 0; 277 | if (value & 0x1) res |= _BV(LCD_BIT_DATA0); 278 | if (value & 0x2) res |= _BV(LCD_BIT_DATA1); 279 | if (value & 0x4) res |= _BV(LCD_BIT_DATA2); 280 | if (value & 0x8) res |= _BV(LCD_BIT_DATA3); 281 | res |= mode | _backlightval; 282 | 283 | expanderWrite(res); 284 | pulseEnable(res); 285 | } 286 | 287 | void expanderWrite(uint8_t _data){ 288 | i2c_start((_addr << 1) | I2C_WRITE); 289 | i2c_write(_data); 290 | i2c_stop(); 291 | } 292 | 293 | void pulseEnable(uint8_t _data){ 294 | expanderWrite(_data | _BV(LCD_BIT_EN)); // En high 295 | _delay_us(1); // enable pulse must be >450ns 296 | 297 | expanderWrite(_data & ~_BV(LCD_BIT_EN)); // En low 298 | _delay_us(50); // commands need > 37us to settle 299 | } 300 | 301 | #endif 302 | -------------------------------------------------------------------------------- /ffconf.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------/ 2 | / FatFs - FAT file system module configuration file R0.10b (C)ChaN, 2014 3 | /---------------------------------------------------------------------------*/ 4 | 5 | #ifndef _FFCONF 6 | #define _FFCONF 8051 /* Revision ID */ 7 | 8 | 9 | /*---------------------------------------------------------------------------/ 10 | / Functions and Buffer Configurations 11 | /---------------------------------------------------------------------------*/ 12 | 13 | #define _FS_TINY 1 /* 0:Normal or 1:Tiny */ 14 | /* When _FS_TINY is set to 1, it reduces memory consumption _MAX_SS bytes each 15 | / file object. For file data transfer, FatFs uses the common sector buffer in 16 | / the file system object (FATFS) instead of private sector buffer eliminated 17 | / from the file object (FIL). */ 18 | 19 | 20 | #define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */ 21 | /* Setting _FS_READONLY to 1 defines read only configuration. This removes 22 | / writing functions, f_write(), f_sync(), f_unlink(), f_mkdir(), f_chmod(), 23 | / f_rename(), f_truncate() and useless f_getfree(). */ 24 | 25 | 26 | #define _FS_MINIMIZE 0 /* 0 to 3 */ 27 | /* The _FS_MINIMIZE option defines minimization level to remove API functions. 28 | / 29 | / 0: All basic functions are enabled. 30 | / 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_chmod(), f_utime(), 31 | / f_truncate() and f_rename() function are removed. 32 | / 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. 33 | / 3: f_lseek() function is removed in addition to 2. */ 34 | 35 | 36 | #define _USE_STRFUNC 0 /* 0:Disable or 1-2:Enable */ 37 | /* To enable string functions, set _USE_STRFUNC to 1 or 2. */ 38 | 39 | 40 | #define _USE_MKFS 0 /* 0:Disable or 1:Enable */ 41 | /* To enable f_mkfs() function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */ 42 | 43 | 44 | #define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */ 45 | /* To enable fast seek feature, set _USE_FASTSEEK to 1. */ 46 | 47 | 48 | #define _USE_LABEL 0 /* 0:Disable or 1:Enable */ 49 | /* To enable volume label functions, set _USE_LAVEL to 1 */ 50 | 51 | 52 | #define _USE_FORWARD 0 /* 0:Disable or 1:Enable */ 53 | /* To enable f_forward() function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */ 54 | 55 | 56 | /*---------------------------------------------------------------------------/ 57 | / Locale and Namespace Configurations 58 | /---------------------------------------------------------------------------*/ 59 | 60 | #define _CODE_PAGE 1252 61 | /* The _CODE_PAGE specifies the OEM code page to be used on the target system. 62 | / Incorrect setting of the code page can cause a file open failure. 63 | / 64 | / 932 - Japanese Shift_JIS (DBCS, OEM, Windows) 65 | / 936 - Simplified Chinese GBK (DBCS, OEM, Windows) 66 | / 949 - Korean (DBCS, OEM, Windows) 67 | / 950 - Traditional Chinese Big5 (DBCS, OEM, Windows) 68 | / 1250 - Central Europe (Windows) 69 | / 1251 - Cyrillic (Windows) 70 | / 1252 - Latin 1 (Windows) 71 | / 1253 - Greek (Windows) 72 | / 1254 - Turkish (Windows) 73 | / 1255 - Hebrew (Windows) 74 | / 1256 - Arabic (Windows) 75 | / 1257 - Baltic (Windows) 76 | / 1258 - Vietnam (OEM, Windows) 77 | / 437 - U.S. (OEM) 78 | / 720 - Arabic (OEM) 79 | / 737 - Greek (OEM) 80 | / 775 - Baltic (OEM) 81 | / 850 - Multilingual Latin 1 (OEM) 82 | / 858 - Multilingual Latin 1 + Euro (OEM) 83 | / 852 - Latin 2 (OEM) 84 | / 855 - Cyrillic (OEM) 85 | / 866 - Russian (OEM) 86 | / 857 - Turkish (OEM) 87 | / 862 - Hebrew (OEM) 88 | / 874 - Thai (OEM, Windows) 89 | / 1 - ASCII (Valid for only non-LFN configuration) */ 90 | 91 | 92 | #define _USE_LFN 1 /* 0 to 3 */ 93 | #define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ 94 | /* The _USE_LFN option switches the LFN feature. 95 | / 96 | / 0: Disable LFN feature. _MAX_LFN has no effect. 97 | / 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. 98 | / 2: Enable LFN with dynamic working buffer on the STACK. 99 | / 3: Enable LFN with dynamic working buffer on the HEAP. 100 | / 101 | / When enable LFN feature, Unicode handling functions ff_convert() and ff_wtoupper() 102 | / function must be added to the project. 103 | / The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. When use stack for the 104 | / working buffer, take care on stack overflow. When use heap memory for the working 105 | / buffer, memory management functions, ff_memalloc() and ff_memfree(), must be added 106 | / to the project. */ 107 | 108 | 109 | #define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */ 110 | /* To switch the character encoding on the FatFs API (TCHAR) to Unicode, enable LFN 111 | / feature and set _LFN_UNICODE to 1. This option affects behavior of string I/O 112 | / functions. This option must be 0 when LFN feature is not enabled. */ 113 | 114 | 115 | #define _STRF_ENCODE 3 /* 0:ANSI/OEM, 1:UTF-16LE, 2:UTF-16BE, 3:UTF-8 */ 116 | /* When Unicode API is enabled by _LFN_UNICODE option, this option selects the character 117 | / encoding on the file to be read/written via string I/O functions, f_gets(), f_putc(), 118 | / f_puts and f_printf(). This option has no effect when _LFN_UNICODE == 0. Note that 119 | / FatFs supports only BMP. */ 120 | 121 | 122 | #define _FS_RPATH 1 /* 0 to 2 */ 123 | /* The _FS_RPATH option configures relative path feature. 124 | / 125 | / 0: Disable relative path feature and remove related functions. 126 | / 1: Enable relative path. f_chdrive() and f_chdir() function are available. 127 | / 2: f_getcwd() function is available in addition to 1. 128 | / 129 | / Note that output of the f_readdir() fnction is affected by this option. */ 130 | 131 | 132 | /*---------------------------------------------------------------------------/ 133 | / Drive/Volume Configurations 134 | /---------------------------------------------------------------------------*/ 135 | 136 | #define _VOLUMES 1 137 | /* Number of volumes (logical drives) to be used. */ 138 | 139 | 140 | #define _STR_VOLUME_ID 0 /* 0:Use only 0-9 for drive ID, 1:Use strings for drive ID */ 141 | #define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3" 142 | /* When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive 143 | / number in the path name. _VOLUME_STRS defines the drive ID strings for each logical 144 | / drives. Number of items must be equal to _VOLUMES. Valid characters for the drive ID 145 | / strings are: 0-9 and A-Z. */ 146 | 147 | 148 | #define _MULTI_PARTITION 0 /* 0:Single partition, 1:Enable multiple partition */ 149 | /* By default(0), each logical drive number is bound to the same physical drive number 150 | / and only a FAT volume found on the physical drive is mounted. When it is set to 1, 151 | / each logical drive number is bound to arbitrary drive/partition listed in VolToPart[]. 152 | */ 153 | 154 | 155 | #define _MIN_SS 512 156 | #define _MAX_SS 512 157 | /* These options configure the range of sector size to be supported. (512, 1024, 2048 or 158 | / 4096) Always set both 512 for most systems, all memory card and harddisk. But a larger 159 | / value may be required for on-board flash memory and some type of optical media. 160 | / When _MAX_SS is larger than _MIN_SS, FatFs is configured to variable sector size and 161 | / GET_SECTOR_SIZE command must be implemented to the disk_ioctl() function. */ 162 | 163 | 164 | #define _USE_ERASE 0 /* 0:Disable or 1:Enable */ 165 | /* To enable sector erase feature, set _USE_ERASE to 1. Also CTRL_ERASE_SECTOR command 166 | / should be added to the disk_ioctl() function. */ 167 | 168 | 169 | #define _FS_NOFSINFO 0 /* 0 to 3 */ 170 | /* If you need to know correct free space on the FAT32 volume, set bit 0 of this option 171 | / and f_getfree() function at first time after volume mount will force a full FAT scan. 172 | / Bit 1 controls the last allocated cluster number as bit 0. 173 | / 174 | / bit0=0: Use free cluster count in the FSINFO if available. 175 | / bit0=1: Do not trust free cluster count in the FSINFO. 176 | / bit1=0: Use last allocated cluster number in the FSINFO if available. 177 | / bit1=1: Do not trust last allocated cluster number in the FSINFO. 178 | */ 179 | 180 | 181 | 182 | /*---------------------------------------------------------------------------/ 183 | / System Configurations 184 | /---------------------------------------------------------------------------*/ 185 | 186 | #define _FS_LOCK 0 /* 0:Disable or >=1:Enable */ 187 | /* To enable file lock control feature, set _FS_LOCK to non-zero value. 188 | / The value defines how many files/sub-directories can be opened simultaneously 189 | / with file lock control. This feature uses bss _FS_LOCK * 12 bytes. */ 190 | 191 | 192 | #define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */ 193 | #define _FS_TIMEOUT 1000 /* Timeout period in unit of time tick */ 194 | #define _SYNC_t HANDLE /* O/S dependent sync object type. e.g. HANDLE, OS_EVENT*, ID, SemaphoreHandle_t and etc.. */ 195 | /* The _FS_REENTRANT option switches the re-entrancy (thread safe) of the FatFs module. 196 | / 197 | / 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect. 198 | / 1: Enable re-entrancy. Also user provided synchronization handlers, 199 | / ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() 200 | / function must be added to the project. 201 | */ 202 | 203 | 204 | #define _WORD_ACCESS 1 /* 0 or 1 */ 205 | /* The _WORD_ACCESS option is an only platform dependent option. It defines 206 | / which access method is used to the word data on the FAT volume. 207 | / 208 | / 0: Byte-by-byte access. Always compatible with all platforms. 209 | / 1: Word access. Do not choose this unless under both the following conditions. 210 | / 211 | / * Address misaligned memory access is always allowed for ALL instructions. 212 | / * Byte order on the memory is little-endian. 213 | / 214 | / If it is the case, _WORD_ACCESS can also be set to 1 to improve performance and 215 | / reduce code size. Following table shows an example of some processor types. 216 | / 217 | / ARM7TDMI 0 ColdFire 0 V850E 0 218 | / Cortex-M3 0 Z80 0/1 V850ES 0/1 219 | / Cortex-M0 0 RX600(LE) 0/1 TLCS-870 0/1 220 | / AVR 0/1 RX600(BE) 0 TLCS-900 0/1 221 | / AVR32 0 RL78 0 R32C 0 222 | / PIC18 0/1 SH-2 0 M16C 0/1 223 | / PIC24 0 H8S 0 MSP430 0 224 | / PIC32 0 H8/300H 0 x86 0/1 225 | */ 226 | 227 | 228 | #endif /* _FFCONF */ 229 | -------------------------------------------------------------------------------- /layout/eagle/parts/NanoV3.lbr: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | Name 95 | Value 96 | 97 | 98 | 99 | 100 | NANO v3 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | NANO v3 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | -------------------------------------------------------------------------------- /ff.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------/ 2 | / FatFs - FAT file system module include file R0.10b (C)ChaN, 2014 3 | /----------------------------------------------------------------------------/ 4 | / FatFs module is a generic FAT file system module for small embedded systems. 5 | / This is a free software that opened for education, research and commercial 6 | / developments under license policy of following terms. 7 | / 8 | / Copyright (C) 2014, ChaN, all right reserved. 9 | / 10 | / * The FatFs module is a free software and there is NO WARRANTY. 11 | / * No restriction on use. You can use, modify and redistribute it for 12 | / personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY. 13 | / * Redistributions of source code must retain the above copyright notice. 14 | / 15 | /----------------------------------------------------------------------------*/ 16 | 17 | #ifndef _FATFS 18 | #define _FATFS 8051 /* Revision ID */ 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #include "integer.h" /* Basic integer types */ 25 | #include "ffconf.h" /* FatFs configuration options */ 26 | 27 | #if _FATFS != _FFCONF 28 | #error Wrong configuration file (ffconf.h). 29 | #endif 30 | 31 | 32 | 33 | /* Definitions of volume management */ 34 | 35 | #if _MULTI_PARTITION /* Multiple partition configuration */ 36 | typedef struct { 37 | BYTE pd; /* Physical drive number */ 38 | BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ 39 | } PARTITION; 40 | extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ 41 | #define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */ 42 | #define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */ 43 | 44 | #else /* Single partition configuration */ 45 | #define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */ 46 | #define LD2PT(vol) 0 /* Find first valid partition or in SFD */ 47 | 48 | #endif 49 | 50 | 51 | 52 | /* Type of path name strings on FatFs API */ 53 | 54 | #if _LFN_UNICODE /* Unicode string */ 55 | #if !_USE_LFN 56 | #error _LFN_UNICODE must be 0 at non-LFN cfg. 57 | #endif 58 | #ifndef _INC_TCHAR 59 | typedef WCHAR TCHAR; 60 | #define _T(x) L ## x 61 | #define _TEXT(x) L ## x 62 | #endif 63 | 64 | #else /* ANSI/OEM string */ 65 | #ifndef _INC_TCHAR 66 | typedef char TCHAR; 67 | #define _T(x) x 68 | #define _TEXT(x) x 69 | #endif 70 | 71 | #endif 72 | 73 | 74 | 75 | /* File system object structure (FATFS) */ 76 | 77 | typedef struct { 78 | BYTE fs_type; /* FAT sub-type (0:Not mounted) */ 79 | BYTE drv; /* Physical drive number */ 80 | BYTE csize; /* Sectors per cluster (1,2,4...128) */ 81 | BYTE n_fats; /* Number of FAT copies (1 or 2) */ 82 | BYTE wflag; /* win[] flag (b0:dirty) */ 83 | BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */ 84 | WORD id; /* File system mount ID */ 85 | WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ 86 | #if _MAX_SS != _MIN_SS 87 | WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */ 88 | #endif 89 | #if _FS_REENTRANT 90 | _SYNC_t sobj; /* Identifier of sync object */ 91 | #endif 92 | #if !_FS_READONLY 93 | DWORD last_clust; /* Last allocated cluster */ 94 | DWORD free_clust; /* Number of free clusters */ 95 | #endif 96 | #if _FS_RPATH 97 | DWORD cdir; /* Current directory start cluster (0:root) */ 98 | #endif 99 | DWORD n_fatent; /* Number of FAT entries, = number of clusters + 2 */ 100 | DWORD fsize; /* Sectors per FAT */ 101 | DWORD volbase; /* Volume start sector */ 102 | DWORD fatbase; /* FAT start sector */ 103 | DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ 104 | DWORD database; /* Data start sector */ 105 | DWORD winsect; /* Current sector appearing in the win[] */ 106 | BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ 107 | } FATFS; 108 | 109 | 110 | 111 | /* File object structure (FIL) */ 112 | 113 | typedef struct { 114 | FATFS* fs; /* Pointer to the related file system object (**do not change order**) */ 115 | WORD id; /* Owner file system mount ID (**do not change order**) */ 116 | BYTE flag; /* Status flags */ 117 | BYTE err; /* Abort flag (error code) */ 118 | DWORD fptr; /* File read/write pointer (Zeroed on file open) */ 119 | DWORD fsize; /* File size */ 120 | DWORD sclust; /* File start cluster (0:no cluster chain, always 0 when fsize is 0) */ 121 | DWORD clust; /* Current cluster of fpter (not valid when fprt is 0) */ 122 | DWORD dsect; /* Sector number appearing in buf[] (0:invalid) */ 123 | #if !_FS_READONLY 124 | DWORD dir_sect; /* Sector number containing the directory entry */ 125 | BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */ 126 | #endif 127 | #if _USE_FASTSEEK 128 | DWORD* cltbl; /* Pointer to the cluster link map table (Nulled on file open) */ 129 | #endif 130 | #if _FS_LOCK 131 | UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ 132 | #endif 133 | #if !_FS_TINY 134 | BYTE buf[_MAX_SS]; /* File private data read/write window */ 135 | #endif 136 | } FIL; 137 | 138 | 139 | 140 | /* Directory object structure (DIR) */ 141 | 142 | typedef struct { 143 | FATFS* fs; /* Pointer to the owner file system object (**do not change order**) */ 144 | WORD id; /* Owner file system mount ID (**do not change order**) */ 145 | WORD index; /* Current read/write index number */ 146 | DWORD sclust; /* Table start cluster (0:Root dir) */ 147 | DWORD clust; /* Current cluster */ 148 | DWORD sect; /* Current sector */ 149 | BYTE* dir; /* Pointer to the current SFN entry in the win[] */ 150 | BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ 151 | #if _FS_LOCK 152 | UINT lockid; /* File lock ID (index of file semaphore table Files[]) */ 153 | #endif 154 | #if _USE_LFN 155 | WCHAR* lfn; /* Pointer to the LFN working buffer */ 156 | WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */ 157 | #endif 158 | } DIR; 159 | 160 | 161 | 162 | /* File status structure (FILINFO) */ 163 | 164 | typedef struct { 165 | DWORD fsize; /* File size */ 166 | WORD fdate; /* Last modified date */ 167 | WORD ftime; /* Last modified time */ 168 | BYTE fattrib; /* Attribute */ 169 | TCHAR fname[13]; /* Short file name (8.3 format) */ 170 | #if _USE_LFN 171 | TCHAR* lfname; /* Pointer to the LFN buffer */ 172 | UINT lfsize; /* Size of LFN buffer in TCHAR */ 173 | #endif 174 | } FILINFO; 175 | 176 | 177 | 178 | /* File function return code (FRESULT) */ 179 | 180 | typedef enum { 181 | FR_OK = 0, /* (0) Succeeded */ 182 | FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ 183 | FR_INT_ERR, /* (2) Assertion failed */ 184 | FR_NOT_READY, /* (3) The physical drive cannot work */ 185 | FR_NO_FILE, /* (4) Could not find the file */ 186 | FR_NO_PATH, /* (5) Could not find the path */ 187 | FR_INVALID_NAME, /* (6) The path name format is invalid */ 188 | FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ 189 | FR_EXIST, /* (8) Access denied due to prohibited access */ 190 | FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ 191 | FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ 192 | FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ 193 | FR_NOT_ENABLED, /* (12) The volume has no work area */ 194 | FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ 195 | FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ 196 | FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ 197 | FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ 198 | FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ 199 | FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */ 200 | FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ 201 | } FRESULT; 202 | 203 | 204 | 205 | /*--------------------------------------------------------------*/ 206 | /* FatFs module application interface */ 207 | 208 | FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ 209 | FRESULT f_close (FIL* fp); /* Close an open file object */ 210 | FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from a file */ 211 | FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */ 212 | FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ 213 | FRESULT f_lseek (FIL* fp, DWORD ofs); /* Move file pointer of a file object */ 214 | FRESULT f_truncate (FIL* fp); /* Truncate file */ 215 | FRESULT f_sync (FIL* fp); /* Flush cached data of a writing file */ 216 | FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */ 217 | FRESULT f_closedir (DIR* dp); /* Close an open directory */ 218 | FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */ 219 | FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */ 220 | FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ 221 | FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ 222 | FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ 223 | FRESULT f_chmod (const TCHAR* path, BYTE value, BYTE mask); /* Change attribute of the file/dir */ 224 | FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change times-tamp of the file/dir */ 225 | FRESULT f_chdir (const TCHAR* path); /* Change current directory */ 226 | FRESULT f_chdrive (const TCHAR* path); /* Change current drive */ 227 | FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ 228 | FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ 229 | FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ 230 | FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ 231 | FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ 232 | FRESULT f_mkfs (const TCHAR* path, BYTE sfd, UINT au); /* Create a file system on the volume */ 233 | FRESULT f_fdisk (BYTE pdrv, const DWORD szt[], void* work); /* Divide a physical drive into some partitions */ 234 | int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ 235 | int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ 236 | int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ 237 | TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ 238 | 239 | #define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0) 240 | #define f_error(fp) ((fp)->err) 241 | #define f_tell(fp) ((fp)->fptr) 242 | #define f_size(fp) ((fp)->fsize) 243 | 244 | #ifndef EOF 245 | #define EOF (-1) 246 | #endif 247 | 248 | 249 | 250 | 251 | /*--------------------------------------------------------------*/ 252 | /* Additional user defined functions */ 253 | 254 | /* RTC function */ 255 | #if !_FS_READONLY 256 | DWORD get_fattime (void); 257 | #endif 258 | 259 | /* Unicode support functions */ 260 | #if _USE_LFN /* Unicode - OEM code conversion */ 261 | WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */ 262 | WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */ 263 | #if _USE_LFN == 3 /* Memory functions */ 264 | void* ff_memalloc (UINT msize); /* Allocate memory block */ 265 | void ff_memfree (void* mblock); /* Free memory block */ 266 | #endif 267 | #endif 268 | 269 | /* Sync functions */ 270 | #if _FS_REENTRANT 271 | int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */ 272 | int ff_req_grant (_SYNC_t sobj); /* Lock sync object */ 273 | void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */ 274 | int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */ 275 | #endif 276 | 277 | 278 | 279 | 280 | /*--------------------------------------------------------------*/ 281 | /* Flags and offset address */ 282 | 283 | 284 | /* File access control and file status flags (FIL.flag) */ 285 | 286 | #define FA_READ 0x01 287 | #define FA_OPEN_EXISTING 0x00 288 | 289 | #if !_FS_READONLY 290 | #define FA_WRITE 0x02 291 | #define FA_CREATE_NEW 0x04 292 | #define FA_CREATE_ALWAYS 0x08 293 | #define FA_OPEN_ALWAYS 0x10 294 | #define FA__WRITTEN 0x20 295 | #define FA__DIRTY 0x40 296 | #endif 297 | 298 | 299 | /* FAT sub type (FATFS.fs_type) */ 300 | 301 | #define FS_FAT12 1 302 | #define FS_FAT16 2 303 | #define FS_FAT32 3 304 | 305 | 306 | /* File attribute bits for directory entry */ 307 | 308 | #define AM_RDO 0x01 /* Read only */ 309 | #define AM_HID 0x02 /* Hidden */ 310 | #define AM_SYS 0x04 /* System */ 311 | #define AM_VOL 0x08 /* Volume label */ 312 | #define AM_LFN 0x0F /* LFN entry */ 313 | #define AM_DIR 0x10 /* Directory */ 314 | #define AM_ARC 0x20 /* Archive */ 315 | #define AM_MASK 0x3F /* Mask of defined bits */ 316 | 317 | 318 | /* Fast seek feature */ 319 | #define CREATE_LINKMAP 0xFFFFFFFF 320 | 321 | 322 | 323 | /*--------------------------------*/ 324 | /* Multi-byte word access macros */ 325 | 326 | #if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */ 327 | #define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr)) 328 | #define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr)) 329 | #define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val) 330 | #define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val) 331 | #else /* Use byte-by-byte access to the FAT structure */ 332 | #define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) 333 | #define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr)) 334 | #define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8) 335 | #define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24) 336 | #endif 337 | 338 | #ifdef __cplusplus 339 | } 340 | #endif 341 | 342 | #endif /* _FATFS */ 343 | -------------------------------------------------------------------------------- /menu.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "ff.h" 6 | #include "config.h" 7 | #include "comms.h" 8 | #include "memstrings.h" 9 | #include "fileutils.h" 10 | #include "tapuino.h" 11 | #include "lcd_interface.h" 12 | #include "lcdutils.h" 13 | 14 | #define MODE_PLAY 0 15 | #define MODE_RECORD 1 16 | #define MODE_OPTIONS 2 17 | 18 | #define REC_MODE_MANUAL 0 19 | #define REC_MODE_AUTO 1 20 | 21 | #define OPTION_MACHINE_TYPE 0 22 | #define OPTION_VIDEO_MODE 1 23 | #define OPTION_SIGNAL 2 24 | #define OPTION_KEY_REPEAT 3 25 | #define OPTION_TICKER_SPEED 4 26 | #define OPTION_TICKER_HOLD 5 27 | #define OPTION_REC_FINALIZE 6 28 | #define OPTION_REC_AUTO_FINALIZE 7 29 | 30 | #define SELECT_MODE_EXIT 0xFF 31 | 32 | int g_num_files = 0; 33 | int g_cur_file_index = 0; 34 | 35 | uint8_t get_cur_command() { 36 | // this order of operations is very important 37 | // first get an 'atomic' read of g_cur_command into a local 38 | uint8_t cur_command = g_cur_command; 39 | // then compare the _local_ against a non-IDLE command 40 | if (cur_command != COMMAND_IDLE) { 41 | // and clear the global i.e. only if the global was non-idle at the time of read 42 | // this prevents clearing the global as a key is pressed and missing it 43 | g_cur_command = COMMAND_IDLE; 44 | } 45 | return cur_command; 46 | } 47 | 48 | uint8_t handle_select_mode(const char* ptitle, const char** ppitems, uint8_t max, uint8_t cur_mode) { 49 | uint8_t prev_mode = (cur_mode + 1) % max; 50 | 51 | lcd_title_P(ptitle); 52 | 53 | while (1) { 54 | if (prev_mode != cur_mode) { 55 | lcd_status_P(ppitems[cur_mode]); 56 | prev_mode = cur_mode; 57 | } 58 | 59 | switch(get_cur_command()) { 60 | case COMMAND_SELECT: 61 | return cur_mode; 62 | break; 63 | case COMMAND_ABORT: 64 | return SELECT_MODE_EXIT; 65 | break; 66 | case COMMAND_NEXT: 67 | if (cur_mode == (max - 1)) { 68 | cur_mode = 0; 69 | } else { 70 | cur_mode++; 71 | } 72 | break; 73 | case COMMAND_PREVIOUS: 74 | if (cur_mode == 0) { 75 | cur_mode = max -1; 76 | } else { 77 | cur_mode--; 78 | } 79 | break; 80 | } 81 | } 82 | } 83 | 84 | void handle_play_mode(FILINFO* pfile_info) { 85 | // reset to the root after a possible record operation 86 | change_dir("/"); 87 | // refresh the file list to avoid blank entries bug 88 | if ((g_num_files = get_num_files(pfile_info)) == 0) { 89 | lcd_title_P(S_NO_FILES_FOUND); 90 | lcd_busy_spinner(); 91 | return; 92 | } 93 | 94 | g_cur_file_index = 0; 95 | if (!get_file_at_index(pfile_info, g_cur_file_index)) { 96 | // shouldn't happen... 97 | lcd_title_P(S_NO_FILES_FOUND); 98 | lcd_busy_spinner(); 99 | return; 100 | } 101 | 102 | lcd_title_P(S_SELECT_FILE); 103 | display_filename(pfile_info); 104 | 105 | while (1) { 106 | switch(get_cur_command()) { 107 | case COMMAND_SELECT: 108 | if (pfile_info->fattrib & AM_DIR) { 109 | if (change_dir(pfile_info->fname) == FR_OK) { 110 | g_num_files = get_num_files(pfile_info); 111 | g_cur_file_index = 0; 112 | get_file_at_index(pfile_info, g_cur_file_index); 113 | display_filename(pfile_info); 114 | } else { 115 | lcd_status_P(S_CHDIR_FAILED); 116 | } 117 | } else { 118 | display_filename(pfile_info); 119 | play_file(pfile_info); 120 | lcd_title_P(S_SELECT_FILE); 121 | // buffer is used so get the file again 122 | get_file_at_index(pfile_info, g_cur_file_index); 123 | display_filename(pfile_info); 124 | } 125 | break; 126 | case COMMAND_ABORT: 127 | if (g_fs.cdir != 0) { 128 | if (change_dir("..") == FR_OK) { 129 | g_num_files = get_num_files(pfile_info); 130 | g_cur_file_index = 0; 131 | get_file_at_index(pfile_info, g_cur_file_index); 132 | display_filename(pfile_info); 133 | } else { 134 | lcd_status_P(S_CHDIR_FAILED); 135 | } 136 | } else { 137 | // back to main menu 138 | return; 139 | } 140 | break; 141 | case COMMAND_NEXT: 142 | if (++g_cur_file_index >= g_num_files) { 143 | g_cur_file_index = 0; 144 | } 145 | get_file_at_index(pfile_info, g_cur_file_index); 146 | display_filename(pfile_info); 147 | break; 148 | case COMMAND_PREVIOUS: 149 | if (--g_cur_file_index < 0) { 150 | g_cur_file_index = g_num_files - 1; 151 | } 152 | get_file_at_index(pfile_info, g_cur_file_index); 153 | display_filename(pfile_info); 154 | break; 155 | } 156 | filename_ticker(pfile_info, get_timer_tick()); 157 | } 158 | } 159 | 160 | void handle_record_mode_ready(char* pfile_name) { 161 | lcd_title_P(S_READY_RECORD); 162 | lcd_status_P(S_PRESS_START); 163 | 164 | while (1) { 165 | switch(get_cur_command()) { 166 | case COMMAND_SELECT: 167 | record_file(pfile_name); 168 | return; 169 | break; 170 | case COMMAND_ABORT: 171 | // back to main menu 172 | return; 173 | break; 174 | } 175 | } 176 | } 177 | 178 | uint8_t handle_manual_filename(FILINFO* pfile_info) { 179 | uint8_t cur_char_pos = 0; 180 | uint8_t cursor_pos = 0; 181 | uint8_t max_chars = strlen_P(S_FILENAME_CHARS); 182 | uint8_t cur_char = 0; 183 | lcd_title_P(S_ENTER_FILENAME); 184 | lcd_status(""); 185 | lcd_cursor(); 186 | lcd_setCursor(0, 1); 187 | 188 | // start with a nicely terminated string! 189 | memset(pfile_info->lfname, 0, pfile_info->lfsize); 190 | 191 | while (1) { 192 | switch(get_cur_command()) { 193 | case COMMAND_SELECT: 194 | if (cursor_pos < (MAX_LCD_LINE_LEN - 1)) { 195 | cur_char = pgm_read_byte(S_FILENAME_CHARS + cur_char_pos); 196 | pfile_info->lfname[cursor_pos] = cur_char; 197 | cursor_pos++; 198 | lcd_setCursor(cursor_pos, 1); 199 | cur_char_pos = 0; 200 | } 201 | break; 202 | case COMMAND_SELECT_LONG: 203 | strcat(pfile_info->lfname, ".tap"); 204 | lcd_noCursor(); 205 | // exit to previous menu, with accept 206 | return 1; 207 | break; 208 | case COMMAND_ABORT: 209 | if (cursor_pos != 0) { 210 | pfile_info->lfname[cursor_pos] = 0; 211 | lcd_setCursor(cursor_pos, 1); 212 | lcd_write(' '); 213 | cursor_pos--; 214 | lcd_setCursor(cursor_pos, 1); 215 | cur_char_pos = 0; 216 | cur_char = pfile_info->lfname[cursor_pos]; 217 | while (pgm_read_byte(S_FILENAME_CHARS + cur_char_pos) != cur_char) { 218 | cur_char_pos++; 219 | } 220 | } 221 | break; 222 | case COMMAND_ABORT_LONG: 223 | lcd_title_P(S_OPERATION_ABORTED); 224 | lcd_noCursor(); 225 | lcd_busy_spinner(); 226 | // exit to previous menu, with cancel 227 | return 0; 228 | break; 229 | case COMMAND_NEXT: 230 | cur_char_pos = (cur_char_pos + 1) % max_chars; 231 | cur_char = pgm_read_byte(S_FILENAME_CHARS + cur_char_pos); 232 | lcd_write(cur_char); 233 | lcd_setCursor(cursor_pos, 1); 234 | pfile_info->lfname[cursor_pos] = cur_char; 235 | break; 236 | case COMMAND_PREVIOUS: 237 | if (cur_char_pos == 0) { 238 | cur_char_pos = max_chars; 239 | } 240 | cur_char_pos--; 241 | cur_char = pgm_read_byte(S_FILENAME_CHARS + cur_char_pos); 242 | lcd_write(cur_char); 243 | lcd_setCursor(cursor_pos, 1); 244 | pfile_info->lfname[cursor_pos] = cur_char; 245 | break; 246 | } 247 | } 248 | } 249 | 250 | void handle_record_mode(FILINFO* pfile_info) { 251 | const char* ppitems[] = {S_REC_MODE_MANUAL, S_REC_MODE_AUTO}; 252 | uint8_t cur_mode = 0; 253 | 254 | lcd_title_P(S_SELECT_RECORD_MODE); 255 | 256 | // attempt to open the recording dir 257 | strcpy_P((char*)g_fat_buffer, S_DEFAULT_RECORD_DIR); 258 | // change to the recording dir 259 | if (change_dir((char*)g_fat_buffer) != FR_OK) { 260 | lcd_status_P(S_CHDIR_FAILED); 261 | lcd_busy_spinner(); 262 | return; 263 | } 264 | 265 | while (1) { 266 | cur_mode = handle_select_mode(S_SELECT_RECORD_MODE, ppitems, 2, cur_mode); 267 | switch (cur_mode) { 268 | case REC_MODE_AUTO: 269 | handle_record_mode_ready(NULL); 270 | return; 271 | break; 272 | case REC_MODE_MANUAL: 273 | if (handle_manual_filename(pfile_info)) { 274 | handle_record_mode_ready(pfile_info->lfname); 275 | return; 276 | } 277 | break; 278 | case SELECT_MODE_EXIT: 279 | return; 280 | break; 281 | } 282 | } 283 | } 284 | 285 | 286 | uint8_t handle_option_value(const char* poption, uint16_t* pcur_value, uint16_t min_value, uint16_t max_value, uint16_t step_value) { 287 | char buffer[MAX_LCD_LINE_LEN + 1]; 288 | int32_t cur_value = *pcur_value; 289 | if (cur_value < min_value || cur_value > max_value) { 290 | cur_value = min_value; 291 | } 292 | lcd_title_P(poption); 293 | 294 | utoa((uint16_t)cur_value, buffer, 10); 295 | lcd_status(buffer); 296 | 297 | while (1) { 298 | switch(get_cur_command()) { 299 | case COMMAND_SELECT: 300 | *pcur_value = (uint16_t) cur_value; 301 | return 1; 302 | break; 303 | case COMMAND_ABORT: 304 | return 0; 305 | break; 306 | case COMMAND_NEXT: 307 | cur_value += step_value; 308 | if (cur_value > max_value) { 309 | cur_value = max_value; 310 | } 311 | utoa((uint16_t)cur_value, buffer, 10); 312 | lcd_status(buffer); 313 | break; 314 | case COMMAND_PREVIOUS: 315 | cur_value -= step_value; 316 | if (cur_value < min_value) { 317 | cur_value = min_value; 318 | } 319 | utoa((uint16_t)cur_value, buffer, 10); 320 | lcd_status(buffer); 321 | break; 322 | } 323 | } 324 | } 325 | 326 | 327 | uint8_t handle_option_enum(const char* poption, uint16_t* pcur_value, uint16_t max_items, const char* ppitems[]) { 328 | int32_t cur_value = *pcur_value; 329 | lcd_title_P(poption); 330 | 331 | lcd_status_P(ppitems[cur_value]); 332 | 333 | while (1) { 334 | switch(get_cur_command()) { 335 | case COMMAND_SELECT: 336 | *pcur_value = (uint16_t) cur_value; 337 | return 1; 338 | break; 339 | case COMMAND_ABORT: 340 | return 0; 341 | break; 342 | case COMMAND_NEXT: 343 | cur_value++; 344 | if (cur_value >= max_items) { 345 | cur_value = 0; 346 | } 347 | lcd_status_P(ppitems[cur_value]); 348 | break; 349 | case COMMAND_PREVIOUS: 350 | cur_value--; 351 | if (cur_value < 0) { 352 | cur_value = max_items - 1; 353 | } 354 | lcd_status_P(ppitems[cur_value]); 355 | break; 356 | } 357 | } 358 | } 359 | 360 | void handle_mode_options() { 361 | const char* ppitems[] = {S_OPTION_MACHINE_TYPE, S_OPTION_VIDEO_MODE, S_OPTION_SIGNAL, S_OPTION_KEY_REPEAT, S_OPTION_TICKER_SPEED, S_OPTION_TICKER_HOLD, S_OPTION_REC_FINALIZE, S_OPTION_REC_AUTO_FINALIZE}; 362 | uint16_t value = 0; 363 | uint8_t save = 0; 364 | uint8_t cur_mode = 0; 365 | 366 | while (1) { 367 | cur_mode = handle_select_mode(S_MODE_OPTIONS, ppitems, 8, cur_mode); 368 | switch (cur_mode) { 369 | case OPTION_MACHINE_TYPE: 370 | { 371 | const char* ppenum[] = {S_C64, S_VIC, S_C16}; 372 | value = g_machine_type; 373 | if (handle_option_enum(S_OPTION_MACHINE_TYPE, &value, 3, ppenum)) { 374 | save = 1; 375 | g_machine_type = value; 376 | } 377 | } 378 | break; 379 | case OPTION_VIDEO_MODE: 380 | { 381 | const char* ppenum[] = {S_PAL, S_NTSC}; 382 | value = g_video_mode; 383 | if (handle_option_enum(S_OPTION_VIDEO_MODE, &value, 2, ppenum)) { 384 | save = 1; 385 | g_video_mode = value; 386 | } 387 | } 388 | break; 389 | case OPTION_SIGNAL: 390 | value = g_invert_signal; 391 | if (handle_option_value(S_OPTION_SIGNAL, &value, 0, 1, 1)) { 392 | g_invert_signal = value; 393 | if (value) { 394 | CONTROL_SET_BUS1(); 395 | } else { 396 | CONTROL_SET_BUS0(); 397 | } 398 | save = 1; 399 | } 400 | break; 401 | case OPTION_KEY_REPEAT: 402 | value = g_key_repeat_next * 10; 403 | if (handle_option_value(S_OPTION_KEY_REPEAT, &value, 50, 500, 50)) { 404 | g_key_repeat_next = value / 10; 405 | save = 1; 406 | } 407 | break; 408 | case OPTION_TICKER_SPEED: 409 | value = g_ticker_rate * 10; 410 | if (handle_option_value(S_OPTION_TICKER_SPEED, &value, 50, 500, 50)) { 411 | g_ticker_rate = value / 10; 412 | save = 1; 413 | } 414 | break; 415 | case OPTION_TICKER_HOLD: 416 | value = g_ticker_hold_rate * 10; 417 | if (handle_option_value(S_OPTION_TICKER_HOLD, &value, 250, 2500, 250)) { 418 | g_ticker_hold_rate = value / 10; 419 | save = 1; 420 | } 421 | break; 422 | case OPTION_REC_FINALIZE: 423 | value = g_rec_finalize_time * 10; 424 | if (handle_option_value(S_OPTION_REC_FINALIZE, &value, 500, 2500, 500)) { 425 | g_rec_finalize_time = value / 10; 426 | save = 1; 427 | } 428 | break; 429 | case OPTION_REC_AUTO_FINALIZE: 430 | value = g_rec_auto_finalize; 431 | if (handle_option_value(S_OPTION_REC_AUTO_FINALIZE, &value, 0, 1, 1)) { 432 | g_rec_auto_finalize = value; 433 | save = 1; 434 | } 435 | break; 436 | case SELECT_MODE_EXIT: 437 | if (save) { 438 | save_eeprom_data(); 439 | } 440 | return; 441 | break; 442 | } 443 | } 444 | } 445 | 446 | 447 | 448 | void main_menu(FILINFO* pfile_info) { 449 | const char* ppitems[] = {S_MODE_PLAY, S_MODE_RECORD, S_MODE_OPTIONS}; 450 | uint8_t cur_mode = 0; 451 | if ((g_num_files = get_num_files(pfile_info)) == 0) { 452 | lcd_title_P(S_NO_FILES_FOUND); 453 | return; 454 | } 455 | 456 | while (1) { 457 | cur_mode = handle_select_mode(S_SELECT_MODE, ppitems, 3, cur_mode); 458 | switch (cur_mode) { 459 | case MODE_PLAY: 460 | handle_play_mode(pfile_info); 461 | break; 462 | case MODE_RECORD: 463 | handle_record_mode(pfile_info); 464 | break; 465 | case MODE_OPTIONS: 466 | handle_mode_options(); 467 | break; 468 | case SELECT_MODE_EXIT: 469 | cur_mode = 0; 470 | break; 471 | } 472 | } 473 | } -------------------------------------------------------------------------------- /layout/eagle/v1.4/buttons template.brd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | Use 4mm or 4.5mm drill 87 | Align this line with the center 88 | of plastic standoff in the box 89 | 90 | 91 | 92 | <b>Special drills</b><p> 93 | For drills bigger as 0.51602 Inch you must draw a circle in Layer 20 Dimension.<br> 94 | See also HELP HOLE, 95 | 96 | 97 | <b>156th Marker</b> 156 thousands of an inch 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | <b>EAGLE Design Rules</b> 113 | <p> 114 | Die Standard-Design-Rules sind so gewählt, dass sie für 115 | die meisten Anwendungen passen. Sollte ihre Platine 116 | besondere Anforderungen haben, treffen Sie die erforderlichen 117 | Einstellungen hier und speichern die Design Rules unter 118 | einem neuen Namen ab. 119 | <b>EAGLE Design Rules</b> 120 | <p> 121 | The default Design Rules have been set to cover 122 | a wide range of applications. Your particular design 123 | may have different requirements, so please make the 124 | necessary adjustments and save your customized 125 | design rules under a new name. 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | Since Version 6.2.2 text objects can contain more than one line, 303 | which will not be processed correctly with this version. 304 | 305 | 306 | 307 | -------------------------------------------------------------------------------- /mmc.c: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------*/ 2 | /* MMCv3/SDv1/SDv2 (in SPI mode) control module (C)ChaN, 2010 */ 3 | /*-----------------------------------------------------------------------*/ 4 | 5 | #include 6 | #include 7 | #include "integer.h" 8 | #include "spi.h" 9 | #include "mmc.h" 10 | #include "diskio.h" 11 | 12 | 13 | /*-------------------------------------------------------------------------- 14 | 15 | Module Private Functions 16 | 17 | ---------------------------------------------------------------------------*/ 18 | 19 | 20 | static volatile 21 | DSTATUS Stat = STA_NOINIT; /* Disk status */ 22 | 23 | static volatile 24 | BYTE Timer1, Timer2; /* 100Hz decrement timer */ 25 | 26 | static 27 | BYTE CardType; /* Card type flags */ 28 | 29 | 30 | /*-----------------------------------------------------------------------*/ 31 | /* Power Control (Platform dependent) */ 32 | /*-----------------------------------------------------------------------*/ 33 | /* When the target system does not support socket power control, there */ 34 | /* is nothing to do in these functions and chk_power always returns 1. */ 35 | 36 | static 37 | void power_on (void) 38 | { 39 | SPI_Init(); 40 | } 41 | 42 | static 43 | void power_off (void) 44 | { 45 | SPCR = 0; /* Disable SPI function */ 46 | } 47 | 48 | 49 | 50 | /*-----------------------------------------------------------------------*/ 51 | /* Transmit/Receive data from/to MMC via SPI (Platform dependent) */ 52 | /*-----------------------------------------------------------------------*/ 53 | 54 | /* Exchange a byte */ 55 | static 56 | BYTE xchg_spi ( /* Returns received data */ 57 | BYTE dat /* Data to be sent */ 58 | ) 59 | { 60 | SPDR = dat; 61 | loop_until_bit_is_set(SPSR, SPIF); 62 | return SPDR; 63 | } 64 | 65 | /* Send a data block fast */ 66 | static 67 | void xmit_spi_multi ( 68 | const BYTE *p, /* Data block to be sent */ 69 | UINT cnt /* Size of data block (must be multiple of 2) */ 70 | ) 71 | { 72 | do { 73 | SPDR = *p++; loop_until_bit_is_set(SPSR,SPIF); 74 | SPDR = *p++; loop_until_bit_is_set(SPSR,SPIF); 75 | } while (cnt -= 2); 76 | } 77 | 78 | /* Receive a data block fast */ 79 | static 80 | void rcvr_spi_multi ( 81 | BYTE *p, /* Data buffer */ 82 | UINT cnt /* Size of data block (must be multiple of 2) */ 83 | ) 84 | { 85 | do { 86 | SPDR = 0xFF; loop_until_bit_is_set(SPSR,SPIF); *p++ = SPDR; 87 | SPDR = 0xFF; loop_until_bit_is_set(SPSR,SPIF); *p++ = SPDR; 88 | } while (cnt -= 2); 89 | } 90 | 91 | 92 | 93 | /*-----------------------------------------------------------------------*/ 94 | /* Wait for card ready */ 95 | /*-----------------------------------------------------------------------*/ 96 | 97 | static 98 | int wait_ready ( /* 1:Ready, 0:Timeout */ 99 | UINT wt /* Timeout [ms] */ 100 | ) 101 | { 102 | BYTE d; 103 | 104 | 105 | Timer2 = wt / 10; 106 | do 107 | d = xchg_spi(0xFF); 108 | while (d != 0xFF && Timer2); 109 | 110 | return (d == 0xFF) ? 1 : 0; 111 | } 112 | 113 | 114 | 115 | /*-----------------------------------------------------------------------*/ 116 | /* Deselect the card and release SPI bus */ 117 | /*-----------------------------------------------------------------------*/ 118 | 119 | static 120 | void deselect (void) 121 | { 122 | SPI_DESELECT(); 123 | xchg_spi(0xFF); /* Dummy clock (force DO hi-z for multiple slave SPI) */ 124 | } 125 | 126 | 127 | 128 | /*-----------------------------------------------------------------------*/ 129 | /* Select the card and wait for ready */ 130 | /*-----------------------------------------------------------------------*/ 131 | 132 | static 133 | int select (int check_ready) /* 1:Successful, 0:Timeout */ 134 | { 135 | SPI_SELECT(); 136 | xchg_spi(0xFF); /* Dummy clock (force DO enabled) */ 137 | 138 | if (!check_ready) return 1; 139 | 140 | if (wait_ready(500)) return 1; /* OK */ 141 | deselect(); 142 | return 0; /* Timeout */ 143 | } 144 | 145 | 146 | 147 | /*-----------------------------------------------------------------------*/ 148 | /* Receive a data packet from MMC */ 149 | /*-----------------------------------------------------------------------*/ 150 | 151 | static 152 | int rcvr_datablock ( 153 | BYTE *buff, /* Data buffer to store received data */ 154 | UINT btr /* Byte count (must be multiple of 4) */ 155 | ) 156 | { 157 | BYTE token; 158 | 159 | 160 | Timer1 = 20; 161 | do { /* Wait for data packet in timeout of 200ms */ 162 | token = xchg_spi(0xFF); 163 | } while ((token == 0xFF) && Timer1); 164 | if (token != 0xFE) return 0; /* If not valid data token, retutn with error */ 165 | 166 | rcvr_spi_multi(buff, btr); /* Receive the data block into buffer */ 167 | xchg_spi(0xFF); /* Discard CRC */ 168 | xchg_spi(0xFF); 169 | 170 | return 1; /* Return with success */ 171 | } 172 | 173 | 174 | 175 | /*-----------------------------------------------------------------------*/ 176 | /* Send a data packet to MMC */ 177 | /*-----------------------------------------------------------------------*/ 178 | 179 | #if _USE_WRITE 180 | static 181 | int xmit_datablock ( 182 | const BYTE *buff, /* 512 byte data block to be transmitted */ 183 | BYTE token /* Data/Stop token */ 184 | ) 185 | { 186 | BYTE resp; 187 | 188 | 189 | if (!wait_ready(500)) return 0; 190 | 191 | xchg_spi(token); /* Xmit data token */ 192 | if (token != 0xFD) { /* Is data token */ 193 | xmit_spi_multi(buff, 512); /* Xmit the data block to the MMC */ 194 | xchg_spi(0xFF); /* CRC (Dummy) */ 195 | xchg_spi(0xFF); 196 | resp = xchg_spi(0xFF); /* Reveive data response */ 197 | if ((resp & 0x1F) != 0x05) /* If not accepted, return with error */ 198 | return 0; 199 | } 200 | 201 | return 1; 202 | } 203 | #endif 204 | 205 | 206 | 207 | /*-----------------------------------------------------------------------*/ 208 | /* Send a command packet to MMC */ 209 | /*-----------------------------------------------------------------------*/ 210 | 211 | static 212 | BYTE send_cmd ( /* Returns R1 resp (bit7==1:Send failed) */ 213 | BYTE cmd, /* Command index */ 214 | DWORD arg /* Argument */ 215 | ) 216 | { 217 | BYTE n, res; 218 | 219 | 220 | if (cmd & 0x80) { /* ACMD is the command sequense of CMD55-CMD */ 221 | cmd &= 0x7F; 222 | res = send_cmd(CMD55, 0); 223 | if (res > 1) return res; 224 | } 225 | 226 | /* Select the card and wait for ready except to stop multiple block read */ 227 | if (cmd != CMD12) { 228 | deselect(); 229 | if (!select(cmd != CMD0)) return 0xFF; 230 | } 231 | 232 | /* Send command packet */ 233 | xchg_spi(0x40 | cmd); /* Start + Command index */ 234 | xchg_spi((BYTE)(arg >> 24)); /* Argument[31..24] */ 235 | xchg_spi((BYTE)(arg >> 16)); /* Argument[23..16] */ 236 | xchg_spi((BYTE)(arg >> 8)); /* Argument[15..8] */ 237 | xchg_spi((BYTE)arg); /* Argument[7..0] */ 238 | n = 0x01; /* Dummy CRC + Stop */ 239 | if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) + Stop */ 240 | if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) Stop */ 241 | xchg_spi(n); 242 | 243 | /* Receive command response */ 244 | if (cmd == CMD12) xchg_spi(0xFF); /* Skip a stuff byte when stop reading */ 245 | n = 10; /* Wait for a valid response in timeout of 10 attempts */ 246 | do 247 | res = xchg_spi(0xFF); 248 | while ((res & 0x80) && --n); 249 | 250 | return res; /* Return with the response value */ 251 | } 252 | 253 | 254 | 255 | /*-------------------------------------------------------------------------- 256 | 257 | Public Functions 258 | 259 | ---------------------------------------------------------------------------*/ 260 | 261 | 262 | /*-----------------------------------------------------------------------*/ 263 | /* Initialize Disk Drive */ 264 | /*-----------------------------------------------------------------------*/ 265 | 266 | DSTATUS disk_initialize ( 267 | BYTE pdrv /* Physical drive nmuber (0) */ 268 | ) 269 | { 270 | BYTE n, cmd, ty, ocr[4]; 271 | 272 | 273 | if (pdrv) return STA_NOINIT; /* Supports only single drive */ 274 | power_off(); /* Turn off the socket power to reset the card */ 275 | if (Stat & STA_NODISK) return Stat; /* No card in the socket */ 276 | power_on(); /* Turn on the socket power */ 277 | SPI_Speed_Slow(); 278 | for (n = 10; n; n--) xchg_spi(0xFF); /* 80 dummy clocks */ 279 | 280 | ty = 0; 281 | if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */ 282 | Timer1 = 100; /* Initialization timeout of 1000 msec */ 283 | if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2? */ 284 | for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF); /* Get trailing return value of R7 resp */ 285 | if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */ 286 | while (Timer1 && send_cmd(ACMD41, 1UL << 30)); /* Wait for leaving idle state (ACMD41 with HCS bit) */ 287 | if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */ 288 | for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF); 289 | ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 */ 290 | } 291 | } 292 | } else { /* SDv1 or MMCv3 */ 293 | if (send_cmd(ACMD41, 0) <= 1) { 294 | ty = CT_SD1; cmd = ACMD41; /* SDv1 */ 295 | } else { 296 | ty = CT_MMC; cmd = CMD1; /* MMCv3 */ 297 | } 298 | while (Timer1 && send_cmd(cmd, 0)); /* Wait for leaving idle state */ 299 | if (!Timer1 || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */ 300 | ty = 0; 301 | } 302 | } 303 | CardType = ty; 304 | deselect(); 305 | 306 | if (ty) { /* Initialization succeded */ 307 | Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */ 308 | SPI_Speed_Fast(); 309 | } else { /* Initialization failed */ 310 | power_off(); 311 | } 312 | 313 | return Stat; 314 | } 315 | 316 | 317 | 318 | /*-----------------------------------------------------------------------*/ 319 | /* Get Disk Status */ 320 | /*-----------------------------------------------------------------------*/ 321 | 322 | DSTATUS disk_status ( 323 | BYTE pdrv /* Physical drive nmuber (0) */ 324 | ) 325 | { 326 | if (pdrv) return STA_NOINIT; /* Supports only single drive */ 327 | return Stat; 328 | } 329 | 330 | 331 | 332 | /*-----------------------------------------------------------------------*/ 333 | /* Read Sector(s) */ 334 | /*-----------------------------------------------------------------------*/ 335 | 336 | DRESULT disk_read ( 337 | BYTE pdrv, /* Physical drive nmuber (0) */ 338 | BYTE *buff, /* Pointer to the data buffer to store read data */ 339 | DWORD sector, /* Start sector number (LBA) */ 340 | UINT count /* Sector count (1..128) */ 341 | ) 342 | { 343 | BYTE cmd; 344 | 345 | 346 | if (pdrv || !count) return RES_PARERR; 347 | if (Stat & STA_NOINIT) return RES_NOTRDY; 348 | 349 | if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */ 350 | 351 | cmd = count > 1 ? CMD18 : CMD17; /* READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */ 352 | if (send_cmd(cmd, sector) == 0) { 353 | do { 354 | if (!rcvr_datablock(buff, 512)) break; 355 | buff += 512; 356 | } while (--count); 357 | if (cmd == CMD18) send_cmd(CMD12, 0); /* STOP_TRANSMISSION */ 358 | } 359 | deselect(); 360 | 361 | return count ? RES_ERROR : RES_OK; 362 | } 363 | 364 | 365 | 366 | /*-----------------------------------------------------------------------*/ 367 | /* Write Sector(s) */ 368 | /*-----------------------------------------------------------------------*/ 369 | 370 | #if _USE_WRITE 371 | DRESULT disk_write ( 372 | BYTE pdrv, /* Physical drive nmuber (0) */ 373 | const BYTE *buff, /* Pointer to the data to be written */ 374 | DWORD sector, /* Start sector number (LBA) */ 375 | UINT count /* Sector count (1..128) */ 376 | ) 377 | { 378 | if (pdrv || !count) return RES_PARERR; 379 | if (Stat & STA_NOINIT) return RES_NOTRDY; 380 | if (Stat & STA_PROTECT) return RES_WRPRT; 381 | 382 | if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */ 383 | 384 | if (count == 1) { /* Single block write */ 385 | if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */ 386 | && xmit_datablock(buff, 0xFE)) 387 | count = 0; 388 | } 389 | else { /* Multiple block write */ 390 | if (CardType & CT_SDC) send_cmd(ACMD23, count); 391 | if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */ 392 | do { 393 | if (!xmit_datablock(buff, 0xFC)) break; 394 | buff += 512; 395 | } while (--count); 396 | if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */ 397 | count = 1; 398 | } 399 | } 400 | deselect(); 401 | 402 | return count ? RES_ERROR : RES_OK; 403 | } 404 | #endif 405 | 406 | 407 | /*-----------------------------------------------------------------------*/ 408 | /* Miscellaneous Functions */ 409 | /*-----------------------------------------------------------------------*/ 410 | 411 | #if _USE_IOCTL 412 | DRESULT disk_ioctl ( 413 | BYTE pdrv, /* Physical drive nmuber (0) */ 414 | BYTE cmd, /* Control code */ 415 | void *buff /* Buffer to send/receive control data */ 416 | ) 417 | { 418 | DRESULT res; 419 | BYTE n, csd[16], *ptr = buff; 420 | DWORD csize; 421 | 422 | 423 | if (pdrv) return RES_PARERR; 424 | 425 | res = RES_ERROR; 426 | 427 | if (Stat & STA_NOINIT) return RES_NOTRDY; 428 | 429 | switch (cmd) { 430 | case CTRL_SYNC : /* Make sure that no pending write process. Do not remove this or written sector might not left updated. */ 431 | if (select(1)) res = RES_OK; 432 | break; 433 | 434 | case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */ 435 | if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { 436 | if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */ 437 | csize = csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 16) + 1; 438 | *(DWORD*)buff = csize << 10; 439 | } else { /* SDC ver 1.XX or MMC*/ 440 | n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2; 441 | csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1; 442 | *(DWORD*)buff = csize << (n - 9); 443 | } 444 | res = RES_OK; 445 | } 446 | break; 447 | 448 | case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */ 449 | if (CardType & CT_SD2) { /* SDv2? */ 450 | if (send_cmd(ACMD13, 0) == 0) { /* Read SD status */ 451 | xchg_spi(0xFF); 452 | if (rcvr_datablock(csd, 16)) { /* Read partial block */ 453 | for (n = 64 - 16; n; n--) xchg_spi(0xFF); /* Purge trailing data */ 454 | *(DWORD*)buff = 16UL << (csd[10] >> 4); 455 | res = RES_OK; 456 | } 457 | } 458 | } else { /* SDv1 or MMCv3 */ 459 | if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { /* Read CSD */ 460 | if (CardType & CT_SD1) { /* SDv1 */ 461 | *(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1); 462 | } else { /* MMCv3 */ 463 | *(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1); 464 | } 465 | res = RES_OK; 466 | } 467 | } 468 | break; 469 | 470 | /* Following commands are never used by FatFs module */ 471 | 472 | case MMC_GET_TYPE : /* Get card type flags (1 byte) */ 473 | *ptr = CardType; 474 | res = RES_OK; 475 | break; 476 | 477 | case MMC_GET_CSD : /* Receive CSD as a data block (16 bytes) */ 478 | if (send_cmd(CMD9, 0) == 0 /* READ_CSD */ 479 | && rcvr_datablock(ptr, 16)) 480 | res = RES_OK; 481 | break; 482 | 483 | case MMC_GET_CID : /* Receive CID as a data block (16 bytes) */ 484 | if (send_cmd(CMD10, 0) == 0 /* READ_CID */ 485 | && rcvr_datablock(ptr, 16)) 486 | res = RES_OK; 487 | break; 488 | 489 | case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */ 490 | if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */ 491 | for (n = 4; n; n--) *ptr++ = xchg_spi(0xFF); 492 | res = RES_OK; 493 | } 494 | break; 495 | 496 | case MMC_GET_SDSTAT : /* Receive SD statsu as a data block (64 bytes) */ 497 | if (send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */ 498 | xchg_spi(0xFF); 499 | if (rcvr_datablock(ptr, 64)) 500 | res = RES_OK; 501 | } 502 | break; 503 | 504 | // case CTRL_POWER_OFF : /* Power off * 505 | // power_off(); 506 | // Stat |= STA_NOINIT; 507 | // break; 508 | 509 | default: 510 | res = RES_PARERR; 511 | } 512 | 513 | deselect(); 514 | 515 | return res; 516 | } 517 | #endif 518 | 519 | 520 | /*-----------------------------------------------------------------------*/ 521 | /* Device Timer Interrupt Procedure */ 522 | /*-----------------------------------------------------------------------*/ 523 | /* This function must be called in period of 10ms */ 524 | 525 | void disk_timerproc (void) 526 | { 527 | BYTE n; 528 | 529 | n = Timer1; /* 100Hz decrement timer */ 530 | if (n) Timer1 = --n; 531 | n = Timer2; 532 | if (n) Timer2 = --n; 533 | 534 | } 535 | -------------------------------------------------------------------------------- /layout/eagle/v1.4/1602 QAPASS LCD Template -0.5.brd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -0.5mm Tol. 84 | 4 x 3mm (or 3.25mm) drill 85 | Use 6mm drill 86 | CHECK WITH YOUR LCD BEFORE DRILLING 87 | 88 | 89 | 90 | <b>Mounting Holes and Pads</b><p> 91 | <author>Created by librarian@cadsoft.de</author> 92 | 93 | 94 | <b>MOUNTING HOLE</b> 3.0 mm with drill center 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 3,0 106 | 107 | 108 | 109 | 110 | 111 | <b>Special drills</b><p> 112 | For drills bigger as 0.51602 Inch you must draw a circle in Layer 20 Dimension.<br> 113 | See also HELP HOLE, 114 | 115 | 116 | <b>1/4" Marker</b> 250 thousands of an inch 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | <b>EAGLE Design Rules</b> 132 | <p> 133 | Die Standard-Design-Rules sind so gewählt, dass sie für 134 | die meisten Anwendungen passen. Sollte ihre Platine 135 | besondere Anforderungen haben, treffen Sie die erforderlichen 136 | Einstellungen hier und speichern die Design Rules unter 137 | einem neuen Namen ab. 138 | <b>EAGLE Design Rules</b> 139 | <p> 140 | The default Design Rules have been set to cover 141 | a wide range of applications. Your particular design 142 | may have different requirements, so please make the 143 | necessary adjustments and save your customized 144 | design rules under a new name. 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | --------------------------------------------------------------------------------