├── Datasheets ├── AT45DB161D.pdf ├── Using Atmel’s Serial DataFlash.pdf └── mcp2515.pdf ├── FSM Library ├── Examples FSM │ ├── FSM_0to100 │ │ ├── FSM_0to100.pde │ │ └── myStates.h │ ├── FSM_v5 │ │ ├── FSM_v5.pde │ │ └── myStates.h │ └── FSM_v6 │ │ ├── FSM_v6.pde │ │ ├── diagrama.ods │ │ └── myStates.h ├── FSM.cpp ├── FSM.h ├── FSMv3.pdf └── README ├── Fast_Acquisition ├── Fast_Acquisition_4.pde ├── README └── adquisicion.py ├── Golf_MK4_Remote_Rolling_Windows ├── README └── RemoteControlRollingWindow.pde ├── Loopback Mode └── SECUduino_Example_Loopback_Mode.pde ├── OBD_RPM_Example └── OBD_RPM_Example.pde ├── PID ├── PID_2.pde └── README ├── R+D └── at45db161d │ ├── Atmel │ ├── AVR335_Digital_Sound_Recorder_with_AVR_and_DataFlash.pdf │ └── Code AVR335 │ │ ├── ICCAVR228A │ │ ├── dataflash.h │ │ ├── sound_recorder.prj │ │ └── sound_system2.c │ │ └── ICCAVR320C │ │ ├── dataflash.h │ │ ├── sound_system.ewp │ │ ├── sound_system.eww │ │ └── sound_system2.c │ ├── README │ ├── at45db161d.cpp │ ├── at45db161d.h │ ├── at45db161d_commands.h │ └── examples │ ├── DataFlash_example1 │ └── DataFlash_example1.ino │ ├── DataFlash_example2 │ └── DataFlash_example2.ino │ └── DataFlash_example3_CAN │ └── DataFlash_example3_CAN.ino ├── README └── Schematics ├── ESQUEMA SECUduino 2.pdf └── ESQUEMA SECUduino.pdf /Datasheets/AT45DB161D.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IgorReal/SECUduino/1d873ff874f276ea3889af50efd877d6c15a5803/Datasheets/AT45DB161D.pdf -------------------------------------------------------------------------------- /Datasheets/Using Atmel’s Serial DataFlash.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IgorReal/SECUduino/1d873ff874f276ea3889af50efd877d6c15a5803/Datasheets/Using Atmel’s Serial DataFlash.pdf -------------------------------------------------------------------------------- /Datasheets/mcp2515.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IgorReal/SECUduino/1d873ff874f276ea3889af50efd877d6c15a5803/Datasheets/mcp2515.pdf -------------------------------------------------------------------------------- /FSM Library/Examples FSM/FSM_0to100/FSM_0to100.pde: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------------- 2 | // SECUduino: Chrono 0 to 100 kph 3 | // By Igor Real 4 | // 22/10/2011 5 | // ------------------------------------------------------------------------------------- 6 | 7 | #include 8 | #include 9 | #include 10 | #include "myStates.h" 11 | 12 | #define delayShowData 7000 13 | 14 | //VARIABLES 15 | unsigned char myEvent; 16 | char myByteRec; 17 | unsigned long my0to100; 18 | unsigned long t0; 19 | unsigned long t_prev; 20 | float Speed; 21 | char bUpdateLCD; 22 | 23 | LiquidCrystal LCD(13,12, 11, 10, 9, 8, 7); 24 | 25 | void setup() 26 | { 27 | 28 | LCD.begin(20,4); 29 | bUpdateLCD=1; 30 | func1(); //Print Initial screen 31 | 32 | CAN.begin(100); 33 | uint16_t Filters[6]; 34 | uint16_t Masks[2]; 35 | Masks[0]=0x3FF; 36 | Masks[1]=0x3FF; 37 | Filters[0]=0x351; //Buffer0 38 | Filters[2]=0x351; //Buffer1 39 | CAN.SetFilters(Filters,Masks); //Only messages with ID=0x351 are allowed in both Rx buffers 40 | 41 | FSM.begin(FSM_NextState,nStateMachine,FSM_State,nStateFcn,STATE1); 42 | } 43 | 44 | void loop() 45 | { 46 | ReadEvents(); 47 | FSM.Update(); 48 | } 49 | 50 | 51 | void ReadEvents(void) 52 | { 53 | 54 | if (CAN.CheckNew() ) 55 | { 56 | CAN.ReadFromDevice(&CAN_RxMsg); 57 | Speed=0.005*(256*CAN_RxMsg.data[2]+CAN_RxMsg.data[1]); 58 | //Speed=CAN_RxMsg.data[0]; 59 | LCD.setCursor(0,1); 60 | LCD.print("Speed= "); 61 | LCD.print((int)Speed); 62 | } 63 | 64 | if (Speed<=0){ 65 | FSM.AddEvent(EV_Stop); 66 | }else if (Speed>=100){ 67 | FSM.AddEvent(EV_100); 68 | }else if ( (Speed>0) && (Speed<100) ){ 69 | FSM.AddEvent(EV_Start); 70 | } 71 | 72 | } 73 | 74 | void func1(void) 75 | { 76 | if (bUpdateLCD) 77 | { 78 | LCD.clear(); 79 | LCD.setCursor(0,0); 80 | LCD.print(" *- SECUduino -*"); 81 | 82 | LCD.setCursor(0,2); 83 | LCD.print("State 1"); 84 | 85 | bUpdateLCD=0; 86 | } 87 | } 88 | void func2(void) 89 | { 90 | LCD.setCursor(0,2); 91 | LCD.print("State 2"); 92 | bUpdateLCD=1; 93 | } 94 | 95 | void func3(void) 96 | { 97 | t0=millis(); 98 | LCD.setCursor(0,2); 99 | LCD.print("State 3"); 100 | FSM.AddEvent(0); 101 | } 102 | 103 | void func4(void) 104 | { 105 | LCD.setCursor(0,2); 106 | LCD.print("State 4"); 107 | } 108 | 109 | void func5(void) 110 | { 111 | my0to100=millis()-t0; 112 | t_prev=millis(); 113 | LCD.setCursor(0,2); 114 | LCD.print("State 4"); 115 | 116 | LCD.setCursor(0,3); 117 | LCD.print((float)my0to100/(float)1000.0); 118 | LCD.print(" s"); 119 | 120 | while(millis()-t_prev<=delayShowData); 121 | FSM.AddEvent(EV_Wait); 122 | } 123 | 124 | 125 | -------------------------------------------------------------------------------- /FSM Library/Examples FSM/FSM_0to100/myStates.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------- 2 | //ESTE ES EL ÚNICO FICHERO QUE HAY QUE MODIFICAR 3 | //----------------------------------------------------- 4 | 5 | #ifndef myStates_H 6 | #define myStates_H 7 | 8 | 9 | //Declaracion de las funciones 10 | extern void func1(void); 11 | extern void func2(void); 12 | extern void func3(void); 13 | extern void func4(void); 14 | extern void func5(void); 15 | 16 | //Declaracion del nombre de ESTADOS y de EVENTOS 17 | #define STATE1 0x01 18 | #define STATE2 0x02 19 | #define STATE3 0x03 20 | #define STATE4 0x04 21 | #define STATE5 0x05 22 | 23 | #define EV_Start 0x01 24 | #define EV_100 0x02 25 | #define EV_Stop 0x03 26 | #define EV_Wait 0x04 27 | 28 | 29 | // Estructuras descriptivas de mi diagrama de flujo 30 | const FSMClass::FSM_State_t FSM_State[] PROGMEM= { 31 | // STATE,STATE_FUNC 32 | {STATE1,func1}, 33 | {STATE2,func2}, 34 | {STATE3,func3}, 35 | {STATE4,func4}, 36 | {STATE5,func5}, 37 | }; 38 | 39 | const FSMClass::FSM_NextState_t FSM_NextState[] PROGMEM= { 40 | // STATE,EVENT,NEXT_STATE 41 | {STATE1,EV_Stop,STATE2}, 42 | {STATE2,EV_Start,STATE3}, 43 | {STATE3,0,STATE4}, 44 | {STATE4,EV_100,STATE5}, 45 | {STATE4,EV_Stop,STATE1}, 46 | {STATE5,EV_Wait,STATE1}, 47 | }; 48 | 49 | 50 | //Macros para el cálculo de los tamaños de las estructuras 51 | //NO MODIFICAR 52 | #define nStateFcn sizeof(FSM_State)/sizeof(FSMClass::FSM_State_t) 53 | #define nStateMachine sizeof(FSM_NextState)/sizeof(FSMClass::FSM_NextState_t) 54 | 55 | #endif 56 | 57 | -------------------------------------------------------------------------------- /FSM Library/Examples FSM/FSM_v5/FSM_v5.pde: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------------- 2 | // Ejemplo libreria FSM 3 | // Si se recibe una secuencia por la UART del tipo SxxxxE, siendo xxxxx numeros 4 | // se recoge en una variable global llamada mynumber y se imprime por pantalla 5 | // S viene de Start y E de End. 6 | // El numero debe ser un unsigned long 7 | // ------------------------------------------------------------------------------------- 8 | 9 | #include 10 | #include "myStates.h" 11 | 12 | unsigned char myEvent; 13 | char myByteRec; 14 | unsigned long mynumber; 15 | 16 | 17 | 18 | void setup() 19 | { 20 | Serial.begin(9600); 21 | Serial.println("Empezamos..."); 22 | 23 | // Inicializo mi maquina de estados. Le paso las estructuras y sus tamaños,que definen el diagrama de flujo 24 | // y le paso el estado inicial. 25 | FSM.begin(FSM_NextState,nStateMachine,FSM_State,nStateFcn,STATE1); 26 | } 27 | 28 | void loop() 29 | { 30 | //PASOS DE LA MAQUINA DE ESTADOS 31 | // Primer paso: LEO EVENTOS EXTERNOS 32 | // Segundo paso: ACTUALIZO ESTADOS 33 | // Tercer paso: EJECUTO FUNCION CORRESPONDIENTE A DICHO ESTADO 34 | // Cuaro paso: ACTUALIZO ESTADOS DEPENDIENDO DE LOS EVENTOS INTERNOS GENERADOS 35 | 36 | ReadEvents(); 37 | FSM.Update(); 38 | 39 | } 40 | 41 | 42 | void ReadEvents(void) 43 | { 44 | myEvent=0; 45 | if (Serial.available()>0) 46 | { 47 | myByteRec=Serial.read(); 48 | 49 | if (myByteRec=='S') 50 | { 51 | myEvent=EV_S; //Evento recibido S 52 | }else if ( (myByteRec>='0') && (myByteRec<='9') ) 53 | { 54 | myEvent=EV_NUMBER; //Evento recibido un numero 55 | }else if (myByteRec=='E') 56 | { 57 | myEvent=EV_E; //Evento recibido E 58 | }else 59 | { 60 | myEvent=EV_ERROR; //Evento recibido caracter no valido 61 | } 62 | } 63 | 64 | FSM.AddEvent(myEvent); 65 | 66 | 67 | } 68 | 69 | //Funciones correspondientes a los ESTADOS 70 | void func1(void) 71 | { 72 | mynumber=0; 73 | } 74 | void func2(void) 75 | { 76 | if (myEvent==EV_NUMBER) 77 | { 78 | mynumber=mynumber*10+(myByteRec-0x30); 79 | } 80 | } 81 | void func3(void) 82 | { 83 | if (myEvent==EV_E) 84 | { 85 | Serial.print("RECIBIDO NUMERO="); 86 | Serial.println(mynumber); 87 | mynumber=0; 88 | } 89 | 90 | } 91 | 92 | 93 | -------------------------------------------------------------------------------- /FSM Library/Examples FSM/FSM_v5/myStates.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------- 2 | //ESTE ES EL ÚNICO FICHERO QUE HAY QUE MODIFICAR 3 | //----------------------------------------------------- 4 | 5 | #ifndef myStates_H 6 | #define myStates_H 7 | 8 | 9 | //Declaracion de las funciones 10 | extern void func1(void); 11 | extern void func2(void); 12 | extern void func3(void); 13 | 14 | 15 | //Declaracion del nombre de ESTADOS y de EVENTOS 16 | #define STATE1 0x01 17 | #define STATE2 0x02 18 | #define STATE3 0x03 19 | 20 | #define EV_S 0x41 21 | #define EV_NUMBER 0x42 22 | #define EV_E 0x43 23 | #define EV_ERROR 0x44 24 | 25 | // Estructuras descriptivas de mi diagrama de flujo 26 | const FSMClass::FSM_State_t FSM_State[] PROGMEM= { 27 | // STATE,STATE_FUNC 28 | {STATE1,func1}, 29 | {STATE2,func2}, 30 | {STATE3,func3}, 31 | }; 32 | 33 | const FSMClass::FSM_NextState_t FSM_NextState[] PROGMEM= { 34 | // STATE,EVENT,NEXT_STATE 35 | {STATE1,EV_S,STATE2}, 36 | {STATE2,EV_NUMBER,STATE2}, 37 | {STATE2,EV_E,STATE3}, 38 | {STATE2,EV_ERROR,STATE1}, 39 | {STATE2,EV_S,STATE1}, 40 | {STATE3,0,STATE1}, 41 | }; 42 | 43 | 44 | //Macros para el cálculo de los tamaños de las estructuras 45 | //NO MODIFICAR 46 | #define nStateFcn sizeof(FSM_State)/sizeof(FSMClass::FSM_State_t) 47 | #define nStateMachine sizeof(FSM_NextState)/sizeof(FSMClass::FSM_NextState_t) 48 | 49 | #endif 50 | 51 | -------------------------------------------------------------------------------- /FSM Library/Examples FSM/FSM_v6/FSM_v6.pde: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------------- 2 | // Ejemplo libreria FSM 3 | // Si se recibe una S (Start) por la UART empieza a cronometrar 4 | // Cuando recibe una E (End) por la UART, imprime el tiempo cronometrado hasta ese momento 5 | // ------------------------------------------------------------------------------------- 6 | 7 | #include 8 | #include "myStates.h" 9 | 10 | unsigned char myEvent; 11 | char myByteRec; 12 | unsigned long t0; 13 | 14 | 15 | 16 | void setup() 17 | { 18 | Serial.begin(9600); 19 | Serial.println("Empezamos..."); 20 | 21 | // Inicializo mi maquina de estados. Le paso las estructuras y sus tamaños,que definen el diagrama de flujo 22 | // y le paso el estado inicial. 23 | FSM.begin(FSM_NextState,nStateMachine,FSM_State,nStateFcn,STATE1); 24 | } 25 | 26 | void loop() 27 | { 28 | //PASOS DE LA MAQUINA DE ESTADOS 29 | // Primer paso: LEO EVENTOS EXTERNOS 30 | // Segundo paso: ACTUALIZO ESTADOS 31 | // Tercer paso: EJECUTO FUNCION CORRESPONDIENTE A DICHO ESTADO 32 | // Cuaro paso: ACTUALIZO ESTADOS DEPENDIENDO DE LOS EVENTOS INTERNOS GENERADOS 33 | 34 | ReadEvents(); 35 | FSM.Update(); 36 | 37 | } 38 | 39 | 40 | void ReadEvents(void) 41 | { 42 | myEvent=0; 43 | if (Serial.available()>0) 44 | { 45 | myByteRec=Serial.read(); 46 | 47 | if (myByteRec=='S') 48 | { 49 | myEvent=EV_S; //Evento recibido S 50 | }else if (myByteRec=='E') 51 | { 52 | myEvent=EV_E; //Evento recibido E 53 | }else 54 | { 55 | myEvent=EV_ERROR; //Evento recibido caracter no valido 56 | } 57 | //Solo genero el evento si se ha recibido algo por serie 58 | FSM.AddEvent(myEvent); 59 | } 60 | 61 | 62 | 63 | 64 | } 65 | 66 | //Funciones correspondientes a los ESTADOS 67 | void func2(void) 68 | { 69 | t0=millis(); 70 | FSM.AddEvent(0); 71 | } 72 | void func4(void) 73 | { 74 | Serial.print("Tiempo transcurrido="); 75 | Serial.println((millis()-t0)/1000.0); 76 | FSM.AddEvent(0); 77 | } 78 | 79 | 80 | -------------------------------------------------------------------------------- /FSM Library/Examples FSM/FSM_v6/diagrama.ods: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IgorReal/SECUduino/1d873ff874f276ea3889af50efd877d6c15a5803/FSM Library/Examples FSM/FSM_v6/diagrama.ods -------------------------------------------------------------------------------- /FSM Library/Examples FSM/FSM_v6/myStates.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------- 2 | //ESTE ES EL ÚNICO FICHERO QUE HAY QUE MODIFICAR 3 | //----------------------------------------------------- 4 | 5 | #ifndef myStates_H 6 | #define myStates_H 7 | 8 | 9 | //Declaracion de las funciones 10 | extern void func2(void); 11 | extern void func4(void); 12 | 13 | 14 | //Declaracion del nombre de ESTADOS y de EVENTOS 15 | #define STATE1 0x01 16 | #define STATE2 0x02 17 | #define STATE3 0x03 18 | #define STATE4 0x04 19 | 20 | #define EV_S 0x41 21 | #define EV_E 0x43 22 | #define EV_ERROR 0x44 23 | 24 | // Estructuras descriptivas de mi diagrama de flujo 25 | const FSMClass::FSM_State_t FSM_State[] PROGMEM= { 26 | // STATE,STATE_FUNC 27 | {STATE1,0}, 28 | {STATE2,func2}, 29 | {STATE3,0}, 30 | {STATE4,func4}, 31 | }; 32 | 33 | const FSMClass::FSM_NextState_t FSM_NextState[] PROGMEM= { 34 | // STATE,EVENT,NEXT_STATE 35 | {STATE1,EV_S,STATE2}, 36 | {STATE2,0,STATE3}, 37 | {STATE3,EV_E,STATE4}, 38 | {STATE4,0,STATE1}, 39 | }; 40 | 41 | 42 | //Macros para el cálculo de los tamaños de las estructuras 43 | //NO MODIFICAR 44 | #define nStateFcn sizeof(FSM_State)/sizeof(FSMClass::FSM_State_t) 45 | #define nStateMachine sizeof(FSM_NextState)/sizeof(FSMClass::FSM_NextState_t) 46 | 47 | #endif 48 | 49 | -------------------------------------------------------------------------------- /FSM Library/FSM.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------- 2 | // Finite State Machine for Arduino 3 | // By: Igor Real 4 | // 17/10/2011 5 | //----------------------------------------------------------- 6 | 7 | #if defined(ARDUINO) && ARDUINO >= 100 8 | #include "Arduino.h" 9 | #else 10 | #include "WProgram.h" 11 | #endif 12 | 13 | #include "FSM.h" 14 | 15 | #define DEBUGMODE 0 16 | 17 | 18 | /****************************************************************************** 19 | * Variables 20 | ******************************************************************************/ 21 | FSMClass FSM; 22 | 23 | /****************************************************************************** 24 | * Constructors 25 | ******************************************************************************/ 26 | 27 | 28 | /****************************************************************************** 29 | * PUBLIC METHODS 30 | ******************************************************************************/ 31 | 32 | void FSMClass::begin(const FSM_NextState_t *FSM_NextState,unsigned char SizeNextState,const FSM_State_t *FSM_State,unsigned char SizeState,unsigned char State) 33 | { 34 | mySizeNextState=SizeNextState; 35 | mySizeState=SizeState; 36 | myState=State; 37 | myFSM_NextState=FSM_NextState; 38 | myFSM_State=FSM_State; 39 | } 40 | 41 | unsigned char FSMClass::State(void) 42 | { 43 | return myState; 44 | } 45 | 46 | void FSMClass::Update(void) 47 | { 48 | //Pasos: 49 | //Hay nuevo evento? Mientras exista nuevo evento: 50 | // 1- Limpio booleano 51 | // 2- Actualizo maquina de estados 52 | // 3- Ejecuto función correspondiente a dicho estado 53 | // [ Dicha función puede generar un nuevo evento (interno) ] 54 | 55 | while (mybNewEvent) 56 | { 57 | mybNewEvent=0; 58 | StateMachine(myEvent); 59 | StateFcn(); 60 | #if (DEBUGMODE==1) 61 | Serial.print("Estado="); 62 | Serial.println(myState,HEX); 63 | Serial.print("Evento ?="); 64 | Serial.println(mybNewEvent,HEX); 65 | #endif 66 | 67 | } 68 | } 69 | 70 | void FSMClass::AddEvent(unsigned char Event) 71 | { 72 | myEvent=Event; 73 | mybNewEvent=1; 74 | } 75 | 76 | 77 | /****************************************************************************** 78 | * PRIVATE METHODS 79 | ******************************************************************************/ 80 | unsigned char FSMClass::StateMachine(unsigned char event) 81 | { 82 | unsigned char new_state=0; 83 | 84 | for (uint8_t i=0; i 12 | 13 | 14 | //---------------------------------------------------------------------------- 15 | // CLASS 16 | //---------------------------------------------------------------------------- 17 | class FSMClass 18 | { 19 | public: 20 | //Variables: 21 | typedef void (*FuncPtr)(void); 22 | 23 | typedef struct PROGMEM 24 | { 25 | unsigned char state; // state 26 | FuncPtr pFunc; // pointer to a function 27 | } FSM_State_t; 28 | 29 | typedef struct PROGMEM 30 | { 31 | unsigned char state; // state 32 | unsigned char event; // input 33 | unsigned char next_state; // next_state 34 | } FSM_NextState_t; 35 | 36 | //Functions: 37 | void begin(const FSM_NextState_t *FSM_NextState,unsigned char SizeNextState,const FSM_State_t *FSM_State,unsigned char SizeState,unsigned char State); 38 | void Update(void); 39 | void AddEvent(unsigned char Event); 40 | 41 | private: 42 | //Functions: 43 | unsigned char StateMachine(unsigned char input); 44 | unsigned char StateFcn(); 45 | unsigned char State(void); 46 | 47 | //Variables: 48 | unsigned char mySizeNextState; 49 | unsigned char mySizeState; 50 | unsigned char myState; 51 | 52 | unsigned char myEvent; 53 | unsigned char mybNewEvent; 54 | 55 | const FSM_State_t *myFSM_State; 56 | const FSM_NextState_t *myFSM_NextState; 57 | 58 | }; 59 | //---------------------------------------------------------------------------- 60 | // VARIABLES 61 | //---------------------------------------------------------------------------- 62 | 63 | extern FSMClass FSM; 64 | 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /FSM Library/FSMv3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IgorReal/SECUduino/1d873ff874f276ea3889af50efd877d6c15a5803/FSM Library/FSMv3.pdf -------------------------------------------------------------------------------- /FSM Library/README: -------------------------------------------------------------------------------- 1 | Simple Finite State Machine library for Arduino 2 | -------------------------------------------------------------------------------- /Fast_Acquisition/Fast_Acquisition_4.pde: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | // Fast Acquisition 3 | // By: Igor R. 4 | // 03/09/2011 5 | //------------------------------------------------ 6 | 7 | 8 | #define CHRONO 0 9 | 10 | 11 | void setup() 12 | { 13 | Serial.begin(1000000); //1 Mbps 14 | 15 | //Prescaler 16 | //ADPS2 - ADPS1 - ADPS0 - Division Factor 17 | //0 - 0 - 0 ->2 18 | //0 - 0 - 1 ->2 19 | //0 - 1 - 0 ->4 20 | //0 - 1 - 1 ->8 21 | //1 - 0 - 0 ->16 22 | //1 - 0 - 1 ->32 23 | //1 - 1 - 0 ->64 24 | //1 - 1 - 1 ->128 25 | //Configure to Prescaler=16 (11793.57 Hz a 115200) 26 | //Configure to Prescaler=16 (66418.71 Hz a 1000000) 27 | 28 | bitWrite(ADCSRA,ADPS2,1); 29 | bitWrite(ADCSRA,ADPS1,0); 30 | bitWrite(ADCSRA,ADPS0,0); 31 | 32 | //Analog Input A5 33 | ADMUX=(1< http://real2electronics.blogspot.com/2011/09/arduino-adc-muestreo-alta-velocidad.html 2 | -------------------------------------------------------------------------------- /Fast_Acquisition/adquisicion.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | import serial 4 | import sys 5 | 6 | 7 | ser = serial.Serial('/dev/ttyUSB0', 1000000); 8 | while 1: 9 | try: 10 | n=ser.read(); 11 | n=ord(n)*5000/255; #Convierto en mV 12 | print n; 13 | except KeyboardInterrupt: 14 | ser.close(); 15 | sys.exit(0) 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Golf_MK4_Remote_Rolling_Windows/README: -------------------------------------------------------------------------------- 1 | Example of code to rolling up/down windows with the original remote control. 2 | -------------------------------------------------------------------------------- /Golf_MK4_Remote_Rolling_Windows/RemoteControlRollingWindow.pde: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------- 2 | // SECUduino 3 | // CAN CONFORT VW 4 | // Ejemplo bajar ventanillas con el mando inalambrico de la llave 5 | // 24/Apr/2011 6 | // By Igor Real 7 | // ------------------------------------------------------------------- 8 | 9 | #include 10 | long myCarOpening; 11 | long myCarClosing; 12 | int myfirsttime; 13 | 14 | void setup() 15 | { 16 | Serial.begin(115200); 17 | Serial.println("Empezamos..."); 18 | CAN.begin(100); 19 | 20 | CAN_TxMsg.id=0x181; 21 | CAN_TxMsg.header.rtr=0; 22 | CAN_TxMsg.header.length=3; 23 | CAN_TxMsg.data[0]=0x00; 24 | CAN_TxMsg.data[1]=0x00; 25 | CAN_TxMsg.data[2]=0x00; 26 | CAN_TxMsg.data[3]=0x00; 27 | CAN_TxMsg.data[4]=0x00; 28 | CAN_TxMsg.data[5]=0x00; 29 | CAN_TxMsg.data[6]=0x00; 30 | CAN_TxMsg.data[7]=0x00; 31 | 32 | myfirsttime=1; 33 | } 34 | 35 | void loop() 36 | { 37 | 38 | while (CAN.CheckNew()) 39 | { 40 | if ( CAN.ReadFromDevice(&CAN_RxMsg) ) 41 | { 42 | if (CAN_RxMsg.id==0x291) //Trama con la info del mando inalámbrico 43 | { 44 | //Serial.print("Byte 0="); 45 | //Serial.println(CAN_RxMsg.data[0],HEX); 46 | //OPENING 47 | if (CAN_RxMsg.data[0]==0x49) 48 | { 49 | myCarOpening++; 50 | myCarClosing=0; 51 | //Serial.print("Opening="); 52 | //Serial.println(myCarOpening,DEC); 53 | //CLOSING 54 | }else if (CAN_RxMsg.data[0]==0x89) 55 | { 56 | myCarClosing++; 57 | myCarOpening=0; 58 | //Serial.print("Closing="); 59 | //Serial.println(myCarClosing,DEC); 60 | }else 61 | { 62 | myCarOpening=0; 63 | myCarClosing=0; 64 | myfirsttime=1; 65 | //Serial.println("myCarOpening=0"); 66 | } 67 | } 68 | 69 | //Abro ventanillas, si el usuario ha estado pulsando el boton una cierta cantidad de tiempo 70 | if (myCarOpening>10) 71 | { 72 | if (myfirsttime) 73 | { 74 | CAN_TxMsg.id=0x271; //Le mando al coche como si estuviera en contacto 75 | CAN_TxMsg.header.rtr=0; 76 | CAN_TxMsg.header.length=1; 77 | CAN_TxMsg.data[0]=0x03; 78 | CAN_TxMsg.data[1]=0x00; 79 | CAN.send(&CAN_TxMsg); 80 | delay(100); 81 | myfirsttime=0; 82 | //Serial.println("Enviado msg contacto"); 83 | } 84 | 85 | CAN_TxMsg.id=0x181; 86 | CAN_TxMsg.header.rtr=0; 87 | CAN_TxMsg.header.length=3; 88 | CAN_TxMsg.data[0]=0x44; // Bajar ventanilla delantera izquierda 89 | CAN_TxMsg.data[1]=0x44; // Bajar ventanillas traseras 90 | CAN.send(&CAN_TxMsg); 91 | //Serial.println("Opening Windows"); 92 | } 93 | //Cierro ventanillas, si el usuario ha estado pulsando el boton una cierta cantidad de tiempo 94 | if (myCarClosing>10) 95 | { 96 | if (myfirsttime) 97 | { 98 | CAN_TxMsg.id=0x271; //Le mando al coche como si estuviera en contacto 99 | CAN_TxMsg.header.rtr=0; 100 | CAN_TxMsg.header.length=1; 101 | CAN_TxMsg.data[0]=0x03; 102 | CAN_TxMsg.data[1]=0x00; 103 | CAN.send(&CAN_TxMsg); 104 | delay(20); 105 | CAN.send(&CAN_TxMsg); 106 | delay(100); 107 | myfirsttime=0; 108 | //Serial.println("Enviado msg contacto"); 109 | } 110 | 111 | CAN_TxMsg.id=0x181; 112 | CAN_TxMsg.header.rtr=0; 113 | CAN_TxMsg.header.length=3; 114 | CAN_TxMsg.data[0]=0x11; // Subir ventanilla delantera izquierda 115 | CAN_TxMsg.data[1]=0x11; // Subir ventanillas traseras 116 | CAN.send(&CAN_TxMsg); 117 | //Serial.println("Closing Windows"); 118 | } 119 | 120 | 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /Loopback Mode/SECUduino_Example_Loopback_Mode.pde: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------- 2 | // SECUDUINO 3 | // http://secuduino.blogspot.com/ 4 | // By Igor Real 5 | // 16/05/2011 6 | // ---------------------------------------------- 7 | 8 | #include 9 | 10 | void setup() 11 | { 12 | // set up CAN 13 | CAN.begin(1); 14 | CAN.SetMode(LOOPBACK_MODE); 15 | //setup SERIAL 16 | Serial.begin(115200); 17 | 18 | CAN_TxMsg.id=0x351; 19 | CAN_TxMsg.header.rtr=0; 20 | CAN_TxMsg.header.length=8; 21 | CAN_TxMsg.data[0]=0x00; 22 | CAN_TxMsg.data[1]=0x00; 23 | CAN_TxMsg.data[2]=0x00; 24 | CAN_TxMsg.data[3]=0x00; 25 | CAN_TxMsg.data[4]=0x00; 26 | CAN_TxMsg.data[5]=0x00; 27 | CAN_TxMsg.data[6]=0x00; 28 | CAN_TxMsg.data[7]=0x00; 29 | } 30 | 31 | void loop() 32 | { 33 | 34 | CAN.send(&CAN_TxMsg); 35 | 36 | if (CAN.CheckNew()) 37 | { 38 | CAN_TxMsg.data[0]++; 39 | CAN.ReadFromDevice(&CAN_RxMsg); 40 | 41 | if (CAN_RxMsg.id==0x351) //SPEED 42 | { 43 | Serial.print(CAN_RxMsg.id,HEX); 44 | Serial.print(";"); 45 | Serial.print(CAN_RxMsg.data[0],HEX); 46 | Serial.print(";"); 47 | Serial.print(CAN_RxMsg.data[1],HEX); 48 | Serial.print(";"); 49 | Serial.print(CAN_RxMsg.data[2],HEX); 50 | Serial.print(";"); 51 | Serial.print(CAN_RxMsg.data[3],HEX); 52 | Serial.print(";"); 53 | Serial.print(CAN_RxMsg.data[4],HEX); 54 | Serial.print(";"); 55 | Serial.print(CAN_RxMsg.data[5],HEX); 56 | Serial.print(";"); 57 | Serial.print(CAN_RxMsg.data[6],HEX); 58 | Serial.print(";"); 59 | Serial.println(CAN_RxMsg.data[7],HEX); 60 | } 61 | 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /OBD_RPM_Example/OBD_RPM_Example.pde: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------- 2 | // SECUDUINO 3 | // OBD2 Example 4 | // http://secuduino.blogspot.com/ 5 | // ---------------------------------------------- 6 | 7 | #include 8 | 9 | long rpm; 10 | 11 | void setup() 12 | { 13 | Serial.begin(115200); 14 | Serial.println("Starting..."); 15 | 16 | CAN.begin(500); 17 | 18 | CAN_TxMsg.id=0x7DF; 19 | CAN_TxMsg.header.rtr=0; 20 | CAN_TxMsg.header.length=8; 21 | CAN_TxMsg.data[0]=0x02; 22 | CAN_TxMsg.data[1]=0x01; //MODE 23 | CAN_TxMsg.data[2]=0x0C; //PID 24 | CAN_TxMsg.data[3]=0x00; 25 | CAN_TxMsg.data[4]=0x00; 26 | CAN_TxMsg.data[5]=0x00; 27 | CAN_TxMsg.data[6]=0x00; 28 | CAN_TxMsg.data[7]=0x00; 29 | 30 | } 31 | 32 | void loop() 33 | { 34 | 35 | 36 | CAN.send(&CAN_TxMsg); 37 | 38 | delay(5); 39 | 40 | 41 | if (CAN.CheckNew()) 42 | { 43 | 44 | if ( CAN.ReadFromDevice(&CAN_RxMsg) ) 45 | { 46 | if (CAN_RxMsg.data[2]==0x0C) //PID=0x0C (rpm) 47 | { 48 | rpm = ((CAN_RxMsg.data[3]*256) + CAN_RxMsg.data[4])/4; 49 | 50 | Serial.print(millis()); 51 | Serial.print(";"); 52 | Serial.print(CAN_RxMsg.id,HEX); 53 | Serial.print(";"); 54 | Serial.print(CAN_RxMsg.data[0],HEX); 55 | Serial.print(";"); 56 | Serial.print(CAN_RxMsg.data[1],HEX); 57 | Serial.print(";"); 58 | Serial.print(CAN_RxMsg.data[2],HEX); 59 | Serial.print(";"); 60 | Serial.print(CAN_RxMsg.data[3],HEX); 61 | Serial.print(";"); 62 | Serial.print(CAN_RxMsg.data[4],HEX); 63 | Serial.print(";"); 64 | Serial.print(CAN_RxMsg.data[5],HEX); 65 | Serial.print(";"); 66 | Serial.print(CAN_RxMsg.data[6],HEX); 67 | Serial.print(";"); 68 | Serial.print(CAN_RxMsg.data[7],HEX); 69 | Serial.print(";"); 70 | Serial.print("RPM="); 71 | Serial.println(rpm,DEC); 72 | } 73 | } 74 | 75 | }else 76 | { 77 | 78 | } 79 | 80 | } 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /PID/PID_2.pde: -------------------------------------------------------------------------------- 1 | //-------------------------------------------- 2 | // MAQUETA DE CONTROL PID 3 | // VIRTUALCAMP JUL 2011 4 | // IGOR R. 5 | //-------------------------------------------- 6 | 7 | #include 8 | 9 | //CONSTANTES 10 | #define cte_kp 500.0 //300 11 | #define cte_ki 10.0 //5.0 12 | #define cte_kd 3500.0 13 | #define Margin_Int 0.9 14 | #define target1 60.0 //60 15 | #define target2 58.0 //58 16 | 17 | //Variables de control de flujo 18 | long tInit; 19 | long tSerial; 20 | 21 | //Input 22 | float Target; 23 | 24 | //Sensor 25 | float temp; 26 | 27 | //Output 28 | float dutycycle; 29 | 30 | //PID 31 | float error; 32 | float prev_error; 33 | float Proportional; 34 | float Integral; 35 | float Derivative; 36 | float Kp; 37 | float Ki; 38 | float Kd; 39 | long LastTime; 40 | long SampleTime; 41 | long timeOutInt; 42 | 43 | 44 | //Tabla guardada en memoria de programa del Arduino (FLASH) 45 | PROGMEM prog_uint16_t ntc[21][2] = { 46 | {861,0}, 47 | {778,10}, 48 | {678,20}, 49 | {570,30}, 50 | {463,40}, 51 | {366,50}, 52 | {285,60}, 53 | {219,70}, 54 | {168,80}, 55 | {128,90}, 56 | {99,100}, 57 | {77,110}, 58 | {60,120}, 59 | {47,130}, 60 | {38,140}, 61 | {30,150}, 62 | {24,160}, 63 | {20,170}, 64 | {16,180}, 65 | {14,190}, 66 | {11,200}, 67 | }; 68 | 69 | 70 | void setup() 71 | { 72 | //Empiezo comunicacion serie a 19200(maxima velocidad de StampPlot) 73 | Serial.begin(19200); 74 | delay(10); 75 | //Configuro el StampPlot (maximo, minimo, grabar en un archivo los datos, etc). 76 | config_StampPlot(); 77 | //Configuro el pin 9 como salida (PWM) 78 | pinMode(9,OUTPUT); 79 | 80 | //Capturo tiempos para el control de mi programa. 81 | tInit=millis(); 82 | LastTime=millis(); 83 | 84 | //Valor de mis constantes del control PI 85 | Kp=cte_kp; 86 | Ki=cte_ki; 87 | Kd=cte_kd; 88 | 89 | //Modificar frecuencia PWM 90 | //Setting Divisor Frequency 91 | //0x01 1 31250 92 | //0x02 8 3906.25 93 | //0x03 64 488.28125 94 | //0x04 256 122.0703125 95 | //0x05 1024 30.517578125 96 | //TCCR1B = TCCR1B & 0b11111000 | ; 97 | //Configuro el PWM a 30 kHz. 98 | TCCR1B=TCCR1B & 0b11111000 | 0x01; 99 | 100 | 101 | } 102 | 103 | void loop() 104 | { 105 | 106 | //Recojo 10 veces el dato del sensor y hago la media 107 | for (int i=0; i<10;i++) 108 | { 109 | temp+=calcTemp(analogRead(A5)); //Función que transforma mi lectura del ADC en grados usando una tabla guardad en memoria FLASH 110 | } 111 | temp/=10; 112 | 113 | // Cambio el SetPoint a target1 y target2 cada 120 segundos 114 | Target=target1; 115 | long time=(millis()-tInit)/1000; 116 | if ((time>60) && (time<120) ) 117 | { 118 | Target=target2; 119 | }else if ( time>120 ) 120 | { 121 | tInit=millis(); 122 | } 123 | 124 | //---------------------------------------------------- 125 | //CONTROL PID 126 | //Hago los calculos de manera periodica 127 | 128 | SampleTime=(millis()-LastTime); 129 | if (SampleTime>=100) 130 | { 131 | 132 | LastTime=millis(); 133 | 134 | //Calculo de error (diferencia entre SetPoint y temperatura actual 135 | prev_error=(float)error; 136 | error=(float)temp-(float)Target; 137 | 138 | Proportional=(float)Kp*(float)error; 139 | 140 | //El control integral solo entra cuando esta lo suficientemente cerca 141 | //Esto es para evitar saturar el control 142 | if ( (abs(error)<=Margin_Int)) 143 | { 144 | 145 | if (timeOutInt++ >10) //Si se cumple durante X veces el SampleTime (delay de la parte integral) 146 | { 147 | Integral+=(float)Ki*(float)error; 148 | timeOutInt=3000; //Para evitar desbordamiento del numero si esta durante mucho tiempo 149 | } 150 | }else 151 | { 152 | Integral=0; 153 | timeOutInt=0; 154 | } 155 | 156 | //Parte derivativa 157 | Derivative=(float)Kd*((float)error-(float)prev_error); 158 | //---------------------------------------------------------------- 159 | dutycycle=(int)Proportional+ (int)Integral + (int)Derivative; 160 | 161 | //Limites de la salida. PWM de Arduino 0-255 (8 bits). 162 | if (dutycycle <0) 163 | { 164 | dutycycle=0; 165 | }else if (dutycycle>255) 166 | { 167 | dutycycle=255; 168 | } 169 | 170 | //Actualizo salida 171 | analogWrite(9,(int)dutycycle); 172 | 173 | //Mando datos a Stamplot 174 | Serial.print(temp); 175 | Serial.print(13,BYTE); 176 | 177 | Serial.print("D="); 178 | Serial.print(dutycycle); 179 | Serial.print(";E="); 180 | Serial.print(error); 181 | Serial.print("; P="); 182 | Serial.print(Proportional); 183 | Serial.print("; I="); 184 | Serial.print(Integral); 185 | Serial.print("; D="); 186 | Serial.print(Derivative); 187 | Serial.print(13,BYTE); 188 | 189 | } 190 | //---------------------------------------------------- 191 | 192 | 193 | } 194 | 195 | // Funcion de conversion lectura ADC a grados mediante una tabla guardada en memoria de programa del micro 196 | // para no gastar memoria RAM. 197 | float calcTemp(uint16_t myADC) 198 | { 199 | 200 | //Recorro la tabla de valores del sensor NTC 201 | for(int i=0; i<21;i++) 202 | { 203 | //No extrapola, si es menor se queda con el primer valor de la tabla 204 | if (myADC>=pgm_read_word(&(ntc[0][0]))) 205 | { 206 | temp=pgm_read_word(&(ntc[0][1])); 207 | break; 208 | } 209 | //No extrapola, si es mayor se queda con el ultimo valor de la tabla 210 | if (myADC<=pgm_read_word(&(ntc[20][0]))) 211 | { 212 | temp=pgm_read_word(&(ntc[20][1])); 213 | break; 214 | } 215 | 216 | uint16_t actualADC=pgm_read_word(&(ntc[i][0])); 217 | 218 | if (myADC>=actualADC) 219 | { 220 | if (i>0) 221 | { 222 | uint16_t previousADC=pgm_read_word(&(ntc[i-1][0])); 223 | uint16_t previousTemp=pgm_read_word(&(ntc[i-1][1])); 224 | uint16_t actualTemp=pgm_read_word(&(ntc[i][1])); 225 | 226 | temp=( ((float)myADC - (float)previousADC) * ((float)actualTemp - (float)previousTemp) / ((float)actualADC - (float)previousADC) )+previousTemp; 227 | 228 | break; 229 | } 230 | } 231 | } 232 | 233 | return (temp); 234 | 235 | } 236 | 237 | 238 | void config_StampPlot() 239 | { 240 | 241 | //---------------------------------------------------------- 242 | //CONFIGURACION STAMP PLOT LITE 243 | //---------------------------------------------------------- 244 | //Titulo de la ventana (FORM) 245 | Serial.print("!TITL Arduino Power!"); 246 | Serial.print(13,BYTE); 247 | //Titulo de usuario (STATUS) 248 | Serial.print("!USRS Control PID"); 249 | Serial.print(13,BYTE); 250 | //Valor maximo del eje Y 251 | Serial.print("!AMAX 62"); 252 | Serial.print(13,BYTE); 253 | //Valor minimo del eje Y 254 | Serial.print("!AMIN 57"); 255 | Serial.print(13,BYTE); 256 | //Valor maximo de tiempo 257 | Serial.print("!TMAX 500"); 258 | Serial.print(13,BYTE); 259 | //Configuro el numero de puntos 260 | Serial.print("!PNTS 8000"); 261 | Serial.print(13,BYTE); 262 | //Ayadir Tiempo en la lista de mensajes 263 | Serial.print("!TSMP OFF"); 264 | Serial.print(13,BYTE); 265 | //Plot ON 266 | Serial.print("!PLOT ON"); 267 | Serial.print(13,BYTE); 268 | //Borra el valor Max y Min almacenado despues del RESET 269 | Serial.print("!CLMM"); 270 | Serial.print(13,BYTE); 271 | //Limpio la lista de mensajes 272 | Serial.print("!CLRM"); 273 | Serial.print(13,BYTE); 274 | 275 | //Borro el fichero stampdat.txt 276 | Serial.print("!DELD"); 277 | Serial.print(13,BYTE); 278 | //Borro el fichero stampmsg.txt 279 | Serial.print("!DELM"); 280 | Serial.print(13,BYTE); 281 | //Salvar datos Analogicos y digitales en stampdat.txt 282 | Serial.print("!SAVD ON"); 283 | Serial.print(13,BYTE); 284 | //Salvar Mensajes en stampmsg.txt 285 | Serial.print("stampmsg.txt"); 286 | Serial.print(13,BYTE); 287 | 288 | //RESET DEL GRAFICO PARA COMENZAR A PLOTEAR 289 | Serial.print("!RSET"); 290 | Serial.print(13,BYTE); 291 | //---------------------------------------------------------- 292 | 293 | } 294 | 295 | -------------------------------------------------------------------------------- /PID/README: -------------------------------------------------------------------------------- 1 | More info => http://real2electronics.blogspot.com/2011/07/maqueta-de-control-pid-con-arduino.html 2 | -------------------------------------------------------------------------------- /R+D/at45db161d/Atmel/AVR335_Digital_Sound_Recorder_with_AVR_and_DataFlash.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IgorReal/SECUduino/1d873ff874f276ea3889af50efd877d6c15a5803/R+D/at45db161d/Atmel/AVR335_Digital_Sound_Recorder_with_AVR_and_DataFlash.pdf -------------------------------------------------------------------------------- /R+D/at45db161d/Atmel/Code AVR335/ICCAVR228A/dataflash.h: -------------------------------------------------------------------------------- 1 | // DataFlash.h 2 | 3 | 4 | #pragma language=extended 5 | 6 | //Global status register flags 7 | 8 | #define T1_OVF 0x01 9 | #define CLEARED 0x02 10 | 11 | // DataFlash reset port pin (PB 0) 12 | #define DF_RESET 0x01 13 | 14 | // DataFlash ready/busy status port pin (PB 1) 15 | #define DF_RDY_BUSY 0x02 16 | 17 | // DataFlash boot sector write protection (PB 2) 18 | #define DF_WRITE_PROTECT 0x04 19 | 20 | // DataFlash chip select port pin (PB 4) 21 | #define DF_CHIP_SELECT 0x10 22 | 23 | // buffer 1 24 | #define BUFFER_1 0x00 25 | 26 | // buffer 2 27 | #define BUFFER_2 0x01 28 | 29 | 30 | // defines for all opcodes 31 | 32 | // buffer 1 write 33 | #define BUFFER_1_WRITE 0x84 34 | 35 | // buffer 2 write 36 | #define BUFFER_2_WRITE 0x87 37 | 38 | // buffer 1 read 39 | #define BUFFER_1_READ 0x54 40 | 41 | // buffer 2 read 42 | #define BUFFER_2_READ 0x56 43 | 44 | // buffer 1 to main memory page program with built-in erase 45 | #define B1_TO_MM_PAGE_PROG_WITH_ERASE 0x83 46 | 47 | // buffer 2 to main memory page program with built-in erase 48 | #define B2_TO_MM_PAGE_PROG_WITH_ERASE 0x86 49 | 50 | // buffer 1 to main memory page program without built-in erase 51 | #define B1_TO_MM_PAGE_PROG_WITHOUT_ERASE 0x88 52 | 53 | // buffer 2 to main memory page program without built-in erase 54 | #define B2_TO_MM_PAGE_PROG_WITHOUT_ERASE 0x89 55 | 56 | // main memory page program through buffer 1 57 | #define MM_PAGE_PROG_THROUGH_B1 0x82 58 | 59 | // main memory page program through buffer 2 60 | #define MM_PAGE_PROG_THROUGH_B2 0x85 61 | 62 | // auto page rewrite through buffer 1 63 | #define AUTO_PAGE_REWRITE_THROUGH_B1 0x58 64 | 65 | // auto page rewrite through buffer 2 66 | #define AUTO_PAGE_REWRITE_THROUGH_B2 0x59 67 | 68 | // main memory page compare to buffer 1 69 | #define MM_PAGE_TO_B1_COMP 0x60 70 | 71 | // main memory page compare to buffer 2 72 | #define MM_PAGE_TO_B2_COMP 0x61 73 | 74 | // main memory page to buffer 1 transfer 75 | #define MM_PAGE_TO_B1_XFER 0x53 76 | 77 | // main memory page to buffer 2 transfer 78 | #define MM_PAGE_TO_B2_XFER 0x55 79 | 80 | // DataFlash status register for reading density, compare status, 81 | // and ready/busy status 82 | #define STATUS_REGISTER 0x57 83 | 84 | // main memory page read 85 | #define MAIN_MEMORY_PAGE_READ 0x52 86 | 87 | // erase a 528 byte page 88 | #define PAGE_ERASE 0x81 89 | 90 | // erase 512 pages 91 | #define BLOCK_ERASE 0x50 92 | 93 | #define TRUE 0xff 94 | #define FALSE 0x00 95 | 96 | // delay values based on a 8Mhz CPU clock 97 | #define QTR_MICRO_SECOND 2 98 | #define HALF_MICROSECOND 4 99 | #define ONE_MICROSECOND 8 100 | #define TWO_MICROSECONDS 16 101 | #define THREE_MICROSECONDS 24 102 | #define FIVE_MICROSECONDS 40 103 | #define TEN_MICROSECONDS 80 104 | #define TWENTY_MICROSECONDS 160 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /R+D/at45db161d/Atmel/Code AVR335/ICCAVR228A/sound_recorder.prj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IgorReal/SECUduino/1d873ff874f276ea3889af50efd877d6c15a5803/R+D/at45db161d/Atmel/Code AVR335/ICCAVR228A/sound_recorder.prj -------------------------------------------------------------------------------- /R+D/at45db161d/Atmel/Code AVR335/ICCAVR228A/sound_system2.c: -------------------------------------------------------------------------------- 1 | /* 2 | Erase all pages if desired. 3 | Write data to buffer 1. If buffer is full, write buffer to page. 4 | Read DataFlash alternating through buffer1 and buffer2 into the data register. 5 | */ 6 | 7 | #include 8 | #include 9 | #include "dataflash.h" 10 | 11 | // prototypes 12 | void setup (void); 13 | void erasing (void); 14 | void recording (void); 15 | void write_to_flash (unsigned char ad_data); 16 | void playback (void); 17 | void next_page_to_next_buffer (unsigned char active_buffer, unsigned int page_counter); 18 | void active_buffer_to_speaker (unsigned char active_buffer); 19 | void write_SPI(unsigned char data); 20 | 21 | // global variables 22 | volatile unsigned char wait = 0; 23 | 24 | 25 | void setup(void) 26 | { 27 | DDRB = 0xBD; // SPI Port initialisation 28 | // SCK, MISO, MOSI, CS, LED, WP , RDYBSY, RST 29 | // PB7, PB6, PB5, PB4, PB3, PB2 , PB1, PB0 30 | // O I O O O O I O 31 | // 1 0 1 1 1 1 0 1 32 | 33 | PORTB = 0xFF; // all outputs high, inputs have pullups (LED is off) 34 | DDRA = 0x00; // define port A as an input 35 | PORTA = 0x00; 36 | DDRD = 0x10; // define port D as an input (D4: output) 37 | 38 | __enable_interrupt(); // enable interrupts 39 | } 40 | 41 | void write_SPI(unsigned char data) 42 | { 43 | SPDR = data; 44 | while (!(SPSR & 0x80)); // wait for data transfer to be completed 45 | } 46 | 47 | void erasing(void) 48 | { 49 | unsigned int block_counter = 0; 50 | 51 | ACSR |= CLEARED; // set signal flag that new data has to be recorded next 52 | 53 | // interrupt disabled, SPI port enabled, master mode, MSB first, SPI mode 3, Fcl/4 54 | SPCR = 0x5C; 55 | 56 | while (block_counter < 512) 57 | { 58 | PORTB &= ~DF_CHIP_SELECT; // enable DataFlash 59 | 60 | write_SPI(BLOCK_ERASE); 61 | write_SPI((char)(block_counter>>3)); 62 | write_SPI((char)(block_counter<<5)); 63 | write_SPI(0x00); 64 | 65 | PORTB |= DF_CHIP_SELECT; // disable DataFlash 66 | 67 | block_counter++; 68 | while(!(PINB & 0x02)); // wait until block is erased 69 | } 70 | SPCR = 0x00; //disable SPI 71 | } 72 | 73 | 74 | void recording(void) 75 | { 76 | unsigned char count; 77 | // interrupt disabled, SPI port enabled, master mode, MSB first, SPI mode 3, Fcl/4 78 | SPCR = 0x5C; 79 | ADMUX = 0x00; // A/D converter input pin number = 0 80 | ADCSRA = 0xD5; // single A/D conversion, fCK/32, conversion now started 81 | do 82 | { 83 | do 84 | { 85 | } while(!(ADCSRA&(1<>8)); // don't cares plus first two bits of buffer address 117 | write_SPI((char)buffer_counter); // buffer address (max. 2^8 = 256 pages) 118 | write_SPI(flash_data); // write data into SPI Data Register 119 | 120 | PORTB |= DF_CHIP_SELECT; // disable DataFlash 121 | 122 | buffer_counter++; 123 | 124 | if (buffer_counter > 528) // if buffer full write buffer into memory page 125 | { 126 | buffer_counter = 0; 127 | if (page_counter < 4096) // if memory is not full 128 | { 129 | PORTB &= ~DF_CHIP_SELECT; // enable DataFlash 130 | 131 | write_SPI(B1_TO_MM_PAGE_PROG_WITHOUT_ERASE);// write data from buffer1 to page 132 | write_SPI((char)(page_counter>>6)); 133 | write_SPI((char)(page_counter<<2)); 134 | write_SPI(0x00); // don't cares 135 | 136 | PORTB |= DF_CHIP_SELECT; // disable DataFlash 137 | page_counter++; 138 | } 139 | else 140 | { 141 | PORTB |= 0x08; // turn LED off 142 | while (!(PIND & 2)); // wait until button for recording (button 1) is released 143 | } 144 | } 145 | } 146 | 147 | 148 | void playback(void) 149 | { 150 | unsigned int page_counter = 0; 151 | unsigned char active_buffer = 1; // active buffer = buffer1 152 | 153 | TCCR1A = 0x21; // 8 bit PWM, using COM1B 154 | TCNT1 = 0x00; // set counter1 to zero 155 | TIFR = 0x04; // clear counter1 overflow flag 156 | TIMSK = 0x04; // enable counter1 overflow interrupt 157 | TCCR1B = 0x01; // counter1 clock prescale = 1 158 | OCR1B = 0x00; // set output compare register B to zero 159 | 160 | // interrupt disabled, SPI port enabled, master mode, MSB first, SPI mode 3, Fcl/4 161 | SPCR = 0x5C; 162 | 163 | next_page_to_next_buffer (active_buffer, page_counter); // read page0 to buffer1 164 | 165 | while (!(PINB & 0x02)); // wait until page0 to buffer1 transaction is finished 166 | 167 | while ((page_counter < 4095)&(!(PIND & 4))) // while button for playback (button 2) is pressed 168 | { 169 | page_counter++; // now take next page 170 | 171 | next_page_to_next_buffer (active_buffer, page_counter); 172 | active_buffer_to_speaker (active_buffer); 173 | 174 | if (active_buffer == 1) // if buffer1 is the active buffer 175 | { 176 | active_buffer++; // set buffer2 as active buffer 177 | } 178 | else // else 179 | { 180 | active_buffer--; // set buffer1 as active buffer 181 | } 182 | } 183 | TIMSK = 0x00; // disable all interrupts 184 | TCCR1B = 0x00; // stop counter1 185 | SPCR = 0x00; // disable SPI 186 | } 187 | 188 | 189 | void next_page_to_next_buffer (unsigned char active_buffer, unsigned int page_counter) 190 | { 191 | while(!(PINB & 0x02)); // wait until flash is not busy 192 | 193 | PORTB &= ~DF_CHIP_SELECT; // enable DataFlash 194 | 195 | if (active_buffer == 1) // if buffer1 is the active buffer 196 | { 197 | write_SPI(MM_PAGE_TO_B2_XFER); // transfer next page to buffer2 198 | } 199 | else // else 200 | { 201 | write_SPI(MM_PAGE_TO_B2_XFER); // transfer next page to buffer1 202 | } 203 | write_SPI((char)(page_counter >> 6)); 204 | write_SPI((char)(page_counter << 2)); 205 | write_SPI(0x00); 206 | 207 | PORTB |= DF_CHIP_SELECT; // disable DataFlash and start transaction 208 | } 209 | 210 | 211 | #pragma vector = TIMER1_OVF_vect 212 | __interrupt void out_now(void) 213 | { 214 | ACSR |= T1_OVF; // an interrupt has occured 215 | } 216 | 217 | 218 | void active_buffer_to_speaker (unsigned char active_buffer) 219 | { 220 | // until active buffer not empty read active buffer to speaker 221 | 222 | unsigned int buffer_counter = 528; 223 | 224 | PORTB &= ~DF_CHIP_SELECT; // enable DataFlash 225 | 226 | if (active_buffer == 1) // if buffer1 is the active buffer 227 | { 228 | write_SPI(BUFFER_1_READ); // read from buffer1 229 | } 230 | else // else 231 | { 232 | write_SPI(BUFFER_2_READ); // read from buffer2 233 | } 234 | write_SPI(0x00); // write don't care byte 235 | write_SPI(0x00); // write don't care byte 236 | write_SPI(0x00); // start at buffer address 0 237 | write_SPI(0x00); // write don't care byte 238 | 239 | do 240 | { 241 | write_SPI(0xFF); // write dummy value to start register shift 242 | while(!(ACSR&T1_OVF)); // wait for timer1 overflow interrupt 243 | OCR1B = SPDR; // play data from shift register 244 | ACSR &= (~T1_OVF); // clear the signal flag 245 | } while (--buffer_counter); 246 | PORTB |= DF_CHIP_SELECT; // disable DataFlash 247 | } 248 | 249 | 250 | void main(void) 251 | { 252 | setup(); 253 | 254 | for(;;) 255 | { 256 | if (!(PIND & 2)) // if button for recording (button 2) is pressed 257 | { 258 | PORTB &= 0xF7; // turn LED on 259 | recording(); 260 | } 261 | if (!(PIND & 1)) // if button for erasing (button 0) is pressed 262 | { 263 | PORTB &= 0xF7; // turn LED on 264 | erasing(); 265 | while (!(PIND & 1)); // wait until button for erasing (button 0) is released 266 | } 267 | if (!(PIND & 4)) // if button for playback (button 3) is pressed 268 | { 269 | PORTB &= 0xF7; // turn LED on 270 | playback(); 271 | while (!(PIND & 4)); // wait until button for playback (button 3) is released 272 | } 273 | PORTB |= 0x08; // turn LED off while running idle 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /R+D/at45db161d/Atmel/Code AVR335/ICCAVR320C/dataflash.h: -------------------------------------------------------------------------------- 1 | // DataFlash.h 2 | 3 | 4 | #pragma language=extended 5 | 6 | //Global status register flags 7 | 8 | #define T1_OVF 0x01 9 | #define CLEARED 0x02 10 | 11 | // DataFlash reset port pin (PB 0) 12 | #define DF_RESET 0x01 13 | 14 | // DataFlash ready/busy status port pin (PB 1) 15 | #define DF_RDY_BUSY 0x02 16 | 17 | // DataFlash boot sector write protection (PB 2) 18 | #define DF_WRITE_PROTECT 0x04 19 | 20 | // DataFlash chip select port pin (PB 4) 21 | #define DF_CHIP_SELECT 0x10 22 | 23 | // buffer 1 24 | #define BUFFER_1 0x00 25 | 26 | // buffer 2 27 | #define BUFFER_2 0x01 28 | 29 | 30 | // defines for all opcodes 31 | 32 | // buffer 1 write 33 | #define BUFFER_1_WRITE 0x84 34 | 35 | // buffer 2 write 36 | #define BUFFER_2_WRITE 0x87 37 | 38 | // buffer 1 read 39 | #define BUFFER_1_READ 0x54 40 | 41 | // buffer 2 read 42 | #define BUFFER_2_READ 0x56 43 | 44 | // buffer 1 to main memory page program with built-in erase 45 | #define B1_TO_MM_PAGE_PROG_WITH_ERASE 0x83 46 | 47 | // buffer 2 to main memory page program with built-in erase 48 | #define B2_TO_MM_PAGE_PROG_WITH_ERASE 0x86 49 | 50 | // buffer 1 to main memory page program without built-in erase 51 | #define B1_TO_MM_PAGE_PROG_WITHOUT_ERASE 0x88 52 | 53 | // buffer 2 to main memory page program without built-in erase 54 | #define B2_TO_MM_PAGE_PROG_WITHOUT_ERASE 0x89 55 | 56 | // main memory page program through buffer 1 57 | #define MM_PAGE_PROG_THROUGH_B1 0x82 58 | 59 | // main memory page program through buffer 2 60 | #define MM_PAGE_PROG_THROUGH_B2 0x85 61 | 62 | // auto page rewrite through buffer 1 63 | #define AUTO_PAGE_REWRITE_THROUGH_B1 0x58 64 | 65 | // auto page rewrite through buffer 2 66 | #define AUTO_PAGE_REWRITE_THROUGH_B2 0x59 67 | 68 | // main memory page compare to buffer 1 69 | #define MM_PAGE_TO_B1_COMP 0x60 70 | 71 | // main memory page compare to buffer 2 72 | #define MM_PAGE_TO_B2_COMP 0x61 73 | 74 | // main memory page to buffer 1 transfer 75 | #define MM_PAGE_TO_B1_XFER 0x53 76 | 77 | // main memory page to buffer 2 transfer 78 | #define MM_PAGE_TO_B2_XFER 0x55 79 | 80 | // DataFlash status register for reading density, compare status, 81 | // and ready/busy status 82 | #define STATUS_REGISTER 0x57 83 | 84 | // main memory page read 85 | #define MAIN_MEMORY_PAGE_READ 0x52 86 | 87 | // erase a 528 byte page 88 | #define PAGE_ERASE 0x81 89 | 90 | // erase 512 pages 91 | #define BLOCK_ERASE 0x50 92 | 93 | #define TRUE 0xff 94 | #define FALSE 0x00 95 | 96 | // delay values based on a 8Mhz CPU clock 97 | #define QTR_MICRO_SECOND 2 98 | #define HALF_MICROSECOND 4 99 | #define ONE_MICROSECOND 8 100 | #define TWO_MICROSECONDS 16 101 | #define THREE_MICROSECONDS 24 102 | #define FIVE_MICROSECONDS 40 103 | #define TEN_MICROSECONDS 80 104 | #define TWENTY_MICROSECONDS 160 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /R+D/at45db161d/Atmel/Code AVR335/ICCAVR320C/sound_system.ewp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1 5 | 6 | Debug 7 | 8 | AVR 9 | 10 | 1 11 | 12 | General 13 | 1 14 | 15 | 4 16 | 1 17 | 1 18 | 22 | 27 | 31 | 35 | 39 | 43 | 47 | 51 | 56 | 60 | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | 96 | 100 | 104 | 108 | 112 | 116 | 120 | 124 | 128 | 132 | 136 | 140 | 145 | 146 | 147 | 148 | ICCAVR 149 | 1 150 | 151 | 8 152 | 1 153 | 1 154 | 158 | 162 | 166 | 170 | 174 | 178 | 182 | 186 | 190 | 194 | 198 | 202 | 206 | 210 | 214 | 218 | 222 | 226 | 230 | 234 | 238 | 242 | 246 | 251 | 255 | 260 | 265 | 270 | 274 | 278 | 282 | 286 | 290 | 294 | 298 | 302 | 306 | 310 | 314 | 318 | 322 | 326 | 330 | 334 | 338 | 342 | 346 | 350 | 355 | 359 | 363 | 364 | 365 | 366 | AAVR 367 | 1 368 | 369 | 7 370 | 1 371 | 1 372 | 376 | 380 | 384 | 388 | 392 | 396 | 400 | 404 | 408 | 412 | 416 | 421 | 425 | 429 | 433 | 437 | 441 | 445 | 449 | 453 | 457 | 461 | 465 | 469 | 473 | 477 | 481 | 485 | 489 | 493 | 497 | 501 | 505 | 509 | 513 | 517 | 521 | 525 | 529 | 533 | 537 | 541 | 545 | 549 | 553 | 554 | 555 | 556 | XLINK 557 | 1 558 | 559 | 7 560 | 1 561 | 1 562 | 566 | 570 | 574 | 579 | 584 | 588 | 592 | 596 | 600 | 604 | 608 | 612 | 616 | 620 | 624 | 628 | 632 | 636 | 640 | 644 | 648 | 652 | 656 | 661 | 665 | 669 | 674 | 678 | 682 | 686 | 690 | 694 | 699 | 704 | 708 | 712 | 716 | 720 | 724 | 728 | 732 | 736 | 737 | 738 | 739 | XAR 740 | 1 741 | 742 | 0 743 | 1 744 | 1 745 | 749 | 753 | 757 | 758 | 759 | 760 | CUSTOM 761 | 3 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | Release 770 | 771 | AVR 772 | 773 | 0 774 | 775 | General 776 | 1 777 | 778 | 4 779 | 1 780 | 0 781 | 785 | 790 | 794 | 798 | 802 | 806 | 810 | 814 | 819 | 823 | 827 | 831 | 835 | 839 | 843 | 847 | 851 | 855 | 859 | 863 | 867 | 871 | 875 | 879 | 883 | 887 | 891 | 895 | 899 | 903 | 908 | 909 | 910 | 911 | ICCAVR 912 | 1 913 | 914 | 8 915 | 1 916 | 0 917 | 921 | 925 | 929 | 933 | 937 | 941 | 945 | 949 | 953 | 957 | 961 | 965 | 969 | 973 | 977 | 981 | 985 | 989 | 993 | 997 | 1001 | 1005 | 1009 | 1014 | 1018 | 1023 | 1028 | 1033 | 1037 | 1041 | 1045 | 1049 | 1053 | 1057 | 1061 | 1065 | 1069 | 1073 | 1077 | 1081 | 1085 | 1089 | 1093 | 1097 | 1101 | 1105 | 1109 | 1113 | 1117 | 1121 | 1125 | 1126 | 1127 | 1128 | AAVR 1129 | 1 1130 | 1131 | 7 1132 | 1 1133 | 0 1134 | 1138 | 1142 | 1146 | 1150 | 1154 | 1158 | 1162 | 1166 | 1170 | 1174 | 1178 | 1183 | 1187 | 1191 | 1195 | 1199 | 1203 | 1207 | 1211 | 1215 | 1219 | 1223 | 1227 | 1231 | 1235 | 1239 | 1243 | 1247 | 1251 | 1255 | 1259 | 1263 | 1267 | 1271 | 1275 | 1279 | 1283 | 1287 | 1291 | 1295 | 1299 | 1303 | 1307 | 1311 | 1315 | 1316 | 1317 | 1318 | XLINK 1319 | 1 1320 | 1321 | 7 1322 | 1 1323 | 0 1324 | 1328 | 1332 | 1336 | 1341 | 1346 | 1350 | 1354 | 1358 | 1362 | 1366 | 1370 | 1374 | 1378 | 1382 | 1386 | 1390 | 1394 | 1398 | 1402 | 1406 | 1410 | 1414 | 1418 | 1423 | 1427 | 1431 | 1436 | 1440 | 1444 | 1448 | 1452 | 1456 | 1461 | 1466 | 1470 | 1474 | 1478 | 1482 | 1486 | 1490 | 1494 | 1498 | 1499 | 1500 | 1501 | XAR 1502 | 1 1503 | 1504 | 0 1505 | 1 1506 | 0 1507 | 1511 | 1515 | 1519 | 1520 | 1521 | 1522 | CUSTOM 1523 | 3 1524 | 1525 | 1526 | 1527 | 1528 | 1529 | 1530 | 1531 | $PROJ_DIR$\sound_system2.c 1532 | 1533 | 1534 | 1535 | 1536 | -------------------------------------------------------------------------------- /R+D/at45db161d/Atmel/Code AVR335/ICCAVR320C/sound_system.eww: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $WS_DIR$\sound_system.ewp 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /R+D/at45db161d/Atmel/Code AVR335/ICCAVR320C/sound_system2.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * 3 | * Atmel Corporation 4 | * 5 | * File : sound_system2.c 6 | * Compiler : IAR EWAAVR 3.20C 7 | * Revision : $Revision: 1.4 $ 8 | * Date : $Date: Monday, November 15, 2004 12:53:58 UTC $ 9 | * 10 | * Support mail : avr@atmel.com 11 | * 12 | * Supported devices : ATmega8535 13 | * 14 | * AppNote : AVR335 Digital Sound Recorder. 15 | * 16 | * 17 | ****************************************************************************/ 18 | 19 | 20 | #include 21 | #include 22 | #include "dataflash.h" 23 | 24 | // prototypes 25 | void setup (void); 26 | void erasing (void); 27 | void recording (void); 28 | void write_to_flash (unsigned char ad_data); 29 | void playback (void); 30 | void next_page_to_next_buffer (unsigned char active_buffer, unsigned int page_counter); 31 | void active_buffer_to_speaker (unsigned char active_buffer); 32 | void write_SPI(unsigned char data); 33 | 34 | // global variables 35 | volatile unsigned char wait = 0; 36 | 37 | 38 | void setup(void) 39 | { 40 | DDRB = 0xBD; // SPI Port initialisation 41 | // SCK, MISO, MOSI, CS, LED, WP , RDYBSY, RST 42 | // PB7, PB6, PB5, PB4, PB3, PB2 , PB1, PB0 43 | // O I O O O O I O 44 | // 1 0 1 1 1 1 0 1 45 | 46 | PORTB = 0xFF; // all outputs high, inputs have pullups (LED is off) 47 | DDRA = 0x00; // define port A as an input 48 | PORTA = 0x00; 49 | DDRD = 0x10; // define port D as an input (D4: output) 50 | 51 | __enable_interrupt(); // enable interrupts 52 | } 53 | 54 | void write_SPI(unsigned char data) 55 | { 56 | SPDR = data; 57 | while (!(SPSR & 0x80)); // wait for data transfer to be completed 58 | } 59 | 60 | void erasing(void) 61 | { 62 | unsigned int block_counter = 0; 63 | 64 | ACSR |= CLEARED; // set signal flag that new data has to be recorded next 65 | 66 | // interrupt disabled, SPI port enabled, master mode, MSB first, SPI mode 3, Fcl/4 67 | SPCR = 0x5C; 68 | 69 | while (block_counter < 512) 70 | { 71 | PORTB &= ~DF_CHIP_SELECT; // enable DataFlash 72 | 73 | write_SPI(BLOCK_ERASE); 74 | write_SPI((char)(block_counter>>3)); 75 | write_SPI((char)(block_counter<<5)); 76 | write_SPI(0x00); 77 | 78 | PORTB |= DF_CHIP_SELECT; // disable DataFlash 79 | 80 | block_counter++; 81 | while(!(PINB & 0x02)); // wait until block is erased 82 | } 83 | SPCR = 0x00; //disable SPI 84 | } 85 | 86 | 87 | void recording(void) 88 | { 89 | unsigned char count; 90 | // interrupt disabled, SPI port enabled, master mode, MSB first, SPI mode 3, Fcl/4 91 | SPCR = 0x5C; 92 | ADMUX = 0x00; // A/D converter input pin number = 0 93 | ADCSRA = 0xD5; // single A/D conversion, fCK/32, conversion now started 94 | do 95 | { 96 | do 97 | { 98 | } while(!(ADCSRA&(1<>8)); // don't cares plus first two bits of buffer address 130 | write_SPI((char)buffer_counter); // buffer address (max. 2^8 = 256 pages) 131 | write_SPI(flash_data); // write data into SPI Data Register 132 | 133 | PORTB |= DF_CHIP_SELECT; // disable DataFlash 134 | 135 | buffer_counter++; 136 | 137 | if (buffer_counter > 528) // if buffer full write buffer into memory page 138 | { 139 | buffer_counter = 0; 140 | if (page_counter < 4096) // if memory is not full 141 | { 142 | PORTB &= ~DF_CHIP_SELECT; // enable DataFlash 143 | 144 | write_SPI(B1_TO_MM_PAGE_PROG_WITHOUT_ERASE);// write data from buffer1 to page 145 | write_SPI((char)(page_counter>>6)); 146 | write_SPI((char)(page_counter<<2)); 147 | write_SPI(0x00); // don't cares 148 | 149 | PORTB |= DF_CHIP_SELECT; // disable DataFlash 150 | page_counter++; 151 | } 152 | else 153 | { 154 | PORTB |= 0x08; // turn LED off 155 | while (!(PIND & 2)); // wait until button for recording (button 1) is released 156 | } 157 | } 158 | } 159 | 160 | 161 | void playback(void) 162 | { 163 | unsigned int page_counter = 0; 164 | unsigned char active_buffer = 1; // active buffer = buffer1 165 | 166 | TCCR1A = 0x21; // 8 bit PWM, using COM1B 167 | TCNT1 = 0x00; // set counter1 to zero 168 | TIFR = 0x04; // clear counter1 overflow flag 169 | TIMSK = 0x04; // enable counter1 overflow interrupt 170 | TCCR1B = 0x01; // counter1 clock prescale = 1 171 | OCR1B = 0x00; // set output compare register B to zero 172 | 173 | // interrupt disabled, SPI port enabled, master mode, MSB first, SPI mode 3, Fcl/4 174 | SPCR = 0x5C; 175 | 176 | next_page_to_next_buffer (active_buffer, page_counter); // read page0 to buffer1 177 | 178 | while (!(PINB & 0x02)); // wait until page0 to buffer1 transaction is finished 179 | 180 | while ((page_counter < 4095)&(!(PIND & 4))) // while button for playback (button 2) is pressed 181 | { 182 | page_counter++; // now take next page 183 | 184 | next_page_to_next_buffer (active_buffer, page_counter); 185 | active_buffer_to_speaker (active_buffer); 186 | 187 | if (active_buffer == 1) // if buffer1 is the active buffer 188 | { 189 | active_buffer++; // set buffer2 as active buffer 190 | } 191 | else // else 192 | { 193 | active_buffer--; // set buffer1 as active buffer 194 | } 195 | } 196 | TIMSK = 0x00; // disable all interrupts 197 | TCCR1B = 0x00; // stop counter1 198 | SPCR = 0x00; // disable SPI 199 | } 200 | 201 | 202 | void next_page_to_next_buffer (unsigned char active_buffer, unsigned int page_counter) 203 | { 204 | while(!(PINB & 0x02)); // wait until flash is not busy 205 | 206 | PORTB &= ~DF_CHIP_SELECT; // enable DataFlash 207 | 208 | if (active_buffer == 1) // if buffer1 is the active buffer 209 | { 210 | write_SPI(MM_PAGE_TO_B2_XFER); // transfer next page to buffer2 211 | } 212 | else // else 213 | { 214 | write_SPI(MM_PAGE_TO_B2_XFER); // transfer next page to buffer1 215 | } 216 | write_SPI((char)(page_counter >> 6)); 217 | write_SPI((char)(page_counter << 2)); 218 | write_SPI(0x00); 219 | 220 | PORTB |= DF_CHIP_SELECT; // disable DataFlash and start transaction 221 | } 222 | 223 | 224 | #pragma vector = TIMER1_OVF_vect 225 | __interrupt void out_now(void) 226 | { 227 | ACSR |= T1_OVF; // an interrupt has occured 228 | } 229 | 230 | 231 | void active_buffer_to_speaker (unsigned char active_buffer) 232 | { 233 | // until active buffer not empty read active buffer to speaker 234 | 235 | unsigned int buffer_counter = 528; 236 | 237 | PORTB &= ~DF_CHIP_SELECT; // enable DataFlash 238 | 239 | if (active_buffer == 1) // if buffer1 is the active buffer 240 | { 241 | write_SPI(BUFFER_1_READ); // read from buffer1 242 | } 243 | else // else 244 | { 245 | write_SPI(BUFFER_2_READ); // read from buffer2 246 | } 247 | write_SPI(0x00); // write don't care byte 248 | write_SPI(0x00); // write don't care byte 249 | write_SPI(0x00); // start at buffer address 0 250 | write_SPI(0x00); // write don't care byte 251 | 252 | do 253 | { 254 | write_SPI(0xFF); // write dummy value to start register shift 255 | while(!(ACSR&T1_OVF)); // wait for timer1 overflow interrupt 256 | OCR1B = SPDR; // play data from shift register 257 | ACSR &= (~T1_OVF); // clear the signal flag 258 | } while (--buffer_counter); 259 | PORTB |= DF_CHIP_SELECT; // disable DataFlash 260 | } 261 | 262 | 263 | void main(void) 264 | { 265 | setup(); 266 | 267 | for(;;) 268 | { 269 | if (!(PIND & 2)) // if button for recording (button 2) is pressed 270 | { 271 | PORTB &= 0xF7; // turn LED on 272 | recording(); 273 | } 274 | if (!(PIND & 1)) // if button for erasing (button 0) is pressed 275 | { 276 | PORTB &= 0xF7; // turn LED on 277 | erasing(); 278 | while (!(PIND & 1)); // wait until button for erasing (button 0) is released 279 | } 280 | if (!(PIND & 4)) // if button for playback (button 3) is pressed 281 | { 282 | PORTB &= 0xF7; // turn LED on 283 | playback(); 284 | while (!(PIND & 4)); // wait until button for playback (button 3) is released 285 | } 286 | PORTB |= 0x08; // turn LED off while running idle 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /R+D/at45db161d/README: -------------------------------------------------------------------------------- 1 | Original from: 2 | http://blockos.org/releases/at45db161d/doc/ 3 | https://github.com/BlockoS/arduino-dataflash/ 4 | 5 | -------------------------------------------------------------------------------- /R+D/at45db161d/at45db161d.cpp: -------------------------------------------------------------------------------- 1 | #include "at45db161d.h" 2 | 3 | /** CTOR **/ 4 | ATD45DB161D::ATD45DB161D() 5 | {} 6 | /** DTOR **/ 7 | ATD45DB161D::~ATD45DB161D() 8 | {} 9 | 10 | /** Setup SPI and pinout **/ 11 | void ATD45DB161D::Init() 12 | { 13 | uint8_t clr; 14 | 15 | /* Initialize pinout */ 16 | pinMode(DATAOUT, OUTPUT); 17 | pinMode(DATAIN, INPUT); 18 | pinMode(SPICLOCK, OUTPUT); 19 | pinMode(SLAVESELECT, OUTPUT); 20 | pinMode(DATAIN, INPUT); 21 | 22 | /* Disable device */ 23 | DF_CS_inactive; 24 | 25 | // activamos el SPI de Arduino como Master y Fosc/2=8 MHz 26 | SPCR = (1<manufacturer = spi_transfer(0xff); 73 | /* Device ID (part 1) */ 74 | id->device[0] = spi_transfer(0xff); 75 | /* Device ID (part 2) */ 76 | id->device[1] = spi_transfer(0xff); 77 | /* Extended Device Information String Length */ 78 | id->extendedInfoLength = spi_transfer(0xff); 79 | 80 | DF_CS_inactive; 81 | 82 | } 83 | 84 | /** 85 | * Main Memory Page Read. 86 | * A main memory page read allows the user to read data directly from 87 | * any one of the 4096 pages in the main memory, bypassing both of the 88 | * data buffers and leaving the contents of the buffers unchanged. 89 | * 90 | * @param page Page of the main memory to read 91 | * @param offset Starting byte address within the page 92 | **/ 93 | void ATD45DB161D::ReadMainMemoryPage(uint16_t page, uint16_t offset) 94 | { 95 | DF_CS_inactive; /* Make sure to toggle CS signal in order */ 96 | DF_CS_active; /* to reset Dataflash command decoder */ 97 | 98 | /* Send opcode */ 99 | spi_transfer(AT45DB161D_PAGE_READ); 100 | 101 | /* Address (page | offset) */ 102 | spi_transfer((uint8_t)(page >> 6)); 103 | spi_transfer((uint8_t)((page << 2) | (offset >> 8))); 104 | spi_transfer((uint8_t)(offset & 0xff)); 105 | 106 | /* 4 "don't care" bytes */ 107 | spi_transfer(0x00); 108 | spi_transfer(0x00); 109 | spi_transfer(0x00); 110 | spi_transfer(0x00); 111 | } 112 | 113 | /** 114 | * Continuous Array Read. 115 | * Sequentially read a continuous stream of data. 116 | * @param page Page of the main memory where the sequential read will start 117 | * @param offset Starting byte address within the page 118 | * @param low If true the read operation will be performed in low speed mode (and in high speed mode if it's false). 119 | * @note The legacy mode is not currently supported 120 | **/ 121 | void ATD45DB161D::ContinuousArrayRead(uint16_t page, uint16_t offset, uint8_t low) 122 | { 123 | DF_CS_inactive; /* Make sure to toggle CS signal in order */ 124 | DF_CS_active; /* to reset Dataflash command decoder */ 125 | 126 | /* Send opcode */ 127 | spi_transfer( low ? AT45DB161D_CONTINUOUS_READ_LOW_FREQ : 128 | AT45DB161D_CONTINUOUS_READ_HIGH_FREQ ); 129 | 130 | /* Address (page | offset) */ 131 | spi_transfer((uint8_t)(page >> 6)); 132 | spi_transfer((uint8_t)((page << 2) | (offset >> 8))); 133 | spi_transfer((uint8_t)(offset & 0xff)); 134 | } 135 | 136 | 137 | /** 138 | * Read the content of one of the SRAM data buffers (in low or high speed mode). 139 | * @param bufferNum Buffer to read (1 or 2) 140 | * @param offset Starting byte within the buffer 141 | * @param low If true the read operation will be performed in low speed mode (and in high speed mode if it's false). 142 | **/ 143 | void ATD45DB161D::BufferRead(uint8_t bufferNum, uint16_t offset, uint8_t low) 144 | { 145 | DF_CS_inactive; /* Make sure to toggle CS signal in order */ 146 | DF_CS_active; /* to reset Dataflash command decoder */ 147 | 148 | /* Send opcode */ 149 | if(bufferNum == 1) 150 | { 151 | spi_transfer(low ? AT45DB161D_BUFFER_1_READ_LOW_FREQ : 152 | AT45DB161D_BUFFER_1_READ); 153 | } 154 | else 155 | { 156 | spi_transfer(low ? AT45DB161D_BUFFER_2_READ_LOW_FREQ : 157 | AT45DB161D_BUFFER_2_READ); 158 | 159 | } 160 | 161 | /* 14 "Don't care" bits */ 162 | spi_transfer(0x00); 163 | /* Rest of the "don't care" bits + bits 8,9 of the offset */ 164 | spi_transfer((uint8_t)(offset >> 8)); 165 | /* bits 7-0 of the offset */ 166 | spi_transfer((uint8_t)(offset & 0xff)); 167 | } 168 | 169 | /** 170 | * Write data to one of the SRAM data buffers. Any further call to 171 | * spi_tranfer will return bytes contained in the data buffer until 172 | * a low-to-high transition is detected on the CS pin. If the end of 173 | * the data buffer is reached, the device will wrap around back to the 174 | * beginning of the buffer. 175 | * @param bufferNum Buffer to read (1 or 2) 176 | * @param offset Starting byte within the buffer 177 | **/ 178 | void ATD45DB161D::BufferWrite(uint8_t bufferNum, uint16_t offset) 179 | { 180 | DF_CS_inactive; /* Make sure to toggle CS signal in order */ 181 | DF_CS_active; /* to reset Dataflash command decoder */ 182 | 183 | spi_transfer( (bufferNum == 1) ? AT45DB161D_BUFFER_1_WRITE : 184 | AT45DB161D_BUFFER_2_WRITE); 185 | 186 | /* 14 "Don't care" bits */ 187 | spi_transfer(0x00); 188 | /* Rest of the "don't care" bits + bits 8,9 of the offset */ 189 | spi_transfer((uint8_t)(offset >> 8)); 190 | /* bits 7-0 of the offset */ 191 | spi_transfer((uint8_t)(offset & 0xff)); 192 | } 193 | 194 | /** 195 | * Transfer data from buffer 1 or 2 to main memory page. 196 | * @param bufferNum Buffer to use (1 or 2) 197 | * @param page Page where the content of the buffer will transfered 198 | * @param erase If set the page will be first erased before the buffer transfer. 199 | * @note If erase is equal to zero, the page must have been previously erased using one of the erase command (Page or Block Erase). 200 | **/ 201 | void ATD45DB161D::BufferToPage(uint8_t bufferNum, uint16_t page, uint8_t erase) 202 | { 203 | DF_CS_inactive; /* Make sure to toggle CS signal in order */ 204 | DF_CS_active; /* to reset Dataflash command decoder */ 205 | 206 | /* Opcode */ 207 | if(erase) 208 | { 209 | spi_transfer( (bufferNum == 1) ? AT45DB161D_BUFFER_1_TO_PAGE_WITH_ERASE : 210 | AT45DB161D_BUFFER_2_TO_PAGE_WITH_ERASE); 211 | } 212 | else 213 | { 214 | spi_transfer( (bufferNum == 1) ? AT45DB161D_BUFFER_1_TO_PAGE_WITHOUT_ERASE : 215 | AT45DB161D_BUFFER_2_TO_PAGE_WITHOUT_ERASE); 216 | } 217 | 218 | /* 219 | * 3 address bytes consist of : 220 | * - 2 don’t care bits 221 | * - 12 page address bits (PA11 - PA0) that specify the page in 222 | * the main memory to be written 223 | * - 10 don’t care bits 224 | */ 225 | spi_transfer((uint8_t)(page >> 6)); 226 | spi_transfer((uint8_t)(page << 2)); 227 | spi_transfer(0x00); 228 | 229 | DF_CS_inactive; /* Start transfer */ 230 | //DF_CS_active; /* If erase was set, the page will first be erased */ 231 | 232 | /* Wait for the end of the transfer */ 233 | while(!(ReadStatusRegister() & READY_BUSY)) 234 | {} 235 | 236 | 237 | } 238 | 239 | /** 240 | * Transfer a page of data from main memory to buffer 1 or 2. 241 | * @param page Main memory page to transfer 242 | * @param buffer Buffer (1 or 2) where the data will be written 243 | **/ 244 | void ATD45DB161D::PageToBuffer(uint16_t page, uint8_t bufferNum) 245 | { 246 | DF_CS_inactive; /* Make sure to toggle CS signal in order */ 247 | DF_CS_active; /* to reset Dataflash command decoder */ 248 | 249 | /* Send opcode */ 250 | spi_transfer((bufferNum == 1) ? AT45DB161D_TRANSFER_PAGE_TO_BUFFER_1 : 251 | AT45DB161D_TRANSFER_PAGE_TO_BUFFER_2); 252 | 253 | /* 254 | * 3 address bytes consist of : 255 | * - 2 don’t care bits 256 | * - 12 page address bits (PA11 - PA0) that specify the page in 257 | * the main memory to be written 258 | * - 10 don’t care bits 259 | */ 260 | spi_transfer((uint8_t)(page >> 6)); 261 | spi_transfer((uint8_t)(page << 2)); 262 | spi_transfer(0x00); 263 | 264 | DF_CS_inactive; /* Start page transfer */ 265 | //DF_CS_active; 266 | 267 | /* Wait for the end of the transfer */ 268 | while(!(ReadStatusRegister() & READY_BUSY)) 269 | {} 270 | 271 | 272 | } 273 | 274 | /** 275 | * Erase a page in the main memory array. 276 | * @param page Page to erase 277 | **/ 278 | void ATD45DB161D::PageErase(uint16_t page) 279 | { 280 | DF_CS_inactive; /* Make sure to toggle CS signal in order */ 281 | DF_CS_active; /* to reset Dataflash command decoder */ 282 | 283 | /* Send opcode */ 284 | spi_transfer(AT45DB161D_PAGE_ERASE); 285 | 286 | /* 287 | * 3 address bytes consist of : 288 | * - 2 don’t care bits 289 | * - 12 page address bits (PA11 - PA0) that specify the page in 290 | * the main memory to be written 291 | * - 10 don’t care bits 292 | */ 293 | spi_transfer((uint8_t)(page >> 6)); 294 | spi_transfer((uint8_t)(page << 2)); 295 | spi_transfer(0x00); 296 | 297 | DF_CS_inactive; /* Start block erase */ 298 | //DF_CS_active; 299 | 300 | /* Wait for the end of the block erase operation */ 301 | while(!(ReadStatusRegister() & READY_BUSY)) 302 | {} 303 | } 304 | 305 | /** 306 | * Erase a block of eight pages at one time. 307 | * @param block Index of the block to erase 308 | **/ 309 | void ATD45DB161D::BlockErase(uint16_t block) 310 | { 311 | DF_CS_inactive; /* Make sure to toggle CS signal in order */ 312 | DF_CS_active; /* to reset Dataflash command decoder */ 313 | 314 | /* Send opcode */ 315 | spi_transfer(AT45DB161D_BLOCK_ERASE); 316 | 317 | /* 318 | * 3 address bytes consist of : 319 | * - 2 don’t care bits 320 | * - 9 block address bits (PA11 - PA3) 321 | * - 13 don’t care bits 322 | */ 323 | spi_transfer((uint8_t)(block >> 3)); 324 | spi_transfer((uint8_t)(block << 5)); 325 | spi_transfer(0x00); 326 | 327 | DF_CS_inactive; /* Start block erase */ 328 | //DF_CS_active; 329 | 330 | /* Wait for the end of the block erase operation */ 331 | while(!(ReadStatusRegister() & READY_BUSY)) 332 | {} 333 | } 334 | 335 | /** 336 | * Erase a sector in main memory. There are 16 sector on the 337 | * at45db161d and only one can be erased at one time. 338 | * @param sector Sector to erase (1-15) 339 | **/ 340 | void ATD45DB161D::SectoreErase(uint8_t sector) 341 | { 342 | DF_CS_inactive; /* Make sure to toggle CS signal in order */ 343 | DF_CS_active; /* to reset Dataflash command decoder */ 344 | 345 | /* Send opcode */ 346 | spi_transfer(AT45DB161D_SECTOR_ERASE); 347 | 348 | /* 349 | * 3 address bytes consist of : 350 | */ 351 | if((sector == 0x0a) || (sector == 0x0b)) 352 | { 353 | /* 354 | * - 11 don’t care bits 355 | * - 356 | * - 12 don’t care bits 357 | */ 358 | spi_transfer(0x00); 359 | spi_transfer(((sector & 0x01) << 4)); 360 | spi_transfer(0x00); 361 | } 362 | else 363 | { 364 | /* 365 | * - 2 don't care bits 366 | * - 4 sector number bits 367 | * - 18 don't care bits 368 | */ 369 | spi_transfer(sector << 1); 370 | spi_transfer(0x00); 371 | spi_transfer(0x00); 372 | } 373 | 374 | DF_CS_inactive; /* Start block erase */ 375 | //DF_CS_active; 376 | 377 | /* Wait for the end of the block erase operation */ 378 | while(!(ReadStatusRegister() & READY_BUSY)) 379 | {} 380 | } 381 | 382 | /** 383 | * Erase the entire chip memory. Sectors proteced or locked down will 384 | * not be erased. 385 | **/ 386 | void ATD45DB161D::ChipErase() 387 | { 388 | DF_CS_inactive; /* Make sure to toggle CS signal in order */ 389 | DF_CS_active; /* to reset Dataflash command decoder */ 390 | 391 | /* Send chip erase sequence */ 392 | spi_transfer(AT45DB161D_CHIP_ERASE_0); 393 | spi_transfer(AT45DB161D_CHIP_ERASE_1); 394 | spi_transfer(AT45DB161D_CHIP_ERASE_2); 395 | spi_transfer(AT45DB161D_CHIP_ERASE_3); 396 | 397 | DF_CS_inactive; /* Start chip erase */ 398 | //DF_CS_active; 399 | 400 | /* Wait for the end of the chip erase operation */ 401 | while(!(ReadStatusRegister() & READY_BUSY)) 402 | {} 403 | } 404 | 405 | /** 406 | * This a combination of Buffer Write and Buffer to Page with 407 | * Built-in Erase. 408 | * @note You must call EndAndWait in order to start transfering data from buffer to page 409 | * @param page Page where the content of the buffer will transfered 410 | * @param offset Starting byte address within the buffer 411 | * @param bufferNum Buffer to use (1 or 2) 412 | * @warning UNTESTED 413 | **/ 414 | void ATD45DB161D::BeginPageWriteThroughBuffer(uint16_t page, uint16_t offset, uint8_t bufferNum) 415 | { 416 | DF_CS_inactive; /* Make sure to toggle CS signal in order */ 417 | DF_CS_active; /* to reset Dataflash command decoder */ 418 | 419 | /* Send opcode */ 420 | spi_transfer((bufferNum == 1) ? AT45DB161D_PAGE_THROUGH_BUFFER_1 : 421 | AT45DB161D_PAGE_THROUGH_BUFFER_2); 422 | 423 | /* Address */ 424 | spi_transfer((uint8_t)(page >> 6)); 425 | spi_transfer((uint8_t)((page << 2) | (offset >> 8))); 426 | spi_transfer((uint8_t)offset); 427 | } 428 | 429 | /** 430 | * Perform a low-to-high transition on the CS pin and then poll 431 | * the status register to check if the dataflash is busy. 432 | **/ 433 | void ATD45DB161D::EndAndWait() 434 | { 435 | DF_CS_inactive; /* End current operation */ 436 | //DF_CS_active; // Some internal operation may occur 437 | // (buffer to page transfer, page erase, etc... ) 438 | 439 | /* Wait for the chip to be ready */ 440 | while(!(ReadStatusRegister() & READY_BUSY)) 441 | {} 442 | } 443 | 444 | /** 445 | * Compare a page of data in main memory to the data in buffer 1 or 2. 446 | * @param page Page to test 447 | * @param bufferNum Buffer number 448 | * @return 449 | * - 1 if the page and the buffer contains the same data 450 | * - 0 else 451 | * @warning UNTESTED 452 | **/ 453 | int8_t ATD45DB161D::ComparePageToBuffer(uint16_t page, uint8_t bufferNum) 454 | { 455 | uint8_t status; 456 | 457 | DF_CS_inactive; /* Make sure to toggle CS signal in order */ 458 | DF_CS_active; /* to reset Dataflash command decoder */ 459 | 460 | /* Send opcode */ 461 | spi_transfer((bufferNum == 1) ? AT45DB161D_COMPARE_PAGE_TO_BUFFER_1 : 462 | AT45DB161D_COMPARE_PAGE_TO_BUFFER_2); 463 | 464 | /* Page address */ 465 | spi_transfer((uint8_t)(page >> 6)); 466 | spi_transfer((uint8_t)(page << 2)); 467 | spi_transfer(0x00); 468 | 469 | DF_CS_inactive; /* Start comparaison */ 470 | //DF_CS_active; 471 | 472 | /* Wait for the end of the comparaison and get the result */ 473 | while(!((status = ReadStatusRegister()) & READY_BUSY)) 474 | {} 475 | 476 | return ((status & COMPARE) == COMPARE); 477 | } 478 | 479 | /** 480 | * Put the device into the lowest power consumption mode. 481 | * Once the device has entered the Deep Power-down mode, all 482 | * instructions are ignored except the Resume from Deep 483 | * Power-down command. 484 | * @warning UNTESTED 485 | **/ 486 | void ATD45DB161D::DeepPowerDown() 487 | { 488 | DF_CS_inactive; /* Make sure to toggle CS signal in order */ 489 | DF_CS_active; /* to reset Dataflash command decoder */ 490 | 491 | /* Send opcode */ 492 | spi_transfer(AT45DB161D_DEEP_POWER_DOWN); 493 | 494 | /* Enter Deep Power-Down mode */ 495 | DF_CS_inactive; 496 | 497 | /* Safety delay */ 498 | delay(100); 499 | } 500 | 501 | /** 502 | * Takes the device out of Deep Power-down mode. 503 | **/ 504 | void ATD45DB161D::ResumeFromDeepPowerDown() 505 | { 506 | DF_CS_inactive; /* Make sure to toggle CS signal in order */ 507 | DF_CS_active; /* to reset Dataflash command decoder */ 508 | 509 | /* Send opcode */ 510 | spi_transfer(AT45DB161D_RESUME_FROM_DEEP_POWER_DOWN); 511 | 512 | /* Resume device */ 513 | DF_CS_inactive; 514 | 515 | /* The CS pin must stay high during t_RDPD microseconds before the device 516 | * can receive any commands. 517 | * On the at45db161D t_RDPD = 35 microseconds. But we will wait 100 518 | * (just to be sure). */ 519 | delay(100); 520 | } 521 | 522 | /** **/ 523 | -------------------------------------------------------------------------------- /R+D/at45db161d/at45db161d.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file at45db161d.h 3 | * @brief AT45DB161D module 4 | **/ 5 | #ifndef AT45DB161D_H 6 | #define AT45DB161D_H 7 | 8 | extern "C" { 9 | #include 10 | #include 11 | }; 12 | 13 | #if defined(ARDUINO) && ARDUINO >= 100 14 | #include "Arduino.h" 15 | #else 16 | #include "WProgram.h" 17 | #endif 18 | 19 | #include "at45db161d_commands.h" 20 | 21 | /** 22 | * @defgroup AT45DB161D AT45DB161D module 23 | * @{ 24 | **/ 25 | 26 | /** 27 | * @defgroup SPI SPI pinout and transfert function 28 | * @{ 29 | **/ 30 | #ifndef SPI 31 | /** 32 | * @defgroup SPI_Pinout SPI pinout 33 | * @{ 34 | **/ 35 | /** Serial input (SI) **/ 36 | #define DATAOUT 11 37 | /** Serial output (SO) **/ 38 | #define DATAIN 12 39 | /** Serial clock (SCK) **/ 40 | #define SPICLOCK 13 41 | /** Chip select (CS) **/ 42 | #define SLAVESELECT 3 43 | /** Reset (Reset) **/ 44 | #define RESET 8 45 | /** Write protect (WP) **/ 46 | #define WP 7 47 | /** 48 | * @} 49 | **/ 50 | 51 | /** 52 | * @fn inline uint8_t spi_transfer(uint8_t data) 53 | * @brief Transfer a byte via spi 54 | * @param data Data to transfer via SPI 55 | * @return The content of the SPI data register (SPDR) 56 | **/ 57 | inline uint8_t spi_transfer(uint8_t data) 58 | { 59 | SPDR = data; 60 | while(!(SPSR & (1 << SPIF))) ; 61 | return SPDR; 62 | } 63 | 64 | /** De-assert CS **/ 65 | #define DF_CS_inactive digitalWrite(SLAVESELECT,HIGH) 66 | /** Assert CS **/ 67 | #define DF_CS_active digitalWrite(SLAVESELECT,LOW) 68 | 69 | #endif /* SPI */ 70 | /** 71 | * @} 72 | **/ 73 | 74 | /** 75 | * @defgroup STATUS_REGISTER_FORMAT Status register format 76 | * @{ 77 | **/ 78 | /** 79 | * Ready/busy status is indicated using bit 7 of the status register. 80 | * If bit 7 is a 1, then the device is not busy and is ready to accept 81 | * the next command. If bit 7 is a 0, then the device is in a busy 82 | * state. 83 | **/ 84 | #define READY_BUSY 0x80 85 | /** 86 | * Result of the most recent Memory Page to Buffer Compare operation. 87 | * If this bit is equal to 0, then the data in the main memory page 88 | * matches the data in the buffer. If it's 1 then at least 1 byte in 89 | * the main memory page does not match the data in the buffer. 90 | **/ 91 | #define COMPARE 0x40 92 | /** 93 | * Bit 1 in the Status Register is used to provide information to the 94 | * user whether or not the sector protection has been enabled or 95 | * disabled, either by software-controlled method or 96 | * hardware-controlled method. 1 means that the sector protection has 97 | * been enabled and 0 that it has been disabled. 98 | **/ 99 | #define PROTECT 0x02 100 | /** 101 | * Bit 0 indicates wether the page size of the main memory array is 102 | * configured for "power of 2" binary page size (512 bytes) (bit=1) or 103 | * standard DataFlash page size (528 bytes) (bit=0). 104 | **/ 105 | #define PAGE_SIZE 0x01 106 | /** 107 | * Bits 5, 4, 3 and 2 indicates the device density. The decimal value 108 | * of these four binary bits does not equate to the device density; the 109 | * four bits represent a combinational code relating to differing 110 | * densities of DataFlash devices. The device density is not the same 111 | * as the density code indicated in the JEDEC device ID information. 112 | * The device density is provided only for backward compatibility. 113 | **/ 114 | #define DEVICE_DENSITY 0x2C 115 | /** 116 | * @} 117 | **/ 118 | 119 | /** 120 | * @brief at45db161d module 121 | * @todo 122 | * - TESTS! 123 | * - Protection and Security Commands 124 | * - Auto Page Rewrite through Buffer 1 125 | * - Auto Page Rewrite through Buffer 2 126 | **/ 127 | class ATD45DB161D 128 | { 129 | public: 130 | /** 131 | * @brief ID structure 132 | * This structure contains various informations about the 133 | * dataflash chip being used. 134 | **/ 135 | struct ID 136 | { 137 | uint8_t manufacturer; /**< Manufacturer id **/ 138 | uint8_t device[2]; /**< Device id **/ 139 | uint8_t extendedInfoLength; /**< Extended device information string length **/ 140 | }; 141 | static const uint16_t pageSize=528; 142 | static const uint16_t pageSizeBinary=512; 143 | 144 | public: 145 | /** CTOR **/ 146 | ATD45DB161D(); 147 | /** DTOR **/ 148 | ~ATD45DB161D(); 149 | 150 | /** Setup SPI and pinout **/ 151 | void Init(); 152 | 153 | /** 154 | * Read status register 155 | * @return The content of the status register 156 | * **/ 157 | uint8_t ReadStatusRegister(); 158 | 159 | /** 160 | * Read Manufacturer and Device ID 161 | * @note if id.extendedInfoLength is not equal to zero, 162 | * successive calls to spi_transfer(0xff) will return 163 | * the extended device information string bytes. 164 | * @param id Pointer to the ID structure to initialize 165 | **/ 166 | void ReadManufacturerAndDeviceID(struct ATD45DB161D::ID *id); 167 | 168 | /** 169 | * A main memory page read allows the user to read data directly from 170 | * any one of the 4096 pages in the main memory, bypassing both of the 171 | * data buffers and leaving the contents of the buffers unchanged. 172 | * @param page Page of the main memory to read 173 | * @param offset Starting byte address within the page 174 | **/ 175 | void ReadMainMemoryPage(uint16_t page, uint16_t offset); 176 | 177 | /** 178 | * Sequentially read a continuous stream of data. 179 | * @param page Page of the main memory where the sequential read will start 180 | * @param offset Starting byte address within the page 181 | * @param low If true the read operation will be performed in low speed mode (and in high speed mode if it's false). 182 | * @note The legacy mode is not currently supported 183 | * @warning UNTESTED 184 | **/ 185 | void ContinuousArrayRead(uint16_t page, uint16_t offset, uint8_t low); 186 | 187 | /** 188 | * Read the content of one of the SRAM data buffers (in low or high speed mode). 189 | * @param bufferNum Buffer to read (1 or 2) 190 | * @param offset Starting byte within the buffer 191 | * @param low If true the read operation will be performed in low speed mode (and in high speed mode if it's false). 192 | **/ 193 | void BufferRead(uint8_t bufferNum, uint16_t offset, uint8_t low); 194 | 195 | /** 196 | * Write data to one of the SRAM data buffers. Any further call to 197 | * spi_tranfer will return bytes contained in the data buffer until 198 | * a low-to-high transition is detected on the CS pin. If the end of 199 | * the data buffer is reached, the device will wrap around back to the 200 | * beginning of the buffer. 201 | * @param bufferNum Buffer to read (1 or 2) 202 | * @param offset Starting byte within the buffer 203 | **/ 204 | void BufferWrite(uint8_t bufferNum, uint16_t offset); 205 | 206 | /** 207 | * Transfer data from buffer 1 or 2 to main memory page. 208 | * @param bufferNum Buffer to use (1 or 2) 209 | * @param page Page where the content of the buffer will transfered 210 | * @param erase If set the page will be first erased before the buffer transfer. 211 | * @note If erase is equal to zero, the page must have been previously erased using one of the erase command (Page or Block Erase). 212 | **/ 213 | void BufferToPage(uint8_t bufferNum, uint16_t page, uint8_t erase); 214 | 215 | /** 216 | * Transfer a page of data from main memory to buffer 1 or 2. 217 | * @param page Main memory page to transfer 218 | * @param buffer Buffer (1 or 2) where the data will be written 219 | **/ 220 | void PageToBuffer(uint16_t page, uint8_t bufferNum); 221 | 222 | /** 223 | * Erase a page in the main memory array. 224 | * @param page Page to erase 225 | * @warning UNTESTED 226 | **/ 227 | void PageErase(uint16_t page); 228 | 229 | /** 230 | * Erase a block of eight pages at one time. 231 | * @param block Index of the block to erase 232 | * @warning UNTESTED 233 | **/ 234 | void BlockErase(uint16_t block); 235 | 236 | /** 237 | * Erase a sector in main memory. There are 16 sector on the 238 | * at45db161d and only one can be erased at one time. 239 | * @param sector Sector to erase 240 | * @warning UNTESTED 241 | **/ 242 | void SectoreErase(uint8_t sector); 243 | 244 | /** 245 | * Erase the entire chip memory. Sectors proteced or locked down will 246 | * not be erased. 247 | * @warning UNTESTED 248 | **/ 249 | void ChipErase(); 250 | 251 | /** 252 | * This a combination of Buffer Write and Buffer to Page with 253 | * Built-in Erase. 254 | * @note You must call EndAndWait in order to start transfering data from buffer to page 255 | * @param page Page where the content of the buffer will transfered 256 | * @param offset Starting byte address within the buffer 257 | * @param bufferNum Buffer to use (1 or 2) 258 | * @warning UNTESTED 259 | **/ 260 | void BeginPageWriteThroughBuffer(uint16_t page, uint16_t offset, uint8_t bufferNum); 261 | 262 | /** 263 | * Perform a low-to-high transition on the CS pin and then poll 264 | * the status register to check if the dataflash is busy. 265 | **/ 266 | void EndAndWait(); 267 | 268 | /** 269 | * Compare a page of data in main memory to the data in buffer 1 or 2. 270 | * @param page Page to test 271 | * @param bufferNum Buffer number 272 | * @return 273 | * - 1 if the page and the buffer contains the same data 274 | * - 0 else 275 | * @warning UNTESTED 276 | **/ 277 | int8_t ComparePageToBuffer(uint16_t page, uint8_t bufferNum); 278 | 279 | /** 280 | * Put the device into the lowest power consumption mode. 281 | * Once the device has entered the Deep Power-down mode, all 282 | * instructions are ignored except the Resume from Deep 283 | * Power-down command. 284 | * @warning UNTESTED 285 | **/ 286 | void DeepPowerDown(); 287 | 288 | /** 289 | * Takes the device out of Deep Power-down mode. 290 | * @warning UNTESTED 291 | **/ 292 | void ResumeFromDeepPowerDown(); 293 | 294 | private: 295 | /* Nothing atm but who knows... */ 296 | }; 297 | 298 | /** 299 | * @} 300 | **/ 301 | 302 | #endif /* AT45DB161D_H */ 303 | -------------------------------------------------------------------------------- /R+D/at45db161d/at45db161d_commands.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file at45db161d_commands.h 3 | * @brief AT45DB161D commands opcodes 4 | **/ 5 | #ifndef AT45DB161D_COMMANDS_H 6 | #define AT45DB161D_COMMANDS_H 7 | 8 | /** 9 | * @defgroup AT45DB161D_commands AT45DB161D commands opcodes 10 | * @{ 11 | **/ 12 | 13 | /** 14 | * @defgroup Read_commands Read commands 15 | * @{ 16 | **/ 17 | /** Main Memory Page Read */ 18 | #define AT45DB161D_PAGE_READ 0xD2 19 | /** Continuous Array Read (Low Frequency) **/ 20 | #define AT45DB161D_CONTINUOUS_READ_LOW_FREQ 0x03 21 | /** Continuous Array Read (High Frequency) **/ 22 | #define AT45DB161D_CONTINUOUS_READ_HIGH_FREQ 0x0B 23 | /** Buffer 1 Read (Low Frequency) **/ 24 | #define AT45DB161D_BUFFER_1_READ_LOW_FREQ 0xD1 25 | /** Buffer 2 Read (Low Frequency) **/ 26 | #define AT45DB161D_BUFFER_2_READ_LOW_FREQ 0xD3 27 | /** Buffer 1 Read **/ 28 | #define AT45DB161D_BUFFER_1_READ 0xD4 29 | /** Buffer 2 Read **/ 30 | #define AT45DB161D_BUFFER_2_READ 0xD6 31 | /** 32 | * @} 33 | **/ 34 | 35 | /** 36 | * @defgroup Program_Erase_commands Program and Erase commands 37 | * @{ 38 | **/ 39 | /** Buffer 1 Write **/ 40 | #define AT45DB161D_BUFFER_1_WRITE 0x84 41 | /** Buffer 2 Write **/ 42 | #define AT45DB161D_BUFFER_2_WRITE 0x87 43 | /** Buffer 1 to Main Memory Page Program with Built-in Erase **/ 44 | #define AT45DB161D_BUFFER_1_TO_PAGE_WITH_ERASE 0x83 45 | /** Buffer 2 to Main Memory Page Program with Built-in Erase **/ 46 | #define AT45DB161D_BUFFER_2_TO_PAGE_WITH_ERASE 0x86 47 | /** Buffer 1 to Main Memory Page Program without Built-in Erase **/ 48 | #define AT45DB161D_BUFFER_1_TO_PAGE_WITHOUT_ERASE 0x88 49 | /** Buffer 2 to Main Memory Page Program without Built-in Erase **/ 50 | #define AT45DB161D_BUFFER_2_TO_PAGE_WITHOUT_ERASE 0x89 51 | /** Page Erase **/ 52 | #define AT45DB161D_PAGE_ERASE 0x81 53 | /** Block Erase **/ 54 | #define AT45DB161D_BLOCK_ERASE 0x50 55 | /** Sector Erase **/ 56 | #define AT45DB161D_SECTOR_ERASE 0x7C 57 | /** Chip Erase Sequence **/ 58 | #define AT45DB161D_CHIP_ERASE_0 0xC7 59 | #define AT45DB161D_CHIP_ERASE_1 0x94 60 | #define AT45DB161D_CHIP_ERASE_2 0x80 61 | #define AT45DB161D_CHIP_ERASE_3 0x9A 62 | /** Main Memory Page Program Through Buffer 1 **/ 63 | #define AT45DB161D_PAGE_THROUGH_BUFFER_1 0x82 64 | /** Main Memory Page Program Through Buffer 2 **/ 65 | #define AT45DB161D_PAGE_THROUGH_BUFFER_2 0x85 66 | /** 67 | * @} 68 | **/ 69 | 70 | /** 71 | * @defgroup ProtectionSecurity_Commands Protection and Security Commands 72 | * @warning UNIMPLEMENTED 73 | * @{ 74 | **/ 75 | #ifdef AT45DB161D_EXPERT_MODE 76 | /* Use the following commands at your own risk ! */ 77 | /** Enable Sector Protection **/ 78 | #define AT45DB161D_ENABLE_SECTOR_PROTECTION_0 0x3D 79 | #define AT45DB161D_ENABLE_SECTOR_PROTECTION_1 0x2A 80 | #define AT45DB161D_ENABLE_SECTOR_PROTECTION_2 0x7F 81 | #define AT45DB161D_ENABLE_SECTOR_PROTECTION_3 0xA9 82 | /** Disable Sector Protection **/ 83 | #define AT45DB161D_DISABLE_SECTOR_PROTECTION_0 0x3D 84 | #define AT45DB161D_DISABLE_SECTOR_PROTECTION_1 0x2A 85 | #define AT45DB161D_DISABLE_SECTOR_PROTECTION_2 0x7F 86 | #define AT45DB161D_DISABLE_SECTOR_PROTECTION_3 0x9A 87 | /** Erase Sector Protection Register **/ 88 | #define AT45DB161D_ERASE_SECTOR_PROTECTION_REGISTER_0 0x3D 89 | #define AT45DB161D_ERASE_SECTOR_PROTECTION_REGISTER_0 0x2A 90 | #define AT45DB161D_ERASE_SECTOR_PROTECTION_REGISTER_0 0x7F 91 | #define AT45DB161D_ERASE_SECTOR_PROTECTION_REGISTER_0 0xCF 92 | /** Program Sector Protection Register **/ 93 | #define AT45DB161D_PROGRAM_SECTOR_PROTECTION_REGISTER_0 0x3D 94 | #define AT45DB161D_PROGRAM_SECTOR_PROTECTION_REGISTER_1 0x2A 95 | #define AT45DB161D_PROGRAM_SECTOR_PROTECTION_REGISTER_2 0x7F 96 | #define AT45DB161D_PROGRAM_SECTOR_PROTECTION_REGISTER_3 0xFC 97 | /** Sector Lockdown **/ 98 | #define AT45DB161D_SECTOR_LOCKDOWN_0 0X3D 99 | #define AT45DB161D_SECTOR_LOCKDOWN_1 0x2A 100 | #define AT45DB161D_SECTOR_LOCKDOWN_2 0x7F 101 | #define AT45DB161D_SECTOR_LOCKDOWN_3 0x30 102 | /** Program Security Register **/ 103 | #define AT45DB161D_PROGRAM_SECURITY_REGISTER_0 0x9B 104 | #define AT45DB161D_PROGRAM_SECURITY_REGISTER_1 0x00 105 | #define AT45DB161D_PROGRAM_SECURITY_REGISTER_2 0x00 106 | #define AT45DB161D_PROGRAM_SECURITY_REGISTER_3 0x00 107 | #endif /* AT45DB161D_EXPERT_MODE */ 108 | 109 | /** Read Sector Protection Register **/ 110 | #define AT45DB161D_READ_SECTOR_PROTECTION_REGISTER 0x32 111 | /** Read Sector Lockdown Register **/ 112 | #define AT45DB161D_READ_SECTOR_LOCKDOWN_REGISTER 35H 113 | /** Read Security Register **/ 114 | #define AT45DB161D_READ_SECURITY_REGISTER 0x77 115 | /** 116 | * @} 117 | **/ 118 | 119 | /** 120 | * @defgroup Additional_commands Additional Commands 121 | * @{ 122 | **/ 123 | /** Main Memory Page to Buffer 1 Transfer **/ 124 | #define AT45DB161D_TRANSFER_PAGE_TO_BUFFER_1 0x53 125 | /** Main Memory Page to Buffer 2 Transfer **/ 126 | #define AT45DB161D_TRANSFER_PAGE_TO_BUFFER_2 0x55 127 | /** Main Memory Page to Buffer 1 Compare **/ 128 | #define AT45DB161D_COMPARE_PAGE_TO_BUFFER_1 0x60 129 | /** Main Memory Page to Buffer 2 Compare **/ 130 | #define AT45DB161D_COMPARE_PAGE_TO_BUFFER_2 0x61 131 | /** Auto Page Rewrite through Buffer 1 **/ 132 | #define AT45DB161D_AUTO_PAGE_REWRITE_THROUGH_BUFFER_1 0x58 133 | /** Auto Page Rewrite through Buffer 2 **/ 134 | #define AT45DB161D_AUTO_PAGE_REWRITE_THROUGH_BUFFER_2 0x59 135 | /** Deep Power-down **/ 136 | #define AT45DB161D_DEEP_POWER_DOWN 0xB9 137 | /** Resume from Deep Power-down **/ 138 | #define AT45DB161D_RESUME_FROM_DEEP_POWER_DOWN 0xAB 139 | /** Status Register Read **/ 140 | #define AT45DB161D_STATUS_REGISTER_READ 0xD7 141 | /** Manufacturer and Device ID Read **/ 142 | #define AT45DB161D_READ_MANUFACTURER_AND_DEVICE_ID 0x9F 143 | /** 144 | * @} 145 | **/ 146 | 147 | /** 148 | * @defgroup Legacy_commands Legacy Commands 149 | * @{ 150 | **/ 151 | /** Buffer 1 Read **/ 152 | #define AT45DB161D_BUFFER_1_READ_LEGACY 0X54 153 | /** Buffer 2 Read **/ 154 | #define AT45DB161D_BUFFER_2_READ_LEGACY 0x56 155 | /** Main Memory Page Read **/ 156 | #define AT45DB161D_PAGE_READ_LEGACY 0x52 157 | /** Continuous Array Read **/ 158 | #define AT45DB161D_CONTINUOUS_READ_LEGACY 0x68 159 | /** Status Register Read **/ 160 | #define AT45DB161D_STATUS_REGISTER_READ_LEGACY 0x57 161 | /** 162 | * @} 163 | **/ 164 | 165 | /** 166 | * @} 167 | **/ 168 | 169 | #endif /* AT45DB161D_COMMANDS_H */ 170 | -------------------------------------------------------------------------------- /R+D/at45db161d/examples/DataFlash_example1/DataFlash_example1.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | ATD45DB161D DF; 4 | uint8_t data; 5 | 6 | void setup() 7 | { 8 | pinMode(10,OUTPUT); 9 | DF.Init(); 10 | Serial.begin(115200); 11 | 12 | 13 | } 14 | 15 | void loop() 16 | { 17 | 18 | //Grabo en el buffer 1 10 datos, empezando desde posicion 0 19 | DF.BufferWrite(1,0); 20 | for (int i=1;i<540;++i) 21 | { 22 | spi_transfer(10); //envio datos por SPI 23 | /* 24 | Serial.print("Grabado="); 25 | Serial.println(i); 26 | */ 27 | if (i>=(DF.pageSizeBinary-1)) break; 28 | 29 | } 30 | spi_transfer(1); //Fin de datos, caracter limitador 0 31 | DF.EndAndWait(); 32 | 33 | //Leo los datos del buffer y los saco por serie. 34 | DF.BufferRead(1,0,1); 35 | data=spi_transfer(0xFF); 36 | int i=0; 37 | while (data !=1) 38 | { 39 | /* 40 | Serial.print("Leido="); 41 | Serial.print(data); 42 | Serial.print(","); 43 | Serial.println(++i); 44 | */ 45 | data=spi_transfer(0xFF); 46 | } 47 | DF.EndAndWait(); 48 | 49 | Serial.println(DF.ReadStatusRegister(),BIN); 50 | 51 | for(;;) 52 | {} 53 | 54 | } 55 | 56 | 57 | -------------------------------------------------------------------------------- /R+D/at45db161d/examples/DataFlash_example2/DataFlash_example2.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | ATD45DB161D DF; 4 | uint8_t data; 5 | 6 | void setup() 7 | { 8 | pinMode(10,OUTPUT); 9 | DF.Init(); 10 | Serial.begin(115200); 11 | 12 | 13 | } 14 | 15 | void loop() 16 | { 17 | 18 | //Grabo en el buffer 1 10 datos, empezando desde posicion 0 19 | unsigned long t0=micros(); 20 | DF.BufferWrite(1,0); 21 | byte counter; 22 | for (int i=1;i<540;++i) 23 | { 24 | spi_transfer(++counter); //envio datos por SPI 25 | /* 26 | Serial.print("Grabado="); 27 | Serial.println(i); 28 | */ 29 | if (i>=(DF.pageSizeBinary-2)) break; 30 | 31 | } 32 | spi_transfer(99); 33 | spi_transfer(1); //Fin de datos, caracter limitador 0 34 | DF.EndAndWait(); 35 | 36 | unsigned long tf=micros()-t0; 37 | Serial.print("Tiempo en enviar una pagina="); 38 | Serial.println(tf/1000.0); 39 | 40 | t0=micros(); 41 | //Lo grabo en la memoria 42 | DF.BufferToPage(1,4095,1); 43 | tf=micros()-t0; 44 | Serial.print("Tiempo en grabar del buffer a una pagina="); 45 | Serial.println(tf/1000.0); 46 | 47 | //Leo los datos de la pagina y los saco por serie. 48 | DF.PageToBuffer(4095,2); 49 | DF.BufferRead(2,0,1); 50 | for (int i=0; i 9 | #include 10 | 11 | #define nMsgCAN 5 12 | 13 | ATD45DB161D DF; 14 | uint8_t data; 15 | uint8_t RXcounter; 16 | uint8_t offset; 17 | 18 | void setup() 19 | { 20 | pinMode(10,OUTPUT); 21 | DF.Init(); 22 | CAN.begin(100); 23 | Serial.begin(115200); 24 | } 25 | 26 | void loop() 27 | { 28 | 29 | 30 | if ( (CAN.CheckNew()) && (RXcounter=nMsgCAN) 54 | { 55 | DF.BufferWrite(1,offset); 56 | spi_transfer(0xFF); //Start/Finish byte 57 | //Read buffer 1 data 58 | DF.BufferRead(1,0,1); 59 | for(int i=0;i<(nMsgCAN*10)+1;i++) 60 | { 61 | data=spi_transfer(0xFF); 62 | Serial.print("Dato "); 63 | Serial.print(i); 64 | Serial.print(","); 65 | Serial.println(data); 66 | 67 | } 68 | DF.EndAndWait(); 69 | RXcounter=0; 70 | offset=0; 71 | } 72 | 73 | 74 | } 75 | 76 | 77 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Please find all the code related with the SECUduino Project 2 | -------------------------------------------------------------------------------- /Schematics/ESQUEMA SECUduino 2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IgorReal/SECUduino/1d873ff874f276ea3889af50efd877d6c15a5803/Schematics/ESQUEMA SECUduino 2.pdf -------------------------------------------------------------------------------- /Schematics/ESQUEMA SECUduino.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IgorReal/SECUduino/1d873ff874f276ea3889af50efd877d6c15a5803/Schematics/ESQUEMA SECUduino.pdf --------------------------------------------------------------------------------