Changing from softAp to Station mode ESP8266

How can I change ESP8266 mode from softAP to Station through coding?

I want esp8266 to start in AP mode so we can provide the the Wi-Fi details to which I want the esp8266 to get connected.

further it must also get disconnect from the Wi-Fi on the press of a button and start again in softAP mode.

Have a look at this:

I know can use this library. But I dont want to use it. I want to do it by myself. I tried this

#include <EEPROM.h>

const int EEPROM_MIN_ADDR = 0;
const int EEPROM_MAX_ADDR = 511;


boolean eeprom_is_addr_ok(int addr) {
  return ((addr >= EEPROM_MIN_ADDR) && (addr <= EEPROM_MAX_ADDR));
}


boolean eeprom_write_bytes(int startAddr, const byte* array, int numBytes) {
  // counter
  int i;

  if (!eeprom_is_addr_ok(startAddr) || !eeprom_is_addr_ok(startAddr + numBytes)) {
    return false;
  }

  for (i = 0; i < numBytes; i++) {
    EEPROM.write(startAddr + i, array[i]);
  }

  return true;
}

boolean eeprom_write_string(int addr, const char* string) {

  int numBytes; 
  numBytes = strlen(string) + 1;

  return eeprom_write_bytes(addr, (const byte*)string, numBytes);
}

boolean eeprom_read_string(int addr, char* buffer, int bufSize) {
  byte ch; // byte read from eeprom
  int bytesRead; 
  
  if (!eeprom_is_addr_ok(addr)) { 
    return false;
  }

  if (bufSize == 0) {
    return false;
  }


  if (bufSize == 1) {
    buffer[0] = 0;
    return true;
  }

  bytesRead = 0; // initialize byte counter
  ch = EEPROM.read(addr + bytesRead);
  buffer[bytesRead] = ch; 
  bytesRead++; 

  while ( (ch != 0x00) && (bytesRead < bufSize) && ((addr + bytesRead) <= EEPROM_MAX_ADDR) ) {
    ch = EEPROM.read(addr + bytesRead);
    buffer[bytesRead] = ch; 
    bytesRead++; 
  }

  if ((ch != 0x00) && (bytesRead >= 1)) {
    buffer[bytesRead - 1] = 0;
  }

  return true;
}

String read_StringEE(int Addr, int length)
{
  
  char cbuff[length+1];
  eeprom_read_string(Addr, cbuff, length+1);
  
  String stemp(cbuff);
  return stemp;
  
}

bool write_StringEE(int Addr, String input)
{
    char cbuff[input.length()+1];//Finds length of string to make a buffer
    input.toCharArray(cbuff,input.length()+1);//Converts String into character array
    return eeprom_write_string(Addr,cbuff);//Saves String
}




#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>


IPAddress local_IP(192,168,4,2);
IPAddress gateway(192,168,4,1);
IPAddress subnet(255,255,255,0);

ESP8266WebServer server(80);

void clientCfg();
void APcfg();

const char* ssid = "OFFLINE";
const char* pswd = "";
//const int channel = 9;
int length = 16;
int ssidAdd = 0;
int passAdd = 18;

String setting;
String user;
String pass;

char* ssid1;
char* pass1;

const char* ssid2;
const char* pass2;

const char* pass3;
const char* ssid3;

boolean state;


void setup()
{
  EEPROM.begin(512);
  
  /*for (int i=0; i<512; i++)
  {
    EEPROM.write(i, 0);
    EEPROM.commit();
  }*/
  
  Serial.begin(9600);
  
  if(EEPROM.read(0)==0 && EEPROM.read(18)==0)
  {
    state = false;
  }
  
  else
  {
    state = true;
  }
 
  if(state==false)
  {
    APcfg();
  }
                
  if(state==true)
  {
    clientCfg();
  }
  
}
  
void loop() 
{
  server.handleClient();
}

void APcfg()
{
      delay(100);
    //WiFi.mode(WIFI_AP);
    delay(10);
    
    Serial.print("Configuring SoftAP Configuration...");
    Serial.println(WiFi.softAPConfig(local_IP, gateway, subnet)? "Ready" : "Failed!");

    Serial.println();
    delay(10);
    
    Serial.print("Setting SoftAP...");
    Serial.println(WiFi.softAP(ssid, pswd)? "Ready": "Failed!");
    delay(10);

    Serial.println();
    Serial.print("connect to the IP Address given below...");
    Serial.println(WiFi.softAPIP());
    delay(10);

    setting = "<form action=\"http://192.168.4.2/iron_fist\" method = \"post\">"
                "New Password:
"
                 "<input type=\"text\" placeholder=\"WiFi\" name =\"user\">"    
                 "
"
                 "
"
                 "<input type=\"password\" placeholder=\"Enter Password\" name =\"psw\">"
                 "
"
                 "
"
                 "<input type=\"submit\" value=\"Submit\">"
                 "</form> ";

                 server.on("/", [] () {server.send(200, "text/html", setting);});
                 server.on("/iron_fist", ironfist);

                 server.begin();
}

void clientCfg()
{
       //delay(300);
     eeprom_read_string(ssidAdd,ssid1,length);
     ssid2 = ssid1;

     //delay(300);
    
     eeprom_read_string(passAdd,pass1,length);
     pass2 = pass1;

     delay(300);

     //WiFi.mode(WIFI_AP_STA);
     delay(300);
     Serial.println();
     Serial.print("connecting to.....");
     Serial.println(ssid2);

     delay(1000);
     WiFi.begin(ssid2,pass2);

     while(WiFi.status() != WL_CONNECTED)
     {
      Serial.print(".");
      delay(500);
     }

      Serial.println();
      Serial.print(".....Connect to the WiFi and open the IP address given below.....");
      Serial.println("IP address:-");
      
      //delay(1000);
      
      Serial.println(WiFi.localIP());
      
      //delay(1000);
      
     server.on("/", client);
}

void ironfist()
{
  if(server.args()!=NULL)
  {
    for (uint8_t i=0; i<server.args(); i++)
    {
      if(server.argName(i)=="user")
      {
        Serial.println();
        Serial.println("SSID Received: -");
        user = server.arg(i);
        Serial.print(user);
        ssid3 = user.c_str();

        if (user=="")
        {
          
        }
        else
        {
          eeprom_write_string(ssidAdd,ssid3);
          EEPROM.commit();
          Serial.println("SSID stored");
        }
        
      }
      
      if(server.argName(i)=="psw")
      {
        Serial.println();
        Serial.println("Password Received: -");
        pass = server.arg(i);
        Serial.print(pass);
        pass3 = pass.c_str();

        eeprom_write_string(passAdd,pass3);
        EEPROM.end();
        Serial.println("Password Stored");
      }

    }
    ESP.restart();
  }
}

void client()
{
  server.send(200, "text/plain", "Hello world!");
}

it worked completely fine as SoftAP but shows Exception (29) when it has to connect to the WiFi.
Below is the error

Exception (29):
epc1=0x40202178 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000

ctx: cont 
sp: 3fff03e0 end: 3fff0610 offset: 01a0

>>>stack>>>
3fff0580:  feefeffe feefeffe 3fff1744 40201cf9  
3fff0590:  00000000 00000001 00000010 feefeffe  
3fff05a0:  00000000 400042db feefeffe 3ffef5dc  
3fff05b0:  3ffeeaf8 3ffef430 3ffe8350 40202397  
3fff05c0:  00000001 feefeffe feefeffe 402062d4  
3fff05d0:  40205629 3ffef430 00000200 3ffef5dc  
3fff05e0:  3fffdad0 3ffef430 3ffeeae0 402024b6  
3fff05f0:  feefeffe 00000000 3ffef5d4 402063e0  
3fff0600:  feefeffe feefeffe 3ffef5f0 40100718  
<<<stack<<<

I tried to find what is Exception (29) using ESP Exception decoder it said

Exception 29: StoreProhibited: A store referenced a page mapped with an attribute that does not permit stores

But I am unable to solve this.

Be sure that these lines are working the way you expected...

eeprom_read_string(ssidAdd,ssid1,length);
eeprom_read_string(passAdd,pass1,length);

Where are ssid1 and pass1 actually pointing when you make these calls?

I think if you load these pointers with addresses of actual declared memory this code will probably work like you expected. They initialize to zero and the processor probably does not like you writing your ssid and password there after you read them from eeprom.

e.g.

char buff1[18];
char buff2[18];

ssid1 = buff1;
pass1 = buff2;

P.S. Doing this might be a good learning experience but after that.... I suggest using the Library.

It worked the way you told me. I guess I am still not good with the pointers, if you have any advice to give, it would be great for me.

Thank you for the help.